diff options
| author | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-02-28 01:14:42 +0000 | 
|---|---|---|
| committer | nbd <nbd@3c298f89-4303-0410-b956-a3cf2f4a3e73> | 2007-02-28 01:14:42 +0000 | 
| commit | 464d8f3a694f96f752e56b3eca630b60a00201b1 (patch) | |
| tree | 926c561700706a119a1cb4f7dda42e61e5ca1d25 | |
| parent | e6a1045cbf4967a8e6d3207fe68abac025c7b6cf (diff) | |
add a patch to revert recent breakage in the intel cfi flash driver (fixes #1140)
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@6420 3c298f89-4303-0410-b956-a3cf2f4a3e73
| -rw-r--r-- | target/linux/generic-2.6/patches/009-revert_intel_flash_breakage.patch | 169 | 
1 files changed, 169 insertions, 0 deletions
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 index 000000000..ea06360c4 --- /dev/null +++ b/target/linux/generic-2.6/patches/009-revert_intel_flash_breakage.patch @@ -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;  | 
