Skip to content

Commit

Permalink
Merge git://git.infradead.org/mtd-2.6
Browse files Browse the repository at this point in the history
* 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.
  • Loading branch information
Linus Torvalds committed Oct 23, 2007
2 parents f3344c5 + 5a37cf1 commit 6e50607
Show file tree
Hide file tree
Showing 17 changed files with 226 additions and 199 deletions.
146 changes: 77 additions & 69 deletions drivers/mtd/chips/cfi_cmdset_0001.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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) {

Expand All @@ -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:
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions drivers/mtd/nand/diskonchip.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions drivers/mtd/nand/nand_base.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/nand_ecc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion drivers/mtd/nand/nandsim.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
14 changes: 14 additions & 0 deletions drivers/mtd/nand/s3c2410.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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:
Expand Down
Loading

0 comments on commit 6e50607

Please sign in to comment.