--- zzzz-none-000/linux-3.10.107/drivers/mtd/chips/cfi_cmdset_0002.c 2017-06-27 09:49:32.000000000 +0000 +++ vr9-7490-729/linux-3.10.107/drivers/mtd/chips/cfi_cmdset_0002.c 2021-11-10 11:53:55.000000000 +0000 @@ -49,6 +49,7 @@ #define SST49LF040B 0x0050 #define SST49LF008A 0x005a #define AT49BV6416 0x00d6 +#define MANUFACTURER_SAMSUNG 0x00ec static int cfi_amdstd_read (struct mtd_info *, loff_t, size_t, size_t *, u_char *); static int cfi_amdstd_write_words(struct mtd_info *, loff_t, size_t, size_t *, const u_char *); @@ -87,6 +88,34 @@ .module = THIS_MODULE }; +/*------------------------------------------------------------------------------------------*\ + * No scheduling in panic mode +\*------------------------------------------------------------------------------------------*/ +#if defined(CONFIG_TFFS2) +extern unsigned int tffs_panic_mode; +#else +static const unsigned int tffs_panic_mode = 0; +#endif + +static inline void cfi_add_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) +{ + if (!tffs_panic_mode) + add_wait_queue(q, wait); +} + +static inline void cfi_remove_wait_queue(wait_queue_head_t *q, wait_queue_t *wait) +{ + if (!tffs_panic_mode) + remove_wait_queue(q, wait); +} + +static inline void cfi_schedule(void) +{ + if (!tffs_panic_mode) + schedule(); +} + + /* #define DEBUG_CFI_FEATURES */ @@ -351,6 +380,16 @@ pr_warning("%s: Bad S29NS512P CFI data; adjust to 512 sectors\n", mtd->name); } +static void fixup_m29w128g_write_buffer(struct mtd_info *mtd) +{ + struct map_info *map = mtd->priv; + struct cfi_private *cfi = map->fldrv_priv; + if (cfi->cfiq->BufWriteTimeoutTyp) { + pr_warning("Don't use write buffer on ST flash M29W128G\n"); + cfi->cfiq->BufWriteTimeoutTyp = 0; + } +} + /* Used to fix CFI-Tables of chips without Extended Query Tables */ static struct cfi_fixup cfi_nopri_fixup_table[] = { { CFI_MFR_SST, 0x234a, fixup_sst39vf }, /* SST39VF1602 */ @@ -361,6 +400,7 @@ { CFI_MFR_SST, 0x235d, fixup_sst39vf_rev_b }, /* SST39VF3201B */ { CFI_MFR_SST, 0x236c, fixup_sst39vf_rev_b }, /* SST39VF6402B */ { CFI_MFR_SST, 0x236d, fixup_sst39vf_rev_b }, /* SST39VF6401B */ + { CFI_MFR_ST, 0x227e, fixup_m29w128g_write_buffer, }, { 0, 0, NULL } }; @@ -554,13 +594,20 @@ */ if (extp->MajorVersion != '1' || (extp->MajorVersion == '1' && (extp->MinorVersion < '0' || extp->MinorVersion > '5'))) { - printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " - "version %c.%c (%#02x/%#02x).\n", - extp->MajorVersion, extp->MinorVersion, - extp->MajorVersion, extp->MinorVersion); - kfree(extp); - kfree(mtd); - return NULL; + if (cfi->mfr == MANUFACTURER_SAMSUNG && + (extp->MajorVersion == '3' && extp->MinorVersion == '3')) { + printk(KERN_NOTICE " Newer Samsung flash detected, " + "should be compatibile with Amd/Fujitsu.\n"); + } + else { + printk(KERN_ERR " Unknown Amd/Fujitsu Extended Query " + "version %c.%c (%#02x/%#02x).\n", + extp->MajorVersion, extp->MinorVersion, + extp->MajorVersion, extp->MinorVersion); + kfree(extp); + kfree(mtd); + return NULL; + } } printk(KERN_INFO " Amd/Fujitsu Extended Query version %c.%c.\n", @@ -782,6 +829,7 @@ case FL_ERASING: if (!cfip || !(cfip->EraseSuspend & (0x1|0x2)) || !(mode == FL_READY || mode == FL_POINT || + (chip->in_progress_block_addr == adr) || (mode == FL_WRITING && (cfip->EraseSuspend & 0x2)))) goto sleep; @@ -807,7 +855,8 @@ * routine to recover from it) or we trying to * use the erase-in-progress sector. */ put_chip(map, chip, adr); - printk(KERN_ERR "MTD %s(): chip not ready after erase suspend\n", __func__); + printk(KERN_ERR "MTD %s(): chip not ready after erase suspend " + "(requested chip mode: %u)\n", __func__, mode); return -EIO; } @@ -840,10 +889,10 @@ default: sleep: set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); mutex_lock(&chip->mutex); goto resettime; } @@ -990,10 +1039,10 @@ while (chip->state != FL_XIP_WHILE_ERASING) { DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); mutex_lock(&chip->mutex); } /* Disallow XIP again */ @@ -1154,12 +1203,12 @@ if (chip->state != FL_READY){ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); timeo = jiffies + HZ; goto retry; @@ -1290,10 +1339,10 @@ DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); timeo = jiffies + (HZ / 2); /* FIXME */ mutex_lock(&chip->mutex); continue; @@ -1360,12 +1409,12 @@ if (cfi->chips[chipnum].state != FL_READY) { set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_add_wait_queue(&cfi->chips[chipnum].wq, &wait); mutex_unlock(&cfi->chips[chipnum].mutex); - schedule(); - remove_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&cfi->chips[chipnum].wq, &wait); goto retry; } @@ -1431,12 +1480,12 @@ if (cfi->chips[chipnum].state != FL_READY) { set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_add_wait_queue(&cfi->chips[chipnum].wq, &wait); mutex_unlock(&cfi->chips[chipnum].mutex); - schedule(); - remove_wait_queue(&cfi->chips[chipnum].wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&cfi->chips[chipnum].wq, &wait); goto retry1; } @@ -1533,10 +1582,10 @@ DECLARE_WAITQUEUE(wait, current); set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); timeo = jiffies + (HZ / 2); /* FIXME */ mutex_lock(&chip->mutex); continue; @@ -1942,10 +1991,10 @@ if (chip->state != FL_ERASING) { /* Someone's suspended the erase. Sleep */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); mutex_lock(&chip->mutex); continue; } @@ -2031,10 +2080,10 @@ if (chip->state != FL_ERASING) { /* Someone's suspended the erase. Sleep */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_schedule(); + cfi_remove_wait_queue(&chip->wq, &wait); mutex_lock(&chip->mutex); continue; } @@ -2423,13 +2472,13 @@ default: /* Not an idle state */ set_current_state(TASK_UNINTERRUPTIBLE); - add_wait_queue(&chip->wq, &wait); + cfi_add_wait_queue(&chip->wq, &wait); mutex_unlock(&chip->mutex); - schedule(); + cfi_schedule(); - remove_wait_queue(&chip->wq, &wait); + cfi_remove_wait_queue(&chip->wq, &wait); goto retry; }