diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-23 19:56:50 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-10-23 19:56:50 +0400 |
commit | 6e506079c80c96dc9f813491231433762fbad91d (patch) | |
tree | ea03c201049d60f0b366657f01603f54e17c11e0 /drivers | |
parent | f3344c54cee4c446a39d046e47707ed9d259f72c (diff) | |
parent | 5a37cf19efcceae14c2078449e35b9f4eb3e63e4 (diff) | |
download | linux-6e506079c80c96dc9f813491231433762fbad91d.tar.xz |
Merge git://git.infradead.org/mtd-2.6
* git://git.infradead.org/mtd-2.6:
[MTD] [NOR] Fix deadlock in Intel chip driver caused by get_chip recursion
[JFFS2] Fix return value from jffs2_write_end()
[MTD] [OneNAND] Fix wrong free the static address in onenand_sim
[MTD] [NAND] Replace -1 with -EBADMSG in nand error correction code
[RSLIB] BUG() when passing illegal parameters to decode_rs8() or decode_rs16()
[MTD] [NAND] treat any negative return value from correct() as an error
[MTD] [NAND] nandsim: bugfix in initialization
[MTD] Fix typo in Alauda config option help text.
[MTD] [NAND] add s3c2440-specific read_buf/write_buf
[MTD] [OneNAND] onenand-sim: fix kernel-doc and typos
[JFFS2] Tidy up fix for ACL/permissions problem.
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/mtd/chips/cfi_cmdset_0001.c | 146 | ||||
-rw-r--r-- | drivers/mtd/nand/Kconfig | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/diskonchip.c | 4 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 6 | ||||
-rw-r--r-- | drivers/mtd/nand/nand_ecc.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/nandsim.c | 2 | ||||
-rw-r--r-- | drivers/mtd/nand/s3c2410.c | 14 | ||||
-rw-r--r-- | drivers/mtd/onenand/onenand_sim.c | 50 |
8 files changed, 124 insertions, 102 deletions
diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c index 3aa3dca56ae6..a9eb1c516247 100644 --- a/drivers/mtd/chips/cfi_cmdset_0001.c +++ b/drivers/mtd/chips/cfi_cmdset_0001.c @@ -85,6 +85,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, static void cfi_intelext_unpoint (struct mtd_info *mtd, u_char *addr, loff_t from, size_t len); +static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode); static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode); static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr); #include "fwh_lock.h" @@ -641,73 +642,13 @@ static int cfi_intelext_partition_fixup(struct mtd_info *mtd, /* * *********** CHIP ACCESS FUNCTIONS *********** */ - -static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) +static int chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode) { DECLARE_WAITQUEUE(wait, current); struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK = CMD(0x80), status_PWS = CMD(0x01); - unsigned long timeo; struct cfi_pri_intelext *cfip = cfi->cmdset_priv; - - resettime: - timeo = jiffies + HZ; - retry: - if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) { - /* - * OK. We have possibility for contension on the write/erase - * operations which are global to the real chip and not per - * partition. So let's fight it over in the partition which - * currently has authority on the operation. - * - * The rules are as follows: - * - * - any write operation must own shared->writing. - * - * - any erase operation must own _both_ shared->writing and - * shared->erasing. - * - * - contension arbitration is handled in the owner's context. - * - * The 'shared' struct can be read and/or written only when - * its lock is taken. - */ - struct flchip_shared *shared = chip->priv; - struct flchip *contender; - spin_lock(&shared->lock); - contender = shared->writing; - if (contender && contender != chip) { - /* - * The engine to perform desired operation on this - * partition is already in use by someone else. - * Let's fight over it in the context of the chip - * currently using it. If it is possible to suspend, - * that other partition will do just that, otherwise - * it'll happily send us to sleep. In any case, when - * get_chip returns success we're clear to go ahead. - */ - int ret = spin_trylock(contender->mutex); - spin_unlock(&shared->lock); - if (!ret) - goto retry; - spin_unlock(chip->mutex); - ret = get_chip(map, contender, contender->start, mode); - spin_lock(chip->mutex); - if (ret) { - spin_unlock(contender->mutex); - return ret; - } - timeo = jiffies + HZ; - spin_lock(&shared->lock); - spin_unlock(contender->mutex); - } - - /* We now own it */ - shared->writing = chip; - if (mode == FL_ERASING) - shared->erasing = chip; - spin_unlock(&shared->lock); - } + unsigned long timeo = jiffies + HZ; switch (chip->state) { @@ -722,16 +663,11 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS)) break; - if (time_after(jiffies, timeo)) { - printk(KERN_ERR "%s: Waiting for chip to be ready timed out. Status %lx\n", - map->name, status.x[0]); - return -EIO; - } spin_unlock(chip->mutex); cfi_udelay(1); spin_lock(chip->mutex); /* Someone else might have been playing with it. */ - goto retry; + return -EAGAIN; } case FL_READY: @@ -809,10 +745,82 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr schedule(); remove_wait_queue(&chip->wq, &wait); spin_lock(chip->mutex); - goto resettime; + return -EAGAIN; } } +static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) +{ + int ret; + + retry: + if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING + || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) { + /* + * OK. We have possibility for contention on the write/erase + * operations which are global to the real chip and not per + * partition. So let's fight it over in the partition which + * currently has authority on the operation. + * + * The rules are as follows: + * + * - any write operation must own shared->writing. + * + * - any erase operation must own _both_ shared->writing and + * shared->erasing. + * + * - contention arbitration is handled in the owner's context. + * + * The 'shared' struct can be read and/or written only when + * its lock is taken. + */ + struct flchip_shared *shared = chip->priv; + struct flchip *contender; + spin_lock(&shared->lock); + contender = shared->writing; + if (contender && contender != chip) { + /* + * The engine to perform desired operation on this + * partition is already in use by someone else. + * Let's fight over it in the context of the chip + * currently using it. If it is possible to suspend, + * that other partition will do just that, otherwise + * it'll happily send us to sleep. In any case, when + * get_chip returns success we're clear to go ahead. + */ + ret = spin_trylock(contender->mutex); + spin_unlock(&shared->lock); + if (!ret) + goto retry; + spin_unlock(chip->mutex); + ret = chip_ready(map, contender, contender->start, mode); + spin_lock(chip->mutex); + + if (ret == -EAGAIN) { + spin_unlock(contender->mutex); + goto retry; + } + if (ret) { + spin_unlock(contender->mutex); + return ret; + } + spin_lock(&shared->lock); + spin_unlock(contender->mutex); + } + + /* We now own it */ + shared->writing = chip; + if (mode == FL_ERASING) + shared->erasing = chip; + spin_unlock(&shared->lock); + } + ret = chip_ready(map, chip, adr, mode); + if (ret == -EAGAIN) + goto retry; + + return ret; +} + static void put_chip(struct map_info *map, struct flchip *chip, unsigned long adr) { struct cfi_private *cfi = map->fldrv_priv; diff --git a/drivers/mtd/nand/Kconfig b/drivers/mtd/nand/Kconfig index 8f9c3baeb38e..246d4512f64b 100644 --- a/drivers/mtd/nand/Kconfig +++ b/drivers/mtd/nand/Kconfig @@ -300,7 +300,7 @@ config MTD_NAND_PLATFORM via platform_data. config MTD_ALAUDA - tristate "MTD driver for Olympus MAUSB-10 and Fijufilm DPC-R1" + tristate "MTD driver for Olympus MAUSB-10 and Fujifilm DPC-R1" depends on MTD_NAND && USB help These two (and possibly other) Alauda-based cardreaders for diff --git a/drivers/mtd/nand/diskonchip.c b/drivers/mtd/nand/diskonchip.c index ab9f5c5db38d..0e72153b3297 100644 --- a/drivers/mtd/nand/diskonchip.c +++ b/drivers/mtd/nand/diskonchip.c @@ -220,7 +220,7 @@ static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc) } } /* If the parity is wrong, no rescue possible */ - return parity ? -1 : nerr; + return parity ? -EBADMSG : nerr; } static void DoC_Delay(struct doc_priv *doc, unsigned short cycles) @@ -1034,7 +1034,7 @@ static int doc200x_correct_data(struct mtd_info *mtd, u_char *dat, WriteDOC(DOC_ECC_DIS, docptr, Mplus_ECCConf); else WriteDOC(DOC_ECC_DIS, docptr, ECCConf); - if (no_ecc_failures && (ret == -1)) { + if (no_ecc_failures && (ret == -EBADMSG)) { printk(KERN_ERR "suppressing ECC failure\n"); ret = 0; } diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b4e0e7723894..e29c1da7f56e 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -789,7 +789,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat == -1) + if (stat < 0) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; @@ -833,7 +833,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, int stat; stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]); - if (stat == -1) + if (stat < 0) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; @@ -874,7 +874,7 @@ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, chip->read_buf(mtd, oob, eccbytes); stat = chip->ecc.correct(mtd, p, oob, NULL); - if (stat == -1) + if (stat < 0) mtd->ecc_stats.failed++; else mtd->ecc_stats.corrected += stat; diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c index fde593e5e634..9003a135e050 100644 --- a/drivers/mtd/nand/nand_ecc.c +++ b/drivers/mtd/nand/nand_ecc.c @@ -189,7 +189,7 @@ int nand_correct_data(struct mtd_info *mtd, u_char *dat, if(countbits(s0 | ((uint32_t)s1 << 8) | ((uint32_t)s2 <<16)) == 1) return 1; - return -1; + return -EBADMSG; } EXPORT_SYMBOL(nand_correct_data); diff --git a/drivers/mtd/nand/nandsim.c b/drivers/mtd/nand/nandsim.c index a7574807dc46..10490b48d9f7 100644 --- a/drivers/mtd/nand/nandsim.c +++ b/drivers/mtd/nand/nandsim.c @@ -511,7 +511,7 @@ static int init_nandsim(struct mtd_info *mtd) } if (ns->options & OPT_SMALLPAGE) { - if (ns->geom.totsz < (64 << 20)) { + if (ns->geom.totsz < (32 << 20)) { ns->geom.pgaddrbytes = 3; ns->geom.secaddrbytes = 2; } else { diff --git a/drivers/mtd/nand/s3c2410.c b/drivers/mtd/nand/s3c2410.c index 21b921dd6aab..66f76e9618dd 100644 --- a/drivers/mtd/nand/s3c2410.c +++ b/drivers/mtd/nand/s3c2410.c @@ -488,12 +488,24 @@ static void s3c2410_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) readsb(this->IO_ADDR_R, buf, len); } +static void s3c2440_nand_read_buf(struct mtd_info *mtd, u_char *buf, int len) +{ + struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + readsl(info->regs + S3C2440_NFDATA, buf, len / 4); +} + static void s3c2410_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) { struct nand_chip *this = mtd->priv; writesb(this->IO_ADDR_W, buf, len); } +static void s3c2440_nand_write_buf(struct mtd_info *mtd, const u_char *buf, int len) +{ + struct s3c2410_nand_info *info = s3c2410_nand_mtd_toinfo(mtd); + writesl(info->regs + S3C2440_NFDATA, buf, len / 4); +} + /* device management functions */ static int s3c2410_nand_remove(struct platform_device *pdev) @@ -604,6 +616,8 @@ static void s3c2410_nand_init_chip(struct s3c2410_nand_info *info, info->sel_bit = S3C2440_NFCONT_nFCE; chip->cmd_ctrl = s3c2440_nand_hwcontrol; chip->dev_ready = s3c2440_nand_devready; + chip->read_buf = s3c2440_nand_read_buf; + chip->write_buf = s3c2440_nand_write_buf; break; case TYPE_S3C2412: diff --git a/drivers/mtd/onenand/onenand_sim.c b/drivers/mtd/onenand/onenand_sim.c index 0d89ad5776fa..d64200b7c94b 100644 --- a/drivers/mtd/onenand/onenand_sim.c +++ b/drivers/mtd/onenand/onenand_sim.c @@ -88,11 +88,11 @@ do { \ /** * onenand_lock_handle - Handle Lock scheme - * @param this OneNAND device structure - * @param cmd The command to be sent + * @this: OneNAND device structure + * @cmd: The command to be sent * * Send lock command to OneNAND device. - * The lock scheme is depends on chip type. + * The lock scheme depends on chip type. */ static void onenand_lock_handle(struct onenand_chip *this, int cmd) { @@ -131,8 +131,8 @@ static void onenand_lock_handle(struct onenand_chip *this, int cmd) /** * onenand_bootram_handle - Handle BootRAM area - * @param this OneNAND device structure - * @param cmd The command to be sent + * @this: OneNAND device structure + * @cmd: The command to be sent * * Emulate BootRAM area. It is possible to do basic operation using BootRAM. */ @@ -153,10 +153,10 @@ static void onenand_bootram_handle(struct onenand_chip *this, int cmd) /** * onenand_update_interrupt - Set interrupt register - * @param this OneNAND device structure - * @param cmd The command to be sent + * @this: OneNAND device structure + * @cmd: The command to be sent * - * Update interrupt register. The status is depends on command. + * Update interrupt register. The status depends on command. */ static void onenand_update_interrupt(struct onenand_chip *this, int cmd) { @@ -189,11 +189,12 @@ static void onenand_update_interrupt(struct onenand_chip *this, int cmd) } /** - * onenand_check_overwrite - Check over-write if happend - * @param dest The destination pointer - * @param src The source pointer - * @param count The length to be check - * @return 0 on same, otherwise 1 + * onenand_check_overwrite - Check if over-write happened + * @dest: The destination pointer + * @src: The source pointer + * @count: The length to be check + * + * Returns: 0 on same, otherwise 1 * * Compare the source with destination */ @@ -213,10 +214,10 @@ static int onenand_check_overwrite(void *dest, void *src, size_t count) /** * onenand_data_handle - Handle OneNAND Core and DataRAM - * @param this OneNAND device structure - * @param cmd The command to be sent - * @param dataram Which dataram used - * @param offset The offset to OneNAND Core + * @this: OneNAND device structure + * @cmd: The command to be sent + * @dataram: Which dataram used + * @offset: The offset to OneNAND Core * * Copy data from OneNAND Core to DataRAM (read) * Copy data from DataRAM to OneNAND Core (write) @@ -295,8 +296,8 @@ static void onenand_data_handle(struct onenand_chip *this, int cmd, /** * onenand_command_handle - Handle command - * @param this OneNAND device structure - * @param cmd The command to be sent + * @this: OneNAND device structure + * @cmd: The command to be sent * * Emulate OneNAND command. */ @@ -350,8 +351,8 @@ static void onenand_command_handle(struct onenand_chip *this, int cmd) /** * onenand_writew - [OneNAND Interface] Emulate write operation - * @param value value to write - * @param addr address to write + * @value: value to write + * @addr: address to write * * Write OneNAND register with value */ @@ -373,7 +374,7 @@ static void onenand_writew(unsigned short value, void __iomem * addr) /** * flash_init - Initialize OneNAND simulator - * @param flash OneNAND simulaotr data strucutres + * @flash: OneNAND simulator data strucutres * * Initialize OneNAND simulator. */ @@ -416,7 +417,7 @@ static int __init flash_init(struct onenand_flash *flash) /** * flash_exit - Clean up OneNAND simulator - * @param flash OneNAND simulaotr data strucutres + * @flash: OneNAND simulator data structures * * Clean up OneNAND simulator. */ @@ -424,7 +425,6 @@ static void flash_exit(struct onenand_flash *flash) { vfree(ONENAND_CORE(flash)); kfree(flash->base); - kfree(flash); } static int __init onenand_sim_init(void) @@ -449,7 +449,7 @@ static int __init onenand_sim_init(void) info->onenand.write_word = onenand_writew; if (flash_init(&info->flash)) { - printk(KERN_ERR "Unable to allocat flash.\n"); + printk(KERN_ERR "Unable to allocate flash.\n"); kfree(ffchars); kfree(info); return -ENOMEM; |