Re: Linux 2.6.39 on Cavium CN38xx

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 13, 2011 at 05:10:06PM -0400, David Daney wrote:
> On 06/12/2011 09:41 AM, Guenter Roeck wrote:
> > On Fri, Jun 10, 2011 at 08:20:42PM -0400, Guenter Roeck wrote:
> > [ ... ]
> >
> >> Hi David,
> >>
> >> Turns out my primary problem is that octeon_irq_setup_secondary_ciu()
> >> sets C0_STATUS to 0x1000efe0, ie all interrupts except IP4 are enabled.
> >> This mask is primarily set through octeon_irq_percpu_enable(), which
> >> sets C0_STATUS to 0x1000e3e0. The value differs from CPU 0, where
> >> C0_STATUS is set to 0x10008ce0.
> >>
> >> This causes persistent spurious interrupts on our boards (both with
> >> CN38xx and CN58xx), where C0_CAUSE persistently reads as zero in the
> >> interrupt handling code but interrupts are triggered anyway. The
> >> spurious interrupt problem goes away if I mask out IP0, IP1, IP5, and
> >> IP6 at the end of octeon_irq_setup_secondary_ciu().
> >>
> > Answering part of my own question: The interrupt enable bits for secondary CPUs
> > are all set through octeon_irq_core_eoi(), which is called from the per-CPU
> > initialization code and enables each interrupt even if "desired_en" is false
> > for a given bit. I modified octeon_irq_core_eoi() to
> >
> > 	if (cd->desired_en)
> >                  set_c0_status(0x100<<  cd->bit);
> >
> 
> That shouldn't be needed.  The logic in irq_cpu_online() should only 
> call chip->irq_cpu_online() if the irq is enabled.
> 
Doesn't look like it. Here is some log output:

SMP: Booting CPU01 (CoreId  1)...
Core 1 ALIVE
CPU revision is: 000d0003 (Cavium Octeon)
PU 1: Calling irq_cpu_online() for irq_chip Core, flags=0x8, disabled=0
CPU 1: irq_core_eoi(enable=0, bit=0)
CPU 1: Calling irq_cpu_online() for irq_chip Core, flags=0x8, disabled=0
CPU 1: irq_core_eoi(enable=0, bit=1)
CPU 1: Calling irq_cpu_online() for irq_chip Core, flags=0x8, disabled=0
CPU 1: irq_core_eoi(enable=0, bit=5)
CPU 1: Calling irq_cpu_online() for irq_chip Core, flags=0x8, disabled=0
CPU 1: irq_core_eoi(enable=0, bit=6)
CPU 1: Calling irq_cpu_online() for irq_chip Core, flags=0x8, disabled=0
CPU 1: irq_core_eoi(enable=1, bit=7)

irqd_irq_disabled(&desc->irq_data) returns false, meaning IRQD_IRQ_DISABLED
is not set in the state_use_accessors field of irq_data for the interrupt bits
in question. If I understand the code correctly, this happens for unused 
interrupts if CONFIG_IRQ_SPARSE is not set (desc_set_defaults(), which sets the bit,
is only called if CONFIG_IRQ_SPARSE is defined).

As a result, irq_core_eoi() is called from irq_cpu_online(), even though
IRQCHIP_ONOFFLINE_ENABLED is set in irq_chip.

> 
> > which takes care of the problem. No idea if that is correct, though.
> >
> > The actual interrupt causing trouble and spurious interrupts in my case is,
> > oddly enough, STATUSF_IP0. So far I have been unable to track down how that
> > is triggered; I don't see the bit being set set in C0_CAUSE anywhere.
> >
> > Are there any means to trigger an IP0 interrupt other than by writing STATUSF_IP0
> > into the C0_CAUSE register ?
> >
> 
> No.  Nothing that I know of ever uses IP0 and IP1, so they should always 
> be cleared.
> 
Exactly what I figured, yet I still get those spurious interrupts if IP0 is enabled.
Something odd is definitely going on in my system.

Besides the above, my hopefully final problem is that timer interrupts are only
received by CPU 0. Any idea what to look for to fix this problem ?

Thanks,
Guenter



[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux