Commit 6b554b49 authored by Alexander Viro's avatar Alexander Viro Committed by Linus Torvalds

[PATCH] mtd fixes

Assorted mtd fixes.
	a) NULL noise removal
	b) %p pointer instead of %x (int)pointer in printks
	c) missed iovec->kvec replacements (basically, fixing merge problems)
	d) fixed type for (unused) last argument in doc_{read,write}_ecc()
	e) sanitized some comparisons.
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent cddeea3c
...@@ -1415,7 +1415,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr) ...@@ -1415,7 +1415,7 @@ int cfi_amdstd_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
ofs = instr->addr; ofs = instr->addr;
len = instr->len; len = instr->len;
ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, 0); ret = cfi_amdstd_varsize_frob(mtd, do_erase_oneblock, ofs, len, NULL);
if (ret) if (ret)
return ret; return ret;
......
...@@ -58,7 +58,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -58,7 +58,7 @@ static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); size_t *retlen, u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel); size_t *retlen, const u_char *buf, u_char *eccbuf, struct nand_oobinfo *oobsel);
static int doc_writev_ecc(struct mtd_info *mtd, const struct iovec *vecs, static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen, unsigned long count, loff_t to, size_t *retlen,
u_char *eccbuf, struct nand_oobinfo *oobsel); u_char *eccbuf, struct nand_oobinfo *oobsel);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
...@@ -632,7 +632,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -632,7 +632,7 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
size_t * retlen, u_char * buf) size_t * retlen, u_char * buf)
{ {
/* Just a special case of doc_read_ecc */ /* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, 0); return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
} }
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
...@@ -790,7 +790,7 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -790,7 +790,7 @@ static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t * retlen, const u_char * buf) size_t * retlen, const u_char * buf)
{ {
char eccbuf[6]; char eccbuf[6];
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, 0); return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
} }
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
...@@ -979,7 +979,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, ...@@ -979,7 +979,7 @@ static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
return 0; return 0;
} }
static int doc_writev_ecc(struct mtd_info *mtd, const struct iovec *vecs, static int doc_writev_ecc(struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen, unsigned long count, loff_t to, size_t *retlen,
u_char *eccbuf, struct nand_oobinfo *oobsel) u_char *eccbuf, struct nand_oobinfo *oobsel)
{ {
......
...@@ -38,9 +38,11 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len, ...@@ -38,9 +38,11 @@ static int doc_read(struct mtd_info *mtd, loff_t from, size_t len,
static int doc_write(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf); size_t *retlen, const u_char *buf);
static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len, static int doc_read_ecc(struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel); size_t *retlen, u_char *buf, u_char *eccbuf,
struct nand_oobinfo *oobsel);
static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len, static int doc_write_ecc(struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel); size_t *retlen, const u_char *buf, u_char *eccbuf,
struct nand_oobinfo *oobsel);
static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len, static int doc_read_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
size_t *retlen, u_char *buf); size_t *retlen, u_char *buf);
static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len, static int doc_write_oob(struct mtd_info *mtd, loff_t ofs, size_t len,
...@@ -404,11 +406,12 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len, ...@@ -404,11 +406,12 @@ static int doc_read (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf) size_t *retlen, u_char *buf)
{ {
/* Just a special case of doc_read_ecc */ /* Just a special case of doc_read_ecc */
return doc_read_ecc(mtd, from, len, retlen, buf, NULL, 0); return doc_read_ecc(mtd, from, len, retlen, buf, NULL, NULL);
} }
static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len, static int doc_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel) size_t *retlen, u_char *buf, u_char *eccbuf,
struct nand_oobinfo *oobsel)
{ {
int i, ret; int i, ret;
volatile char dummy; volatile char dummy;
...@@ -530,11 +533,12 @@ static int doc_write (struct mtd_info *mtd, loff_t to, size_t len, ...@@ -530,11 +533,12 @@ static int doc_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf) size_t *retlen, const u_char *buf)
{ {
char eccbuf[6]; char eccbuf[6];
return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, 0); return doc_write_ecc(mtd, to, len, retlen, buf, eccbuf, NULL);
} }
static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len, static int doc_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf, u_char *eccbuf, int oobsel) size_t *retlen, const u_char *buf, u_char *eccbuf,
struct nand_oobinfo *oobsel)
{ {
int i,ret = 0; int i,ret = 0;
volatile char dummy; volatile char dummy;
......
...@@ -167,8 +167,8 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate) ...@@ -167,8 +167,8 @@ static u16 INFTL_findfreeblock(struct INFTLrecord *inftl, int desperate)
u16 pot = inftl->LastFreeEUN; u16 pot = inftl->LastFreeEUN;
int silly = inftl->nb_blocks; int silly = inftl->nb_blocks;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findfreeblock(inftl=%p,"
"desperate=%d)\n", (int)inftl, desperate); "desperate=%d)\n", inftl, desperate);
/* /*
* Normally, we force a fold to happen before we run out of free * Normally, we force a fold to happen before we run out of free
...@@ -210,8 +210,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned ...@@ -210,8 +210,8 @@ static u16 INFTL_foldchain(struct INFTLrecord *inftl, unsigned thisVUC, unsigned
struct inftl_oob oob; struct inftl_oob oob;
size_t retlen; size_t retlen;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=0x%x,thisVUC=%d," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_foldchain(inftl=%p,thisVUC=%d,"
"pending=%d)\n", (int)inftl, thisVUC, pendingblock); "pending=%d)\n", inftl, thisVUC, pendingblock);
memset(BlockMap, 0xff, sizeof(BlockMap)); memset(BlockMap, 0xff, sizeof(BlockMap));
memset(BlockDeleted, 0, sizeof(BlockDeleted)); memset(BlockDeleted, 0, sizeof(BlockDeleted));
...@@ -366,8 +366,8 @@ u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock) ...@@ -366,8 +366,8 @@ u16 INFTL_makefreeblock(struct INFTLrecord *inftl, unsigned pendingblock)
u16 ChainLength = 0, thislen; u16 ChainLength = 0, thislen;
u16 chain, EUN; u16 chain, EUN;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_makefreeblock(inftl=%p,"
"pending=%d)\n", (int)inftl, pendingblock); "pending=%d)\n", inftl, pendingblock);
for (chain = 0; chain < inftl->nb_blocks; chain++) { for (chain = 0; chain < inftl->nb_blocks; chain++) {
EUN = inftl->VUtable[chain]; EUN = inftl->VUtable[chain];
...@@ -428,8 +428,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block) ...@@ -428,8 +428,8 @@ static inline u16 INFTL_findwriteunit(struct INFTLrecord *inftl, unsigned block)
size_t retlen; size_t retlen;
int silly, silly2 = 3; int silly, silly2 = 3;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_findwriteunit(inftl=%p,"
"block=%d)\n", (int)inftl, block); "block=%d)\n", inftl, block);
do { do {
/* /*
...@@ -590,8 +590,8 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC) ...@@ -590,8 +590,8 @@ static void INFTL_trydeletechain(struct INFTLrecord *inftl, unsigned thisVUC)
struct inftl_bci bci; struct inftl_bci bci;
size_t retlen; size_t retlen;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_trydeletechain(inftl=%p,"
"thisVUC=%d)\n", (int)inftl, thisVUC); "thisVUC=%d)\n", inftl, thisVUC);
memset(BlockUsed, 0, sizeof(BlockUsed)); memset(BlockUsed, 0, sizeof(BlockUsed));
memset(BlockDeleted, 0, sizeof(BlockDeleted)); memset(BlockDeleted, 0, sizeof(BlockDeleted));
...@@ -709,8 +709,8 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block) ...@@ -709,8 +709,8 @@ static int INFTL_deleteblock(struct INFTLrecord *inftl, unsigned block)
size_t retlen; size_t retlen;
struct inftl_bci bci; struct inftl_bci bci;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_deleteblock(inftl=%p,"
"block=%d)\n", (int)inftl, block); "block=%d)\n", inftl, block);
while (thisEUN < inftl->nb_blocks) { while (thisEUN < inftl->nb_blocks) {
if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
...@@ -768,8 +768,8 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block, ...@@ -768,8 +768,8 @@ static int inftl_writeblock(struct mtd_blktrans_dev *mbd, unsigned long block,
struct inftl_oob oob; struct inftl_oob oob;
char *p, *pend; char *p, *pend;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=0x%x,block=%ld," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_writeblock(inftl=%p,block=%ld,"
"buffer=0x%x)\n", (int)inftl, block, (int)buffer); "buffer=%p)\n", inftl, block, buffer);
/* Is block all zero? */ /* Is block all zero? */
pend = buffer + SECTORSIZE; pend = buffer + SECTORSIZE;
...@@ -816,8 +816,8 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block, ...@@ -816,8 +816,8 @@ static int inftl_readblock(struct mtd_blktrans_dev *mbd, unsigned long block,
struct inftl_bci bci; struct inftl_bci bci;
size_t retlen; size_t retlen;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=0x%x,block=%ld," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: inftl_readblock(inftl=%p,block=%ld,"
"buffer=0x%x)\n", (int)inftl, block, (int)buffer); "buffer=%p)\n", inftl, block, buffer);
while (thisEUN < inftl->nb_blocks) { while (thisEUN < inftl->nb_blocks) {
if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) + if (MTD_READOOB(inftl->mbd.mtd, (thisEUN * inftl->EraseSize) +
......
...@@ -60,8 +60,7 @@ static int find_boot_record(struct INFTLrecord *inftl) ...@@ -60,8 +60,7 @@ static int find_boot_record(struct INFTLrecord *inftl)
struct INFTLPartition *ip; struct INFTLPartition *ip;
size_t retlen; size_t retlen;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=0x%x)\n", DEBUG(MTD_DEBUG_LEVEL3, "INFTL: find_boot_record(inftl=%p)\n", inftl);
(int)inftl);
/* /*
* Assume logical EraseSize == physical erasesize for starting the * Assume logical EraseSize == physical erasesize for starting the
...@@ -352,8 +351,8 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address, ...@@ -352,8 +351,8 @@ static int check_free_sectors(struct INFTLrecord *inftl, unsigned int address,
size_t retlen; size_t retlen;
int i; int i;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: check_free_sectors(inftl=%p,"
"address=0x%x,len=%d,check_oob=%d)\n", (int)inftl, "address=0x%x,len=%d,check_oob=%d)\n", inftl,
address, len, check_oob); address, len, check_oob);
for (i = 0; i < len; i += SECTORSIZE) { for (i = 0; i < len; i += SECTORSIZE) {
...@@ -388,8 +387,8 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block) ...@@ -388,8 +387,8 @@ int INFTL_formatblock(struct INFTLrecord *inftl, int block)
struct erase_info *instr = &inftl->instr; struct erase_info *instr = &inftl->instr;
int physblock; int physblock;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=0x%x," DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_formatblock(inftl=%p,"
"block=%d)\n", (int)inftl, block); "block=%d)\n", inftl, block);
memset(instr, 0, sizeof(struct erase_info)); memset(instr, 0, sizeof(struct erase_info));
...@@ -556,7 +555,7 @@ int INFTL_mount(struct INFTLrecord *s) ...@@ -556,7 +555,7 @@ int INFTL_mount(struct INFTLrecord *s)
int i; int i;
u8 *ANACtable, ANAC; u8 *ANACtable, ANAC;
DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=0x%x)\n", (int)s); DEBUG(MTD_DEBUG_LEVEL3, "INFTL: INFTL_mount(inftl=%p)\n", s);
/* Search for INFTL MediaHeader and Spare INFTL Media Header */ /* Search for INFTL MediaHeader and Spare INFTL Media Header */
if (find_boot_record(s) < 0) { if (find_boot_record(s) < 0) {
......
...@@ -286,7 +286,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev, ...@@ -286,7 +286,7 @@ static int __devinit ichxrom_init_one (struct pci_dev *pdev,
info->mtd->unlock = ichxrom_unlock; info->mtd->unlock = ichxrom_unlock;
} }
if (info->mtd->size > info->map.size) { if (info->mtd->size > info->map.size) {
printk(KERN_WARNING MOD_NAME " rom(%u) larger than window(%u). fixing...\n", printk(KERN_WARNING MOD_NAME " rom(%u) larger than window(%lu). fixing...\n",
info->mtd->size, info->map.size); info->mtd->size, info->map.size);
info->mtd->size = info->map.size; info->mtd->size = info->map.size;
} }
......
...@@ -511,7 +511,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file, ...@@ -511,7 +511,7 @@ static int mtd_ioctl(struct inode *inode, struct file *file,
} }
default: default:
DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %x)\n", cmd, MEMGETINFO); DEBUG(MTD_DEBUG_LEVEL0, "Invalid ioctl %x (MEMGETINFO = %lx)\n", cmd, (unsigned long)MEMGETINFO);
ret = -ENOTTY; ret = -ENOTTY;
} }
......
...@@ -651,11 +651,11 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf, ...@@ -651,11 +651,11 @@ static int __init find_media_headers(struct mtd_info *mtd, u_char *buf,
{ {
struct nand_chip *this = mtd->priv; struct nand_chip *this = mtd->priv;
struct doc_priv *doc = (void *)this->priv; struct doc_priv *doc = (void *)this->priv;
int offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift); unsigned offs, end = (MAX_MEDIAHEADER_SCAN << this->phys_erase_shift);
int ret; int ret;
size_t retlen; size_t retlen;
end = min(end, (int)mtd->size); // paranoia end = min(end, mtd->size); // paranoia
for (offs = 0; offs < end; offs += mtd->erasesize) { for (offs = 0; offs < end; offs += mtd->erasesize) {
ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf); ret = mtd->read(mtd, offs, mtd->oobblock, &retlen, buf);
if (retlen != mtd->oobblock) continue; if (retlen != mtd->oobblock) continue;
...@@ -696,8 +696,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, ...@@ -696,8 +696,8 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
struct doc_priv *doc = (void *)this->priv; struct doc_priv *doc = (void *)this->priv;
u_char *buf = this->data_buf; u_char *buf = this->data_buf;
struct NFTLMediaHeader *mh = (struct NFTLMediaHeader *) buf; struct NFTLMediaHeader *mh = (struct NFTLMediaHeader *) buf;
const int psize = 1 << this->page_shift; const unsigned psize = 1 << this->page_shift;
int blocks, maxblocks; unsigned blocks, maxblocks;
int offs, numheaders; int offs, numheaders;
if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) return 0; if (!(numheaders=find_media_headers(mtd, buf, "ANAND", 1))) return 0;
...@@ -715,7 +715,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, ...@@ -715,7 +715,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
//#endif //#endif
blocks = mtd->size >> this->phys_erase_shift; blocks = mtd->size >> this->phys_erase_shift;
maxblocks = min(32768, (int)mtd->erasesize - psize); maxblocks = min(32768U, mtd->erasesize - psize);
if (mh->UnitSizeFactor == 0x00) { if (mh->UnitSizeFactor == 0x00) {
/* Auto-determine UnitSizeFactor. The constraints are: /* Auto-determine UnitSizeFactor. The constraints are:
...@@ -726,7 +726,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, ...@@ -726,7 +726,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
mh->UnitSizeFactor = 0xff; mh->UnitSizeFactor = 0xff;
while (blocks > maxblocks) { while (blocks > maxblocks) {
blocks >>= 1; blocks >>= 1;
maxblocks = min(32768, (maxblocks << 1) + psize); maxblocks = min(32768U, (maxblocks << 1) + psize);
mh->UnitSizeFactor--; mh->UnitSizeFactor--;
} }
printk(KERN_WARNING "UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor); printk(KERN_WARNING "UnitSizeFactor=0x00 detected. Correct value is assumed to be 0x%02x.\n", mh->UnitSizeFactor);
...@@ -742,7 +742,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd, ...@@ -742,7 +742,7 @@ static inline int __init nftl_partscan(struct mtd_info *mtd,
mtd->erasesize <<= (0xff - mh->UnitSizeFactor); mtd->erasesize <<= (0xff - mh->UnitSizeFactor);
printk(KERN_INFO "Setting virtual erase size to %d\n", mtd->erasesize); printk(KERN_INFO "Setting virtual erase size to %d\n", mtd->erasesize);
blocks = mtd->size >> this->bbt_erase_shift; blocks = mtd->size >> this->bbt_erase_shift;
maxblocks = min(32768, (int)mtd->erasesize - psize); maxblocks = min(32768U, mtd->erasesize - psize);
} }
if (blocks > maxblocks) { if (blocks > maxblocks) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment