Messages in this thread Patch in this message |  | | Date | Thu, 7 Sep 2000 18:26:12 +0200 (CEST) | From | Andrea Arcangeli <> | Subject | Re: DAC960 SMP deadlock fix |
| |
On Thu, 7 Sep 2000, Leonard N. Zubkoff wrote:
>I tried retrieving that file but was unsuccessful; is that the correct URL?
I guess I cut and pasted too much directories, sorry. I attached the file since it's small.
>Is the fix simply moving the spin_unlock right before the call to >add_wait_queue?
A little more, we also have to make sure not to miss events and the __wait_event interfaces addersses that second issue.
>I should be able to release a new driver very shortly with such a fix; I >just have one or two other minor nits I'm finishing up.
Good, thanks!
Andrea After reading the two NMI dumps and the assembler of the .text.lock section of the vmlinux ELF image I think I found it.
It seems a regular SMP lock inversion in the DAC960 driver that is acquiring the waitqueue_lock with the io_request_lock still acquired. Here the trace that I deducted:
CPU0 CPU1 ------------------ --------------- spin_lock_irqsave(&io_request_lock) DAC9xx_request_fn() wake_up(something...) read_lock(&waitqueue_lock) aic7xxx_irq_handler() DAC9xx_WaitForCommand() add_to_wait_queue(something....) write_lock_irqsave(&waitqueue_lock) /* hanging because of the read_lock on the other side */ spin_lock_irqsave(&io_request_lock) /* hanging because it's acquired from the other side */
/* DEADLOCK */
Here the fix (uncompiled and untested):
--- 2.2.18pre2aa2/drivers/block/DAC960.c Wed Aug 30 03:42:29 2000 +++ /tmp/DAC960.c Thu Sep 7 02:10:39 2000 @@ -310,13 +310,8 @@ static void DAC960_WaitForCommand(DAC960_Controller_T *Controller) { - WaitQueue_T WaitQueueEntry = { current, NULL }; - add_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); - current->state = TASK_UNINTERRUPTIBLE; spin_unlock(&io_request_lock); - schedule(); - current->state = TASK_RUNNING; - remove_wait_queue(&Controller->CommandWaitQueue, &WaitQueueEntry); + __wait_event(Controller->CommandWaitQueue, Controller->FreeCommands); spin_lock_irq(&io_request_lock); } |  |