[3389] in linux-scsi channel archive

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

Re: Race in AHA1542 detection

daemon@ATHENA.MIT.EDU (Keith Owens)
Mon Feb 23 18:55:34 1998

From: Keith Owens <kaos@ocs.com.au>
To: Eric Youngdale <eric@andante.jic.com>
cc: linux-scsi@vger.rutgers.edu
In-reply-to: Your message of "Mon, 23 Feb 1998 09:09:46 CDT."
             <Pine.LNX.3.95.980223090042.16823E-100000@andante.jic.com> 
Date: 	Tue, 24 Feb 1998 09:12:20 +1100

On Mon, 23 Feb 1998 09:09:46 -0500 (EST), 
Eric Youngdale <eric@andante.jic.com> wrote:
>	First of all, I don't really know what the APIC patches were for.
>Could someone explain this, and tell me when it went into the kernel?
>Also, what does pirq=0 mean?

Copied to the list in case it is useful for other SCSI drivers.  Any
driver relying on cli/sti may have problems with IO-APIC.

Ingo Molnar's patches to allow interrupts to be serviced by *any* cpu
on an SMP machine.  Once more step (a big one) in multi threading the
kernel.  Experimental patches came out around 2.1.84, it is now
integrated into the kernel.  pirq=0 was originally required to activate
this feature for my motherboard, it is no longer required.  See
Documentation/IO-APIC.txt.  /proc/interrupts looks like this

Without apic.  All interrupts on one processor.

           CPU0       CPU1       
  0:       8075          0   XT PIC   timer
  1:        147          0   XT PIC   keyboard
  2:          0          0   XT PIC   cascade
  3:          3          0   XT PIC   serial
  4:          4          0   XT PIC   serial
 10:          7          0   XT PIC   aha1542
 11:       5084          0   XT PIC   ncr53c8xx
 13:          4          0   XT PIC   fpu
 15:       2890          0   XT PIC   NE2000
NMI:          0
IPI:          0

With apic.  Most interrupts can be handled by either cpu.

           CPU0       CPU1       
  0:      10573      31038  IO-APIC   timer
  1:        189        712  IO-APIC   keyboard
  2:          0          0   XT PIC   cascade
  3:          1          2  IO-APIC   serial
  4:          5          0  IO-APIC   serial
 10:          6          8  IO-APIC   aha1542
 11:       6388       6284  IO-APIC   ncr53c8xx
 13:          4          0   XT PIC   fpu
 15:         35         46  IO-APIC   NE2000
NMI:          0
IPI:          0

>	Nonetheless, the thing that confuses me is that the mailboxes are
>set up before the interrupt handler is registered.  Thus I cannot quite
>see how things could get fouled up in this fashion, but until I know more
>about what the APIC stuff is doing, I am flying blind.
>
>	Maybe I am reading the stuff below wrong, but it almost looks like
>both processors are running the aha1542_detect() routine.   If this is
>true, it is almost certainly not correct.

setup_mailboxes, aha1542_out, aha1542_detect are all running on cpu(0),
pid(1).  aha1542_detect calls request_irq on cpu(0) then proceeds to do
the DMA work.  With apic, after the irq has been assigned, cpu(1) takes
an interrupt before aha1542_detect has ended.

c01c1d27  setup_mailboxes +<13/e4> (6.31) cpu(0) pid(1)
c01c1043  aha1542_out +<13/e0> (1.17) cpu(0) pid(1)
c010cfa1  __global_save_flags +<d/40> (1.34) cpu(0) pid(1)
c010ce23  __global_cli +<f/13c> (96.23) cpu(0) pid(1)
c010cfe1  __global_restore_flags +<d/6c> (0.93) cpu(0) pid(1)
c010cf5d  __global_sti +<d/44> (45.28) cpu(0) pid(1)
c010cfa1  __global_save_flags +<d/40> (1.36) cpu(0) pid(1)
c010ce23  __global_cli +<f/13c> (2.99) cpu(0) pid(1)
c010d5ae  do_IRQ +<e/64> (2.77) cpu(1) pid(0)
c01c250f  aha1542_detect +<2a7/42c> (2.98) cpu(0) pid(1)
c010d4ac  do_ioapic_IRQ +<10/104> (2.62) cpu(1) pid(0)
c010d700  request_irq +<10/8c> (2.67) cpu(0) pid(1)
c0113afd  ack_APIC_irq +<d/28> (52.23) cpu(1) pid(0)
c012bd6f  kmalloc_wrapper +<f/3c> (1.30) cpu(0) pid(1)
c0128170  real_kmalloc +<10/188> (2.83) cpu(0) pid(1)
c012bad4  alloc_addr +<10/100> (2.56) cpu(0) pid(1)
c010d617  setup_x86_irq +<13/ec> (1.52) cpu(0) pid(1)
c010cfa1  __global_save_flags +<d/40> (1.07) cpu(0) pid(1)
c010ce23  __global_cli +<f/13c> (2.47) cpu(0) pid(1)
c010c871  set_8259A_irq_mask +<d/44> (1.42) cpu(0) pid(1)
c010c8b5  unmask_generic_irq +<d/48> (1.20) cpu(0) pid(1)
c0113105  enable_IO_APIC_irq +<11/3c> (1.04) cpu(0) pid(1)
c01130b5  io_apic_read +<d/24> (8.49) cpu(0) pid(1)
c01130d9  io_apic_write +<d/28> (1.27) cpu(0) pid(1)
c010cfe1  __global_restore_flags +<d/6c> (1.02) cpu(0) pid(1)
c010ce23  __global_cli +<f/13c> (1.88) cpu(0) pid(1)
c01c2551  aha1542_detect +<2e9/42c> (1.57) cpu(0) pid(1)
c011972a  request_dma +<e/50> (2.29) cpu(0) pid(1)
c01c25a1  aha1542_detect +<339/42c> (4.72) cpu(0) pid(1)
c01c2624  aha1542_detect +<3bc/42c> (0.87) cpu(0) pid(1)
c010cfe1  __global_restore_flags +<d/6c> (0.95) cpu(0) pid(1)
c010cf5d  __global_sti +<d/44> (1.49) cpu(0) pid(1)

**** Flags restored, cpu(0) is still in aha1542_detect and
**** aha1542_intr_handle starts running on cpu(1).

c01c262f  aha1542_detect +<3c7/42c> (2.71) cpu(0) pid(1)
c010d050  handle_IRQ_event +<10/60> (2.92) cpu(1) pid(0) <=== interrupt on cpu(1)
c01c2634  aha1542_detect +<3cc/42c> (5.07) cpu(0) pid(1)
c01c1437  aha1542_intr_handle +<13/2a8> (7.68) cpu(1) pid(0)
c0120300  request_region +<10/8c> (6.15) cpu(0) pid(1)
c010cfa1  __global_save_flags +<d/40> (3.10) cpu(1) pid(0)
c0120293  find_gap +<13/70> (3.25) cpu(0) pid(1)
c010ce23  __global_cli +<f/13c> (4.88) cpu(1) pid(0)
c010cfa1  __global_save_flags +<d/40> (4.36) cpu(0) pid(1)
c010cfe1  __global_restore_flags +<d/6c> (2.83) cpu(1) pid(0)
c010ce23  __global_cli +<f/13c> (2.68) cpu(0) pid(1)
c011ae8b  printk +<13/184> (2.29) cpu(1) pid(0)

The normal fix to this problem is to use spinlocks instead of cli/sti,
that is Linus's preferred direction.  I can do the patch, but where to
store the spinlock?  Should it be global for all 1542's in a machine or
local to each card?  My feeling is local to each card which probably
means adding a spinlock to the Scsi_Host structure.  Before I do that
and affect every other SCSI driver, it might be a good idea to agree on
how to handle apic.


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