[3550] in linux-scsi channel archive

home help back first fref pref prev next nref lref last post

Re: spinlocks in SCSI code

daemon@ATHENA.MIT.EDU (Doug Ledford)
Tue Mar 17 19:48:20 1998

Date: 	Tue, 17 Mar 1998 18:32:27 -0600
From: Doug Ledford <dledford@dialnet.net>
To: Kurt Garloff <garloff@kg1.ping.de>
CC: linux-scsi@vger.rutgers.edu, "Leonard N. Zubkoff" <lnz@dandelion.com>,
        Gerard Roudier <groudier@club-internet.fr>

Kurt Garloff wrote:
> 
> On Tue, Mar 17, 1998 at 01:29:50PM +0100, Kurt Garloff wrote:
> > Well, as a first test, I implemented this for the ncr53c8xx driver, as I'm
> > able to test it directly. Of course it works very well, as I have a UP
> > machine and the spin_lock_irqsave (); does exactly the same as save_flags();
> > cli();
> >
> > Too bad I don't have a SMP machine to test.
> 
> Well, I can compile a SMP kernel for my UP machine.
> There's one situation, I didn't think of:
> The driver could try to lock the kernel twice, which will result in a
> deadlock. With the save_flags(); cli(); syntax, this was not detected, but
> with the spin_lock(); this will cause a hang.
> 
> There are at least two places in the ncr53c8xx driver where this occurs:
> 1) ncr_timeout(): requeue_waiting_list(); is called which will call
>    ncr_queue_command() which tries to get the spinlock.
> 2) ncr_complete() is called from within ncr_exception(), the interrupt
>    handler, which holds the lock. ncr_complete() calls
>    requeue_waiting_list().
> 
> As a workaround, I added two spin_unlock() [without the _irqrestore] insns
> at the places where requeue_ ... is called. This is no clean solution, though.

Although I'm not the worlds foremost expert on spin locks, I would have to
guess that this would be, umm, problematic.  You need to use the actual
spin_unlock_irqrestore() function instead so that the cli() doesn't get
released earlyier than planned.  The problem I'm thinking of is this:

spin_lock_irqsave();   [ interrupts turned off ]
spin_unlock();         [ lock released, interrupts off ]
function();
  spin_lock_irqsave(); [ lock restored, interrupts turned off again ]
  ...
  spin_unlock_irqrestore(); [ lock released, interrupts *enabled* ]
  return();
spin_lock();           [ lock restored, interrupts untouched and on ]
spin_unlock_irqrestore(); [ lock released, interrupts turned on,
                            but they were already on anyway ]

In short, I'm not sure, but I don't think the spin_lock_irqsave() and
associated functions are completely nestable.  I would check to find out
before relying on these locks too much :)
-- 

 Doug Ledford  <dledford@dialnet.net>
  Opinions expressed are my own, but
     they should be everybody's.

-
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.rutgers.edu

home help back first fref pref prev next nref lref last post