Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[MTD] CFI-0002 - Improve error checking

Check for errors besides infinite loops when writing and erasing.

Signed-off-by: Eric W. Biederman <ebiederman@lnxi.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Eric W. Biedermann and committed by
Thomas Gleixner
fb4a90bf 6da70124

+69 -34
+69 -34
drivers/mtd/chips/cfi_cmdset_0002.c
··· 13 13 * 14 14 * This code is GPL 15 15 * 16 - * $Id: cfi_cmdset_0002.c,v 1.114 2004/12/11 15:43:53 dedekind Exp $ 16 + * $Id: cfi_cmdset_0002.c,v 1.115 2005/05/20 03:28:23 eric Exp $ 17 17 * 18 18 */ 19 19 ··· 43 43 #define MANUFACTURER_AMD 0x0001 44 44 #define MANUFACTURER_SST 0x00BF 45 45 #define SST49LF004B 0x0060 46 + #define SST49LF008A 0x005a 46 47 47 48 static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); 48 49 static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); ··· 192 191 }; 193 192 static struct cfi_fixup jedec_fixup_table[] = { 194 193 { MANUFACTURER_SST, SST49LF004B, fixup_use_fwh_lock, NULL, }, 194 + { MANUFACTURER_SST, SST49LF008A, fixup_use_fwh_lock, NULL, }, 195 195 { 0, 0, NULL, NULL } 196 196 }; 197 197 ··· 401 399 t = map_read(map, addr); 402 400 403 401 return map_word_equal(map, d, t); 402 + } 403 + 404 + /* 405 + * Return true if the chip is ready and has the correct value. 406 + * 407 + * Ready is one of: read mode, query mode, erase-suspend-read mode (in any 408 + * non-suspended sector) and it is indicated by no bits toggling. 409 + * 410 + * Error are indicated by toggling bits or bits held with the wrong value, 411 + * or with bits toggling. 412 + * 413 + * Note that anything more complicated than checking if no bits are toggling 414 + * (including checking DQ5 for an error status) is tricky to get working 415 + * correctly and is therefore not done (particulary with interleaved chips 416 + * as each chip must be checked independantly of the others). 417 + * 418 + */ 419 + static int chip_good(struct map_info *map, unsigned long addr, map_word expected) 420 + { 421 + map_word oldd, curd; 422 + 423 + oldd = map_read(map, addr); 424 + curd = map_read(map, addr); 425 + 426 + return map_word_equal(map, oldd, curd) && 427 + map_word_equal(map, curd, expected); 404 428 } 405 429 406 430 static int get_chip(struct map_info *map, struct flchip *chip, unsigned long adr, int mode) ··· 793 765 } 794 766 795 767 if (chip_ready(map, adr)) 796 - goto op_done; 768 + break; 797 769 798 - if (time_after(jiffies, timeo)) 770 + if (time_after(jiffies, timeo)) { 771 + printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); 799 772 break; 773 + } 800 774 801 775 /* Latency issues. Drop the lock, wait a while and retry */ 802 776 cfi_spin_unlock(chip->mutex); 803 777 cfi_udelay(1); 804 778 cfi_spin_lock(chip->mutex); 805 779 } 780 + /* Did we succeed? */ 781 + if (!chip_good(map, adr, datum)) { 782 + /* reset on all failures. */ 783 + map_write( map, CMD(0xF0), chip->start ); 784 + /* FIXME - should have reset delay before continuing */ 806 785 807 - printk(KERN_WARNING "MTD %s(): software timeout\n", __func__); 786 + if (++retry_cnt <= MAX_WORD_RETRIES) 787 + goto retry; 808 788 809 - /* reset on all failures. */ 810 - map_write( map, CMD(0xF0), chip->start ); 811 - /* FIXME - should have reset delay before continuing */ 812 - if (++retry_cnt <= MAX_WORD_RETRIES) 813 - goto retry; 814 - 815 - ret = -EIO; 789 + ret = -EIO; 790 + } 816 791 op_done: 817 792 chip->state = FL_READY; 818 793 put_chip(map, chip, adr); ··· 1218 1187 } 1219 1188 1220 1189 if (chip_ready(map, adr)) 1221 - goto op_done; 1222 - 1223 - if (time_after(jiffies, timeo)) 1224 1190 break; 1191 + 1192 + if (time_after(jiffies, timeo)) { 1193 + printk(KERN_WARNING "MTD %s(): software timeout\n", 1194 + __func__ ); 1195 + break; 1196 + } 1225 1197 1226 1198 /* Latency issues. Drop the lock, wait a while and retry */ 1227 1199 cfi_spin_unlock(chip->mutex); ··· 1232 1198 schedule_timeout(1); 1233 1199 cfi_spin_lock(chip->mutex); 1234 1200 } 1201 + /* Did we succeed? */ 1202 + if (!chip_good(map, adr, map_word_ff(map))) { 1203 + /* reset on all failures. */ 1204 + map_write( map, CMD(0xF0), chip->start ); 1205 + /* FIXME - should have reset delay before continuing */ 1235 1206 1236 - printk(KERN_WARNING "MTD %s(): software timeout\n", 1237 - __func__ ); 1207 + ret = -EIO; 1208 + } 1238 1209 1239 - /* reset on all failures. */ 1240 - map_write( map, CMD(0xF0), chip->start ); 1241 - /* FIXME - should have reset delay before continuing */ 1242 - 1243 - ret = -EIO; 1244 - op_done: 1245 1210 chip->state = FL_READY; 1246 1211 put_chip(map, chip, adr); 1247 1212 cfi_spin_unlock(chip->mutex); ··· 1305 1272 } 1306 1273 1307 1274 if (chip_ready(map, adr)) 1308 - goto op_done; 1309 - 1310 - if (time_after(jiffies, timeo)) 1311 1275 break; 1276 + 1277 + if (time_after(jiffies, timeo)) { 1278 + printk(KERN_WARNING "MTD %s(): software timeout\n", 1279 + __func__ ); 1280 + break; 1281 + } 1312 1282 1313 1283 /* Latency issues. Drop the lock, wait a while and retry */ 1314 1284 cfi_spin_unlock(chip->mutex); ··· 1319 1283 schedule_timeout(1); 1320 1284 cfi_spin_lock(chip->mutex); 1321 1285 } 1322 - 1323 - printk(KERN_WARNING "MTD %s(): software timeout\n", 1324 - __func__ ); 1325 - 1326 - /* reset on all failures. */ 1327 - map_write( map, CMD(0xF0), chip->start ); 1328 - /* FIXME - should have reset delay before continuing */ 1286 + /* Did we succeed? */ 1287 + if (chip_good(map, adr, map_word_ff(map))) { 1288 + /* reset on all failures. */ 1289 + map_write( map, CMD(0xF0), chip->start ); 1290 + /* FIXME - should have reset delay before continuing */ 1329 1291 1330 - ret = -EIO; 1331 - op_done: 1292 + ret = -EIO; 1293 + } 1294 + 1332 1295 chip->state = FL_READY; 1333 1296 put_chip(map, chip, adr); 1334 1297 cfi_spin_unlock(chip->mutex);