--- linux-2.6.25/drivers/mtd/chips/cfi_cmdset_0001.c 2008-04-17 04:49:44.000000000 +0200 +++ linux-2.6.25.hacked/drivers/mtd/chips/cfi_cmdset_0001.c 2008-04-23 18:00:16.000000000 +0200 @@ -86,7 +86,7 @@ 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 chip_ready (struct map_info *map, struct flchip *chip, unsigned long adr, int mode, unsigned long timeout); 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" @@ -691,34 +691,40 @@ /* * *********** CHIP ACCESS FUNCTIONS *********** */ -static int chip_ready (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, unsigned long timeo) { DECLARE_WAITQUEUE(wait, current); struct cfi_private *cfi = map->fldrv_priv; map_word status, status_OK = CMD(0x80), status_PWS = CMD(0x01); struct cfi_pri_intelext *cfip = cfi->cmdset_priv; - unsigned long timeo = jiffies + HZ; switch (chip->state) { case FL_STATUS: - for (;;) { - status = map_read(map, adr); - if (map_word_andequal(map, status, status_OK, status_OK)) - break; - /* At this point we're fine with write operations - in other partitions as they don't conflict. */ - if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS)) - break; + status = map_read(map, adr); - spin_unlock(chip->mutex); - cfi_udelay(1); - spin_lock(chip->mutex); - /* Someone else might have been playing with it. */ - return -EAGAIN; + if (map_word_andequal(map, status, status_OK, status_OK)) + return 0; + + /* At this point we're fine with write operations + in other partitions as they don't conflict. */ + if (chip->priv && map_word_andequal(map, status, status_PWS, status_PWS)) + return 0; + + 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; } - /* Fall through */ + + spin_unlock(chip->mutex); + cfi_udelay(1); + spin_lock(chip->mutex); + + /* Someone else might have been playing with it. */ + return -EAGAIN; + case FL_READY: case FL_CFI_QUERY: case FL_JEDEC_QUERY: @@ -801,8 +807,12 @@ static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) { int ret; + unsigned int timeo; + DECLARE_WAITQUEUE(wait, current); + timeo = jiffies + HZ; + retry: if (chip->priv && (mode == FL_WRITING || mode == FL_ERASING || mode == FL_OTP_WRITE || mode == FL_SHUTDOWN)) { @@ -843,7 +853,7 @@ if (!ret) goto retry; spin_unlock(chip->mutex); - ret = chip_ready(map, contender, contender->start, mode); + ret = chip_ready(map, contender, contender->start, mode, timeo); spin_lock(chip->mutex); if (ret == -EAGAIN) { @@ -878,7 +888,7 @@ shared->erasing = chip; spin_unlock(&shared->lock); } - ret = chip_ready(map, chip, adr, mode); + ret = chip_ready(map, chip, adr, mode, timeo); if (ret == -EAGAIN) goto retry;