Skip to contentSkip to conversation

I/O errors from do_erase_oneblock()

DISCUSSION jfaslist 1 participant 1 message May 31, 2006 Memory technology devices (MTD)

lore
Share & tools
lore

jfaslist

author
#0 lore raw

Hi,
I have a question on the chips/cfi_cmdset0002.c:do_erase_oneblock() function (see below). It is probably a stupid question but I can't find the answer:

-What is the use of INVALIDATE_CACHE_UDELAY (seems to be just a call to cfi_udelay() ) . I guess I don't understand the reason for having this delay, plus the HZ*20 delay in the following for(;;) loop. -After the function do a "add_wait_queue" and "schedule", what code is going to send a "wake_up()" to end the wait?

My problem is that on erase, I get I/O errors coming from this function. I have added call to cfi_udelay() (up to 12ms) and that seems to solve the problem (even though ST Micro claims worst case is 6ms). But I prefer to understand what's going on. I have a suspicion that chip_ready() may be ending the for(;;) loop too soon causing chip_good() to fail.

My geometry is:
-interleave = 4
-bankwidth = 8 (64b)
p/n = ST MICRO M29DW640

I use the MTD code from linux-2.6.15

Thanks for the help,
-jf simon

static int __xipram do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr, int len, void *thunk)

{
       struct cfi_private *cfi = map->fldrv_priv;
       unsigned long timeo = jiffies + HZ;
       DECLARE_WAITQUEUE(wait, current);
       int ret = 0;

       adr += chip->start;

       spin_lock(chip->mutex);
       ret = get_chip(map, chip, adr, FL_ERASING);
       if (ret) {
               spin_unlock(chip->mutex);
               return ret;
       }

       DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
              __func__, adr );

       XIP_INVAL_CACHED_RANGE(map, adr, len);
       ENABLE_VPP(map);
       xip_disable(map, chip, adr);

       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, 
cfi->device_type, NULL);
       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, 
cfi->device_type, NULL);
       cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, 
cfi->device_type, NULL);
       cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, 
cfi->device_type, NULL);
       cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, 
cfi->device_type, NULL);
       map_write(map, CMD(0x30), adr);

       chip->state = FL_ERASING;
       chip->erase_suspended = 0;
       chip->in_progress_block_addr = adr;


    INVALIDATE_CACHE_UDELAY(map, chip,
                               adr, len,
                               chip->erase_time*500);

       timeo = jiffies + (HZ*20);

       for (;;) {
               if (chip->state != FL_ERASING) {
                       /* Someone's suspended the erase. Sleep */
                       set_current_state(TASK_UNINTERRUPTIBLE);
                       add_wait_queue(&chip->wq, &wait);
                       spin_unlock(chip->mutex);
                       schedule();
                       remove_wait_queue(&chip->wq, &wait);
                       spin_lock(chip->mutex);
                       continue;
               }
               if (chip->erase_suspended) {
                       /* This erase was suspended and resumed.
                          Adjust the timeout */
                       timeo = jiffies + (HZ*20); /* FIXME */
                       chip->erase_suspended = 0;
               }

               if (chip_ready(map, adr)) {
                       xip_enable(map, chip, adr);
                       break;
               }

               if (time_after(jiffies, timeo)) {
                       xip_enable(map, chip, adr);
                       printk(KERN_WARNING "MTD %s(): software timeout\n",
                               __func__ );
                       break;
               }

               /* Latency issues. Drop the lock, wait a while and retry */
               UDELAY(map, chip, adr, 1000000/HZ);
       }
       /* Did we succeed? */
       if (!chip_good(map, adr, map_word_ff(map))) {
               /* reset on all failures. */
               map_write( map, CMD(0xF0), chip->start );
               /* FIXME - should have reset delay before continuing */

               ret = -EIO;
       }

       chip->state = FL_READY;
       put_chip(map, chip, adr);
       spin_unlock(chip->mutex);
       return ret;
}

___________________________________________________________________________ Yahoo! Mail réinvente le mail ! Découvrez le nouveau Yahoo! Mail et son interface révolutionnaire.
http://fr.mail.yahoo.com