Resubmitting patch after feedback from Grant Coady and Willy Tarreau.
Changed description and erroneous diff output for dontdiff file.
We are running a Timesys modified version of the 2.4 kernel.
Occasionally we see board lockups on heavy file system and direct MTD
flash accesses. I have traced this down to a bug in the 2.4 MTD code
(chip driver to be specific) and see this problem even in the latest 2.4
kernel (2.4.32). I realize that this problem may not be seen by others
using the stock kernel, but I think it needs to be fixed anyway for
correctness.
The problem is in cfi_cmdset_0001.c, and is present in drivers for other
chips as well. In the function cfi_intelext_sync() function before
calling schedule(), the current process needs to be put to sleep by
calling set_current_state(TASK_UNINTERRUPTIBLE). If it is not put to
sleep, the task remains in the run queue of the kernel and if its
priority is high enough, the kernel will constantly keep scheduling this
process, the state of the chip will never change.
Adding this one line seems to make our lockups go away. There were
questions raised as to why TASK_UNINTERRUPTIBLE. The same driver uses
TASK_UNINTERRUPTIBLE in other similar places while waiting for hardware
to complete erasing etc. I chose the same thing.
I am not subscribed to the mailing list, so please CC me on any replies.
Signed-off-by: Vijay Sampath <[email protected]>
---
diff -uprN -X linux-2.4.32/Documentation/dontdiff
linux-2.4.32/drivers/mtd/chips/amd_flash.c
/home/vsampath/my-linux-2.4.32/drivers/mtd/chips/amd_flash.c
--- linux-2.4.32/drivers/mtd/chips/amd_flash.c 2003-06-13
07:51:34.000000000 -0700
+++ /home/vsampath/my-linux-2.4.32/drivers/mtd/chips/amd_flash.c
2005-12-17 14:55:20.000000000 -0800
@@ -1350,6 +1350,7 @@ static void amd_flash_sync(struct mtd_in
default:
/* Not an idle state */
+ set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex);
diff -uprN -X linux-2.4.32/Documentation/dontdiff
linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0001.c
/home/vsampath/my-linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0001.c 2004-11-17
03:54:21.000000000 -0800
+++ /home/vsampath/my-linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0001.c
2005-12-17 14:53:42.000000000 -0800
@@ -1687,6 +1687,7 @@ static void cfi_intelext_sync (struct mt
default:
/* Not an idle state */
+ set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
spin_unlock(chip->mutex);
diff -uprN -X linux-2.4.32/Documentation/dontdiff
linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c
/home/vsampath/my-linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c 2004-11-17
03:54:21.000000000 -0800
+++ /home/vsampath/my-linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0002.c
2005-12-17 14:53:58.000000000 -0800
@@ -1172,6 +1172,7 @@ static void cfi_amdstd_sync (struct mtd_
default:
/* Not an idle state */
+ set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
cfi_spin_unlock(chip->mutex);
diff -uprN -X linux-2.4.32/Documentation/dontdiff
linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0020.c
/home/vsampath/my-linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0020.c
--- linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0020.c 2004-11-17
03:54:21.000000000 -0800
+++ /home/vsampath/my-linux-2.4.32/drivers/mtd/chips/cfi_cmdset_0020.c
2005-12-17 14:54:09.000000000 -0800
@@ -1036,6 +1036,7 @@ static void cfi_staa_sync (struct mtd_in
default:
/* Not an idle state */
+ set_current_state(TASK_UNINTERRUPTIBLE);
add_wait_queue(&chip->wq, &wait);
spin_unlock_bh(chip->mutex);
Hi Vijay,
On Sun, Dec 18, 2005 at 10:50:54AM -0800, Vijay Sampath wrote:
> Resubmitting patch after feedback from Grant Coady and Willy Tarreau.
> Changed description and erroneous diff output for dontdiff file.
>
>
> We are running a Timesys modified version of the 2.4 kernel.
> Occasionally we see board lockups on heavy file system and direct MTD
> flash accesses. I have traced this down to a bug in the 2.4 MTD code
> (chip driver to be specific) and see this problem even in the latest 2.4
> kernel (2.4.32). I realize that this problem may not be seen by others
> using the stock kernel, but I think it needs to be fixed anyway for
> correctness.
>
> The problem is in cfi_cmdset_0001.c, and is present in drivers for other
> chips as well. In the function cfi_intelext_sync() function before
> calling schedule(), the current process needs to be put to sleep by
> calling set_current_state(TASK_UNINTERRUPTIBLE). If it is not put to
> sleep, the task remains in the run queue of the kernel and if its
> priority is high enough, the kernel will constantly keep scheduling this
> process, the state of the chip will never change.
>
> Adding this one line seems to make our lockups go away. There were
> questions raised as to why TASK_UNINTERRUPTIBLE. The same driver uses
> TASK_UNINTERRUPTIBLE in other similar places while waiting for hardware
> to complete erasing etc. I chose the same thing.
OK, that seems reasonnable. Thanks for the explanation.
I'm queuing it for the -hf tree.
> I am not subscribed to the mailing list, so please CC me on any replies.
>
> Signed-off-by: Vijay Sampath <[email protected]>
>
Thanks,
Willy