From: Stefano Babic <stefano.babic@siemens.com>
To: David Woodhouse <dwmw2@infradead.org>
Cc: linux-mtd@lists.infradead.org
Subject: Re: Concurrency erase/write on the same AMD chip with not aligned words
Date: 08 Aug 2003 08:42:32 +0200 [thread overview]
Message-ID: <1060324952.24780.115.camel@mhw42463> (raw)
In-Reply-To: <1060252618.25209.31.camel@passion.cambridge.redhat.com>
[-- Attachment #1: Type: text/plain, Size: 240 bytes --]
On Thu, 2003-08-07 at 12:36, David Woodhouse wrote:
>
> I haven't seen it personally, but it definitely looks like you're right.
> Please could you send a patch?
Hi David,
I send you the patch file for the cfi_cmdset_0002.c .
stefano
[-- Attachment #2: patch_cficmdset_0002 --]
[-- Type: text/x-patch, Size: 13411 bytes --]
diff -Naur mtd-snapshot-2003071/cfi_cmdset_0002.c new/cfi_cmdset_0002.c
--- mtd-snapshot-2003071/cfi_cmdset_0002.c Fri Aug 8 08:31:20 2003
+++ new/cfi_cmdset_0002.c Fri Aug 8 08:32:08 2003
@@ -238,7 +238,7 @@
break;
default:
- printk(KERN_WARNING "Unsupported buswidth\n");
+ printk(KERN_WARNING "Unsupported buswidth %d\n",CFIDEV_BUSWIDTH);
goto setup_err;
break;
}
@@ -468,10 +468,11 @@
static int do_write_oneword(struct map_info *map, struct flchip *chip, unsigned long adr, cfi_word datum, int fast)
{
unsigned long timeo = jiffies + HZ;
- unsigned int oldstatus, status, prev_oldstatus, prev_status;
- unsigned int dq6;
struct cfi_private *cfi = map->fldrv_priv;
+ cfi_word oldstatus, status, prev_oldstatus, prev_status;
+ cfi_word dq6;
+
/* We use a 1ms + 1 jiffies generic timeout for writes (most devices have
a max write time of a few hundreds usec). However, we should use the
maximum timeout value given by the chip at probe time instead.
@@ -484,7 +485,7 @@
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ta = 0;
-
+
retry:
cfi_spin_lock(chip->mutex);
@@ -512,7 +513,12 @@
chip->state = FL_WRITING;
adr += chip->start;
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n",
+ status = cfi_read(map, adr);
+
+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): READ 0x%.8lx(0x%.8x)\n",
+ __func__, adr, status );
+
+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): WRITE 0x%.8lx(0x%.8x)\n",
__func__, adr, datum );
ENABLE_VPP(map);
@@ -557,6 +563,7 @@
* - Thayne Harbaugh
*/
dq6 = CMD(1<<6);
+
/* See comment above for timeout value. */
timeo = jiffies + uWriteTimeout;
@@ -591,6 +598,7 @@
} else
udelay(1);
+
oldstatus = cfi_read( map, adr );
status = cfi_read( map, adr );
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
@@ -623,13 +631,13 @@
}
if ( ta ) {
- int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
+ cfi_word dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
if ( status & dq5mask ) {
/* dq5 asserted - decode interleave chips */
printk( KERN_WARNING
- "MTD %s(): FLASH internal timeout: 0x%.8x\n",
+ "MTD %s(): FLASH internal timeout: 0x%.8x 0x%.8x 0x%.8x\n",
__func__,
- status & dq5mask );
+ status & dq5mask, status, datum );
} else {
printk( KERN_WARNING
"MTD %s(): Software timed out during write.\n",
@@ -675,6 +683,7 @@
int ret = 0;
int chipnum;
unsigned long ofs, chipstart;
+ DECLARE_WAITQUEUE(wait, current);
*retlen = 0;
if (!len)
@@ -683,7 +692,7 @@
chipnum = to >> cfi->chipshift;
ofs = to - (chipnum << cfi->chipshift);
chipstart = cfi->chips[chipnum].start;
-
+
/* If it's not bus-aligned, do the first byte write */
if (ofs & (CFIDEV_BUSWIDTH-1)) {
unsigned long bus_ofs = ofs & ~(CFIDEV_BUSWIDTH-1);
@@ -692,10 +701,36 @@
u_char tmp_buf[sizeof(cfi_word)];
cfi_word datum;
- map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
- while (len && i < CFIDEV_BUSWIDTH)
- tmp_buf[i++] = buf[n++], len--;
+ retry:
+ cfi_spin_lock(cfi->chips[chipnum].mutex);
+ if (cfi->chips[chipnum].state != FL_READY) {
+#if 0
+ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
+#endif
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&cfi->chips[chipnum].wq, &wait);
+
+ cfi_spin_unlock(cfi->chips[chipnum].mutex);
+
+ schedule();
+ remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
+#if 0
+ printk(KERN_DEBUG "Wake up to write:\n");
+ if(signal_pending(current))
+ return -EINTR;
+#endif
+ goto retry;
+ }
+
+ map->copy_from(map, tmp_buf, bus_ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
+
+ cfi_spin_unlock(cfi->chips[chipnum].mutex);
+
+ while (len && i < CFIDEV_BUSWIDTH) {
+ tmp_buf[i++] = buf[n++];
+ len--;
+ }
if (cfi_buswidth_is_2()) {
datum = *(__u16*)tmp_buf;
} else if (cfi_buswidth_is_4()) {
@@ -794,7 +829,32 @@
u_char tmp_buf[sizeof(cfi_word)];
cfi_word datum;
+ retry1:
+ cfi_spin_lock(cfi->chips[chipnum].mutex);
+
+ if (cfi->chips[chipnum].state != FL_READY) {
+#if 0
+ printk(KERN_DEBUG "Waiting for chip to write, status = %d\n", cfi->chips[chipnum].state);
+#endif
+ set_current_state(TASK_UNINTERRUPTIBLE);
+ add_wait_queue(&cfi->chips[chipnum].wq, &wait);
+
+ cfi_spin_unlock(cfi->chips[chipnum].mutex);
+
+ schedule();
+ remove_wait_queue(&cfi->chips[chipnum].wq, &wait);
+#if 0
+ printk(KERN_DEBUG "Wake up to write:\n");
+ if(signal_pending(current))
+ return -EINTR;
+#endif
+ goto retry1;
+ }
+
map->copy_from(map, tmp_buf, ofs + cfi->chips[chipnum].start, CFIDEV_BUSWIDTH);
+
+ cfi_spin_unlock(cfi->chips[chipnum].mutex);
+
while (len--)
tmp_buf[i++] = buf[n++];
@@ -822,16 +882,17 @@
static inline int do_erase_chip(struct map_info *map, struct flchip *chip)
{
- unsigned int oldstatus, status, prev_oldstatus, prev_status;
- unsigned int dq6;
unsigned long timeo = jiffies + HZ;
unsigned long int adr;
struct cfi_private *cfi = map->fldrv_priv;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ta = 0;
- cfi_word ones = 0;
+ cfi_word status, prev_status;
+ cfi_word dq7, dq5;
+ cfi_word ones = 0;
+
retry:
cfi_spin_lock(chip->mutex);
@@ -879,15 +940,14 @@
* command to the chip.
*/
/* see comments in do_write_oneword */
- dq6 = CMD(1<<6);
+ dq7 = CMD(1<<7);
+ dq5 = CMD(1<<5);
- oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
-
- while( ( ( status ^ oldstatus ) & dq6 )
- && ! ( ta = time_after(jiffies, timeo) ) ) {
+
+ while( ((status & dq7) != dq7) &&
+ ((status & dq5) != dq5) &&
+ ! ( ta = time_after(jiffies, timeo) ) ) {
int wait_reps;
/* an initial short sleep */
@@ -916,8 +976,9 @@
/* Busy wait for 1/10 of a milisecond */
for(wait_reps = 0;
- (wait_reps < 100)
- && ( ( status ^ oldstatus ) & dq6 );
+ (wait_reps < 100) &&
+ ((status & dq7) != dq7) &&
+ ((status & dq5) != dq5);
wait_reps++) {
/* Latency issues. Drop the lock, wait a while and retry */
@@ -926,23 +987,17 @@
cfi_udelay(1);
cfi_spin_lock(chip->mutex);
- oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
}
- oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
+ __func__, status );
}
- prev_oldstatus = oldstatus;
prev_status = status;
- oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
+ __func__, status );
if ( cfi_buswidth_is_1() ) {
ones = (__u8)~0;
@@ -950,18 +1005,20 @@
ones = (__u16)~0;
} else if ( cfi_buswidth_is_4() ) {
ones = (__u32)~0;
+ } else if ( cfi_buswidth_is_8() ) {
+ ones = (__u64)~0;
} else {
- printk(KERN_WARNING "Unsupported buswidth\n");
+ printk(KERN_WARNING "Unsupported buswidth %d\n",CFIDEV_BUSWIDTH);
goto erase_failed;
}
- if ( oldstatus == ones && status == ones ) {
+ if ( prev_status == ones && status == ones ) {
/* success - do nothing */
goto erase_done;
}
if ( ta ) {
- int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
+ cfi_word dq5mask = ( ( status ^ prev_status ) & dq7 ) >> 2;
if ( status & dq5mask ) {
/* dq5 asserted - decode interleave chips */
printk( KERN_WARNING
@@ -981,10 +1038,9 @@
__func__ );
printk(KERN_WARNING
- "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
+ "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x\n",
__func__, adr, ones,
- prev_oldstatus, prev_status,
- oldstatus, status);
+ prev_status, status);
erase_failed:
ret = -EIO;
@@ -1003,15 +1059,17 @@
static inline int do_erase_oneblock(struct map_info *map, struct flchip *chip, unsigned long adr)
{
- unsigned int oldstatus, status, prev_oldstatus, prev_status;
- unsigned int dq6;
unsigned long timeo = jiffies + HZ;
struct cfi_private *cfi = map->fldrv_priv;
DECLARE_WAITQUEUE(wait, current);
int ret = 0;
int ta = 0;
+ int i;
+
+ cfi_word status, prev_status;
+ cfi_word dq7, dq5;
cfi_word ones = 0;
-
+
retry:
cfi_spin_lock(chip->mutex);
@@ -1035,7 +1093,7 @@
chip->state = FL_ERASING;
adr += chip->start;
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8lx\n",
+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): ERASE 0x%.8x 0x%.8x\n",
__func__, adr );
ENABLE_VPP(map);
@@ -1044,7 +1102,6 @@
cfi_send_gen_cmd(0x80, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
cfi_send_gen_cmd(0xAA, cfi->addr_unlock1, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
cfi_send_gen_cmd(0x55, cfi->addr_unlock2, chip->start, map, cfi, CFI_DEVICETYPE_X8, NULL);
-
cfi_write(map, CMD(0x30), adr);
timeo = jiffies + (HZ*20);
@@ -1055,19 +1112,21 @@
* The toggling stops as soon as the procedure is completed.
*
* If the process has gone on for too long on the chip bit 5 gets.
- * After bit5 is set you can kill the operation by sending a reset
+ * After bit5 is set you can kill the operation by Wackysending a reset
* command to the chip.
*/
/* see comments in do_write_oneword */
- dq6 = CMD(1<<6);
+ dq7 = CMD(1<<7);
+ dq5 = CMD(1<<5);
- oldstatus = cfi_read(map, adr);
- status = cfi_read(map, adr);
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
+ status = cfi_read(map, adr);
- while( ( ( status ^ oldstatus ) & dq6 )
- && ! ( ta = time_after(jiffies, timeo) ) ) {
+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x\n",
+ __func__, status );
+
+ while( ((status & dq7) != dq7) &&
+ ((status & dq5) != dq5) &&
+ !( ta = time_after(jiffies, timeo) )) {
int wait_reps;
/* an initial short sleep */
@@ -1096,9 +1155,10 @@
/* Busy wait for 1/10 of a milisecond */
for(wait_reps = 0;
- (wait_reps < 100)
- && ( ( status ^ oldstatus ) & dq6 );
- wait_reps++) {
+ (wait_reps < 100) &&
+ ((status & dq7) != dq7) &&
+ ((status & dq5) != dq5);
+ wait_reps++) {
/* Latency issues. Drop the lock, wait a while and retry */
cfi_spin_unlock(chip->mutex);
@@ -1106,23 +1166,19 @@
cfi_udelay(1);
cfi_spin_lock(chip->mutex);
- oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
+ __func__, status );
}
- oldstatus = cfi_read(map, adr);
status = cfi_read(map, adr);
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x\n",
+ __func__, status );
}
+ prev_status = status;
+ status = cfi_read(map, adr);
- prev_oldstatus = oldstatus;
- prev_status = status;
- oldstatus = cfi_read(map, adr);
- status = cfi_read(map, adr);
- DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x 0x%.8x\n",
- __func__, oldstatus, status );
+ DEBUG( MTD_DEBUG_LEVEL3, "MTD %s(): Check 0x%.8x\n",
+ __func__, status );
if ( cfi_buswidth_is_1() ) {
ones = (__u8)~0;
@@ -1130,18 +1186,20 @@
ones = (__u16)~0;
} else if ( cfi_buswidth_is_4() ) {
ones = (__u32)~0;
+ } else if ( cfi_buswidth_is_8() ) {
+ ones = (__u64)~0;
} else {
- printk(KERN_WARNING "Unsupported buswidth\n");
+ printk(KERN_WARNING "Unsupported buswidth %d\n",CFIDEV_BUSWIDTH);
goto erase_failed;
}
- if ( oldstatus == ones && status == ones ) {
+ if ( prev_status == ones && status == ones ) {
/* success - do nothing */
goto erase_done;
}
if ( ta ) {
- int dq5mask = ( ( status ^ oldstatus ) & dq6 ) >> 1;
+ cfi_word dq5mask = ( ( status ^ prev_status ) & dq7 ) >> 2;
if ( status & dq5mask ) {
/* dq5 asserted - decode interleave chips */
printk( KERN_WARNING
@@ -1161,10 +1219,9 @@
__func__ );
printk(KERN_WARNING
- "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x 0x%.8x 0x%.8x\n",
+ "MTD %s(): 0x%.8lx(0x%.8x): 0x%.8x 0x%.8x\n",
__func__, adr, ones,
- prev_oldstatus, prev_status,
- oldstatus, status);
+ prev_status, status);
erase_failed:
ret = -EIO;
@@ -1174,6 +1231,7 @@
erase_done:
DISABLE_VPP(map);
+
chip->state = FL_READY;
wake_up(&chip->wq);
cfi_spin_unlock(chip->mutex);
next prev parent reply other threads:[~2003-08-08 6:42 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2003-08-05 10:12 Concurrency erase/write on the same AMD chip with not aligned words Stefano Babic
2003-08-07 10:36 ` David Woodhouse
2003-08-08 6:42 ` Stefano Babic [this message]
2003-08-14 19:30 ` Thayne Harbaugh
2003-10-17 20:54 ` Thayne Harbaugh
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1060324952.24780.115.camel@mhw42463 \
--to=stefano.babic@siemens.com \
--cc=dwmw2@infradead.org \
--cc=linux-mtd@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox