add a patch to revert recent breakage in the intel cfi flash driver (fixes #1140)
authorFelix Fietkau <nbd@openwrt.org>
Wed, 28 Feb 2007 01:14:42 +0000 (01:14 +0000)
committerFelix Fietkau <nbd@openwrt.org>
Wed, 28 Feb 2007 01:14:42 +0000 (01:14 +0000)
SVN-Revision: 6420

target/linux/generic-2.6/patches/009-revert_intel_flash_breakage.patch [new file with mode: 0644]

diff --git a/target/linux/generic-2.6/patches/009-revert_intel_flash_breakage.patch b/target/linux/generic-2.6/patches/009-revert_intel_flash_breakage.patch
new file mode 100644 (file)
index 0000000..ea06360
--- /dev/null
@@ -0,0 +1,169 @@
+--- linux.old/drivers/mtd/chips/cfi_cmdset_0001.c      2007-02-13 02:41:50.816650352 +0100
++++ linux.dev/drivers/mtd/chips/cfi_cmdset_0001.c      2007-02-13 02:42:13.782159064 +0100
+@@ -908,7 +908,7 @@
+ static int __xipram xip_wait_for_operation(
+               struct map_info *map, struct flchip *chip,
+-              unsigned long adr, unsigned int chip_op_time )
++              unsigned long adr, int *chip_op_time )
+ {
+       struct cfi_private *cfi = map->fldrv_priv;
+       struct cfi_pri_intelext *cfip = cfi->cmdset_priv;
+@@ -917,7 +917,7 @@
+       flstate_t oldstate, newstate;
+               start = xip_currtime();
+-      usec = chip_op_time * 8;
++      usec = *chip_op_time * 8;
+       if (usec == 0)
+               usec = 500000;
+       done = 0;
+@@ -1027,8 +1027,8 @@
+ #define XIP_INVAL_CACHED_RANGE(map, from, size)  \
+       INVALIDATE_CACHED_RANGE(map, from, size)
+-#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, usec) \
+-      xip_wait_for_operation(map, chip, cmd_adr, usec)
++#define INVAL_CACHE_AND_WAIT(map, chip, cmd_adr, inval_adr, inval_len, p_usec) \
++      xip_wait_for_operation(map, chip, cmd_adr, p_usec)
+ #else
+@@ -1040,65 +1040,65 @@
+ static int inval_cache_and_wait_for_operation(
+               struct map_info *map, struct flchip *chip,
+               unsigned long cmd_adr, unsigned long inval_adr, int inval_len,
+-              unsigned int chip_op_time)
++              int *chip_op_time )
+ {
+       struct cfi_private *cfi = map->fldrv_priv;
+       map_word status, status_OK = CMD(0x80);
+-      int chip_state = chip->state;
+-      unsigned int timeo, sleep_time;
++      int z, chip_state = chip->state;
++      unsigned long timeo;
+       spin_unlock(chip->mutex);
+       if (inval_len)
+               INVALIDATE_CACHED_RANGE(map, inval_adr, inval_len);
++      if (*chip_op_time)
++              cfi_udelay(*chip_op_time);
+       spin_lock(chip->mutex);
+-      /* set our timeout to 8 times the expected delay */
+-      timeo = chip_op_time * 8;
+-      if (!timeo)
+-              timeo = 500000;
+-      sleep_time = chip_op_time / 2;
++      timeo = *chip_op_time * 8 * HZ / 1000000;
++      if (timeo < HZ/2)
++              timeo = HZ/2;
++      timeo += jiffies;
++      z = 0;
+       for (;;) {
++              if (chip->state != chip_state) {
++                      /* Someone's suspended the operation: sleep */
++                      DECLARE_WAITQUEUE(wait, current);
++
++                      set_current_state(TASK_UNINTERRUPTIBLE);
++                      add_wait_queue(&chip->wq, &wait);
++                      spin_unlock(chip->mutex);
++                      schedule();
++                      remove_wait_queue(&chip->wq, &wait);
++                      timeo = jiffies + (HZ / 2); /* FIXME */
++                      spin_lock(chip->mutex);
++                      continue;
++              }
++
+               status = map_read(map, cmd_adr);
+               if (map_word_andequal(map, status, status_OK, status_OK))
+                       break;
+-              if (!timeo) {
++              /* OK Still waiting */
++              if (time_after(jiffies, timeo)) {
+                       map_write(map, CMD(0x70), cmd_adr);
+                       chip->state = FL_STATUS;
+                       return -ETIME;
+               }
+-              /* OK Still waiting. Drop the lock, wait a while and retry. */
++              /* Latency issues. Drop the lock, wait a while and retry */
++              z++;
+               spin_unlock(chip->mutex);
+-              if (sleep_time >= 1000000/HZ) {
+-                      /*
+-                       * Half of the normal delay still remaining
+-                       * can be performed with a sleeping delay instead
+-                       * of busy waiting.
+-                       */
+-                      msleep(sleep_time/1000);
+-                      timeo -= sleep_time;
+-                      sleep_time = 1000000/HZ;
+-              } else {
+-                      udelay(1);
+-                      cond_resched();
+-                      timeo--;
+-              }
++              cfi_udelay(1);
+               spin_lock(chip->mutex);
+-
+-              while (chip->state != chip_state) {
+-                      /* Someone's suspended the operation: sleep */
+-                      DECLARE_WAITQUEUE(wait, current);
+-                      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);
+-              }
+       }
++      if (!z) {
++              if (!--(*chip_op_time))
++                      *chip_op_time = 1;
++      } else if (z > 1)
++              ++(*chip_op_time);
++
+       /* Done and happy. */
+       chip->state = FL_STATUS;
+       return 0;
+@@ -1107,7 +1107,8 @@
+ #endif
+ #define WAIT_TIMEOUT(map, chip, adr, udelay) \
+-      INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, udelay);
++      ({ int __udelay = (udelay); \
++         INVAL_CACHE_AND_WAIT(map, chip, adr, 0, 0, &__udelay); })
+ static int do_point_onechip (struct map_info *map, struct flchip *chip, loff_t adr, size_t len)
+@@ -1331,7 +1332,7 @@
+       ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
+                                  adr, map_bankwidth(map),
+-                                 chip->word_write_time);
++                                 &chip->word_write_time);
+       if (ret) {
+               xip_enable(map, chip, adr);
+               printk(KERN_ERR "%s: word write error (status timeout)\n", map->name);
+@@ -1568,7 +1569,7 @@
+       ret = INVAL_CACHE_AND_WAIT(map, chip, cmd_adr,
+                                  adr, len,
+-                                 chip->buffer_write_time);
++                                 &chip->buffer_write_time);
+       if (ret) {
+               map_write(map, CMD(0x70), cmd_adr);
+               chip->state = FL_STATUS;
+@@ -1703,7 +1704,7 @@
+       ret = INVAL_CACHE_AND_WAIT(map, chip, adr,
+                                  adr, len,
+-                                 chip->erase_time);
++                                 &chip->erase_time);
+       if (ret) {
+               map_write(map, CMD(0x70), adr);
+               chip->state = FL_STATUS;