P30 flash left in read status mode after a write
Hi,
We have a hardware architecture with a IXP455 processor that allows read access to a P30 flash attached to the IXP's expansion bus from a Pentium M that does it's access via the PCI bus. The flash has 4 partitions: Redboot, jffs2, fconfig, fis. I am running Linux 2.6.16.29 and I've found that whenever a write is done to the jffs2 filesystem that flash is left in read status mode and anything trying to do a read of flash directly reads only 0x0080. Reading from an mtd device seems to fix the problem. I modified the mapper utility from LDD3 so I could read flash directly from linux which illustrates the problem:
[root@rsc4 ~]# mapper /dev/mem 0x51fa0000 0x100 1|hexdump -C mapped "/dev/mem" from 1375338496 (0x51fa0000) to 1375338752 (0x51fa0100)
00000000 00 00 10 00 0b ad fa ce 01 0c 01 00 62 6f 6f 74 |............boot|
00000010 5f 73 63 72 69 70 74 00 00 00 00 01 04 11 01 0c |_script.........|
00000020 62 6f 6f 74 5f 73 63 72 69 70 74 5f 64 61 74 61 |boot_script_data|
00000030 00 62 6f 6f 74 5f 73 63 72 69 70 74 00 25 7b 73 |.boot_script.%{s|
00000040 6e 69 66 66 7d 0a 25 7b 67 6f 7d 0a 25 7b 66 69 |niff}.%{go}.%{fi|
00000050 78 5f 7a 49 6d 61 67 65 7d 0a 00 00 00 00 00 00 |x_zImage}.......|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*
00000100
[root@rsc4 ~]# touch xyz
[root@rsc4 ~]# mapper /dev/mem 0x51fa0000 0x100 1|hexdump -C mapped "/dev/mem" from 1375338496 (0x51fa0000) to 1375338752 (0x51fa0100) 00000000 00 80 00 80 00 80 00 80 00 80 00 80 00 80 00 80 |................| *
00000100
[root@rsc4 ~]# cat /dev/mtd2 > /dev/null
[root@rsc4 ~]# mapper /dev/mem 0x51fa0000 0x100 1|hexdump -C mapped "/dev/mem" from 1375338496 (0x51fa0000) to 1375338752 (0x51fa0100)
00000000 00 00 10 00 0b ad fa ce 01 0c 01 00 62 6f 6f 74 |............boot|
00000010 5f 73 63 72 69 70 74 00 00 00 00 01 04 11 01 0c |_script.........|
00000020 62 6f 6f 74 5f 73 63 72 69 70 74 5f 64 61 74 61 |boot_script_data|
00000030 00 62 6f 6f 74 5f 73 63 72 69 70 74 00 25 7b 73 |.boot_script.%{s|
00000040 6e 69 66 66 7d 0a 25 7b 67 6f 7d 0a 25 7b 66 69 |niff}.%{go}.%{fi|
00000050 78 5f 7a 49 6d 61 67 65 7d 0a 00 00 00 00 00 00 |x_zImage}.......|
00000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|*
00000100
It appears that the MTD_XIP code has what I need to get flash out of read status mode after a write, however, since I'm not actually doing execute in place, it's overkill for my purposes. It seems that writing a xip_enable() function that puts flash in ready mode and leaving the other xip_* functions defined as nothing was a quick way to fix the problem in my case:
static void __xipram xip_enable(struct map_info *map, struct flchip *chip,
unsigned long adr)
{
struct cfi_private *cfi = map->fldrv_priv;
if (chip->state != FL_POINT && chip->state != FL_READY) {
map_write(map, CMD(0xff), adr);
chip->state = FL_READY; }
(void) map_read(map, adr);
}
This did indeed seem to fix the problem, but I'm not sure if I might inadvertently be causing some side effect. I believe that I might be taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
Any advice would be appreciated.
Thanks,
Jon
Quoted 9 lines · Jon Ringle
Hi,
We have a hardware architecture with a IXP455 processor that allows read access to a P30 flash attached to the IXP's expansion bus from a Pentium M that does it's access via the PCI bus. The flash has 4 partitions:
Redboot, jffs2, fconfig, fis. I am running Linux 2.6.16.29 and I've found that whenever a write is done to the jffs2 filesystem that flash is left in read status mode and anything trying to do a read of flash directly reads only0x0080. Reading from an mtd device seems to fix the
Yes.
Quoted 5 lines
This did indeed seem to fix the problem, but I'm not sure if I might inadvertently be causing some side effect. I believe that I might be taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
You're probably better off changing the driver to put the chip back in read mode after directly from the write function. You will, as you correctly pointed out, incur a performance hit to consecutive JFFS2 writes.
Of course, I don't really see a problem here to being with though. Doing the reads and writes through the MTD layer (which JFFS2 does) should all work just fine. Unless you're trying to access the flash via something other than MTD. If so, that is likely going to be racy.
josh
Quoted 5 lines · Jon Ringle
I am running Linux 2.6.16.29 and I've
found that whenever a write is done to the jffs2 filesystem that flash is left in read status mode and anything trying to do a read of flash directly reads only0x0080. Reading from an mtd device seems to fix the problem.
This is done on purpose. And as you deduced yourself this is so to avoid ...
Quoted 5 lines
taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
Any advice would be appreciated.
First, why is this a problem for you?
Nicolas
Quoted 9 lines · Nicolas Pitre
Quoted 2 lines · Jon Ringle
I am running Linux 2.6.16.29 and I've found that whenever a write is done to the jffs2 filesystem that flash is left in read status mode and anything trying to do a read of flash directly reads only
0x0080. Reading from an mtd device seems to fix the problem.This is done on purpose. And as you deduced yourself this is so to avoid ...
Quoted 8 lines
Quoted 4 lines
taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
Any advice would be appreciated.
First, why is this a problem for you?
This is a problem on our (unusual) hardware because we have a Pentium M processor (not running Linux) that reads fconfig partition outside the context of the IXP processor that is running Linux. It does so via data path: Pentium -> PCI -> IXP Expansion bus -> Flash. This data path allows the Pentium to directly access the fconfig partition without needing any active code on the IXP's arm core processor to do anything to facilitate such access by the Pentium. However, when the mtd driver leaves the flash in read status mode, the Pentium just reads 0x0080 when trying to read the fconfig partition. With a change to have the mtd driver put the flash back into ready mode after a write, then I think that the Pentium only needs to deal with a temporary read failure if it happens to do a read at the same time that a write is occurring on the jffs2. In which case, the Pentium code simply spins retrying to do the read until it is successful.
Jon
Quoted 4 lines · Jon Ringle
Quoted 3 lines · Nicolas Pitre
First, why is this a problem for you?
Quoted 13 lines
This is a problem on our (unusual) hardware because we have a Pentium M processor (not running Linux) that reads fconfig partition outside the context of the IXP processor that is running Linux. It does so via data path: Pentium -> PCI -> IXP Expansion bus -> Flash. This data path allows the Pentium to directly access the fconfig partition without needing any active code on the IXP's arm core processor to do anything to facilitate such access by the Pentium. However, when the mtd driver leaves the flash in read status mode, the Pentium just reads
0x0080when trying to read the fconfig partition. With a change to have the mtd driver put the flash back into ready mode after a write, then I think that the Pentium only needs to deal with a temporary read failure if it happens to do a read at the same time that a write is occurring on the jffs2. In which case, the Pentium code simply spins retrying to do the read until it is successful.
And how do you determine that you have a read failure?
Because the flash doesn't necessarily always have 0x00800080 to show when outside of the read mode.
Of course, since you have an unusual setup you can have an unusual patch in your own kernel tree for this issue. But this isn't entirely safe since the Pentium code might be fooled by some other flash status output that doesn,t look like a read failure.
Nicolas
Quoted 24 lines · Nicolas Pitre
Quoted 6 lines · Jon Ringle
Quoted 4 lines · Nicolas Pitre
First, why is this a problem for you?
Quoted 14 lines
This is a problem on our (unusual) hardware because we have a Pentium M processor (not running Linux) that reads fconfig partition outside the context of the IXP processor that is running Linux. It does so via data path: Pentium -> PCI -> IXP Expansion bus -> Flash. This data path allows the Pentium to directly access the fconfig partition without needing any active code on the IXP's arm core processor to do anything to facilitate such access by the Pentium. However, when the mtd driver leaves the flash in read status mode, the Pentium just reads
0x0080when trying to read the fconfig partition. With a change to have the mtd driver put the flash back into ready mode after a write, then I think that the Pentium only needs to deal with a temporary read failure if it happens to do a read at the same time that a write is occurring on the jffs2. In which case, the Pentium code simply spins retrying to do the read until it is successful.
Quoted 4 lines
And how do you determine that you have a read failure?
Because the flash doesn't necessarily always have
0x00800080to show when outside of the read mode.
True. However, the data that is being read has magic values and a checksum for validity, so the likelihood of a false positive on passing these tests is extremely unlikely.
Quoted 2 lines
Of course, since you have an unusual setup you can have an unusual patch in your own kernel tree for this issue. But this isn't entirely safe since the Pentium code might be fooled by some other flash status output that doesn,t look like a read failure.
I was intending for just patching my own kernel tree for this issue, since this issue is unlikely to be of wider audience appeal. I just wanted to present my problem to people that are more knowledgeable with the mtd code as a sanity check for my solution.
Jon
Quoted 13 lines · Jon Ringle
Quoted 5 lines
And how do you determine that you have a read failure?
Because the flash doesn't necessarily always have
0x00800080to show when outside of the read mode.True. However, the data that is being read has magic values and a checksum for validity, so the likelihood of a false positive on passing these tests is extremely unlikely.
Quoted 5 lines
Of course, since you have an unusual setup you can have an unusual patch in your own kernel tree for this issue. But this isn't entirely safe since the Pentium code might be fooled by some other flash status output that doesn,t look like a read failure.
Quoted 4 lines
I was intending for just patching my own kernel tree for this issue, since this issue is unlikely to be of wider audience appeal. I just wanted to present my problem to people that are more knowledgeable with the mtd code as a sanity check for my solution.
Your solution looked sane.
Nicolas
Quoted 6 lines · Jon Ringle
This did indeed seem to fix the problem, but I'm not sure if I might inadvertently be causing some side effect. I believe that I might be taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
If the performance hit concerns you, you could set a timer instead of changing the chip state. Only if the timer expires - which means that consecutive writes are a non-issue - do you change the chip state.
Jörn
Signature · 2 lines
"Error protection by error detection and correction." -- from a university class
Quoted 10 lines · Jörn Engel
Quoted 2 lines · Jon Ringle
This did indeed seem to fix the problem, but I'm not sure if I might inadvertently be causing some side effect. I believe that I might be taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
If the performance hit concerns you, you could set a timer instead of changing the chip state. Only if the timer expires - which means that consecutive writes are a non-issue - do you change the chip state.
Using a timer sounds like a good idea. I'll keep it in mind. I'm not sure yet whether I'm concerned about the performance hit as I haven't profiled the impact yet. Has anyone got any data that shows what kind of improvement jffs2 write operations get with this optimization in place to leave flash in read status mode?
Jon
Quoted 15 lines · Jon Ringle
Quoted 9 lines · Jörn Engel
Quoted 6 lines · Jon Ringle
This did indeed seem to fix the problem, but I'm not sure if I might inadvertently be causing some side effect. I believe that I might be taking a slight performance hit to consecutive jffs2 write operations because now each write operation will need to spend more cycles putting the flash in to a write mode.
Quoted 5 lines
If the performance hit concerns you, you could set a timer instead of changing the chip state. Only if the timer expires - which means that consecutive writes are a non-issue - do you change the chip state.
Quoted 5 lines
Using a timer sounds like a good idea. I'll keep it in mind. I'm not sure yet whether I'm concerned about the performance hit as I haven't profiled the impact yet. Has anyone got any data that shows what kind of improvement jffs2 write operations get with this optimization in place to leave flash in read status mode?
It should be fairly minimal. Probably less than 5% difference.
Nicolas
HI ALL.
I'm not sure if it could help but it remind me one bug I faced over a year ago. Could you please try this fixup. It fixes improper CFI parsing in CFI drivers.
drivers/mtd/chips/cfi_cmdset_0001.c (revision 10) renamed from drivers/mtd/chips/cfi_cmdset_0001.c (revision 8) +2 -3
@@ -285,7 +285,7 @@ sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - extra_size += (extp->MinorVersion < '4') ? 6 : 5; + extra_size += (unsigned int)extp->extra[extra_size+1]+2; /* Number of hardware-partitions */ extra_size += 1;
@@ -519,7 +519,7 @@ sizeof(struct cfi_intelext_otpinfo); /* Burst Read info */ - offs += (extp->MinorVersion < '4') ? 6 : 5; + offs += (int)extp->extra[offs+1]+2; -------------------------------------
Original fix message is here:http://lists.infradead.org/pipermail/linux-mtd/2005-October/014144.html
Thanks
Alexey