ISA IRQ autodetection on SMP / 2.2.10 (more info)

Linux Lists (lists@cyclades.com)
Thu, 1 Jul 1999 10:45:25 -0700 (PDT)


Hello,

Some additional information:

- Compiling the kernel as UP in the SMP system makes the detection work
flawlessly as well;

Question: does the theory of the other CPU clearing up the interrupt
generated by the card (see attached -- original -- msg) make sense ??

What else would I need to take care of ??

Regards,
Ivan

---------- Forwarded message ----------
Date: Wed, 30 Jun 1999 18:53:39 -0700 (PDT)
From: Linux Lists <lists@cyclades.com>
To: Linux Kernel List <linux-kernel@vger.rutgers.edu>
Subject: ISA IRQ autodetection on SMP / 2.2.10

Hello,

I'm finally changing the ISA IRQ autodetection scheme on the Cyclades
async driver from the nasty wild_interrupts scheme from the ol'days to a
scheme that calls probe_irq_[on,off].

With the help of serial.c, I came up with the following code:

static unsigned detect_isa_irq (volatile ucchar *address)
{
unsigned long irq, irqs, flags, timeout;
int save_xir, save_car, i;
int index = 0; /* IRQ probing is only for ISA */

/* forget possible initially masked and pending IRQ */
irq = probe_irq_off(probe_irq_on());

/* Clear interrupts on the board first */
cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0);
/* Cy_ClrIntr is 0x1800 */

irqs = probe_irq_on();
/* Wait ... */
timeout = jiffies+(HZ/50);
while (time_after_eq(timeout, jiffies))
;

/* Enable the Tx interrupts on the CD1400 */
save_flags(flags); cli();
cy_writeb((u_long)address + (CyCAR<<index), 0);
cyy_issue_cmd(address, CyCHAN_CTL|CyENB_XMTR, index);
cy_writeb((u_long)address + (CySRER<<index),
cy_readb(address + (CySRER<<index)) | CyTxMpty);
restore_flags(flags);

/* Wait ... */
timeout = jiffies+(HZ/50);
while (time_after_eq(timeout, jiffies))
;

/* Check which interrupt is in use */
irq = probe_irq_off(irqs);

/* Clean up */
save_xir = (u_char) cy_readb(address + (CyTIR<<index));
save_car = cy_readb(address + (CyCAR<<index));
cy_writeb((u_long)address + (CyCAR<<index), (save_xir & 0x3));
cy_writeb((u_long)address + (CySRER<<index),
cy_readb(address + (CySRER<<index)) & ~CyTxMpty);
cy_writeb((u_long)address + (CyTIR<<index), (save_xir & 0x3f));
cy_writeb((u_long)address + (CyCAR<<index), (save_car));
cy_writeb((u_long)address + (Cy_ClrIntr<<index), 0);
/* Cy_ClrIntr is 0x1800 */

return (irq > 0)? irq : 0;
}

Basically, what it does is as follows:

- Clear the probe;
- Clear any interrupts that might be on the board;
- Start the probe;
- Wait (2ms);
- Enable interrupts on the board;
- Wait (2ms);
- Check for interrupts generated by the board;
- Clean up (disable board interrupts, clear any interrupts generated by
it, etc.);
- Return the IRQ found;

In UP, this routine _always_ works flawlessly. However, in SMP, it rarely
works !! It seems that the IRQ was generated, but the CPU that's running
the routine does not see it ... (this is just an idea -- a nasty one, I
might say -- that came out of my mind). Then, the function returns 0
(zero) and the IRQ autodetection fails ... :(

Does anybody have any idea on what could be wrong ?? Can anyone help me ??

Thanks in advance !!

Regards,
Ivan

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/