Shared IRQ clarifications for Vortices/Adaptecs et al.

Ted_Rule@flextech.co.uk Ted_Rule@flextech.co.uk
Mon Feb 15 12:58:56 1999



Donald Becker has made reference here previously to his document:

http://cesdis.gsfc.nasa.gov/linux/misc/irq-conflict.html

which outlines various issues associated with Shared IRQ usage in various
drivers.

Perhaps I might seek some clarification of certain points - with particular
reference to the driver
snippets from a 2.0.36 kernel machine below....

a)   The aic7xxx.c driver snippet below performs a "request_irq SA_SHIRQ "
before a
"request_irq SA_INTERRUPT | SA_SHIRQ". Is it therefore immune from the
SA_INTERRUPT problem as
if an interrupt is available, the first call to request_irq will succeed and the
 second never gets performed?

b)   The advansys.c driver does things the other way round. So presumably it is
NOT immune to the SA_INTERRUPT
problem, and ought to be corrected?

c)   The 3c59x.c and tulip.c drivers only ever call request_irq with SA_SHIRQ. I
 take it that this is therefore the only correct way to call
request_irq? Or is this only true for a PCI device? Presumably ISA device
drivers are called with no SA_ flags - a quick glance at several
network drivers seems to suggest this is so.

d)   The ThunderLAN driver tlan.c seems to only call request_irq with
SA_INTERRUPT if its sa_int flag is set for the instance in question.
It seems this is set according to where the memory map for the card sits, and
hence whether it is or is not capable of sharing interrupts?
Hence this driver seems to be immune from the problem - perhaps!

e)   Is there a performance advantage ( significant or otherwise ) to be had
with running different cards on non-shared interrupts? In particular
is it better performance-wise to run one's 100BaseTx network card and SCSI
Controller on different IRQ's..?



Ted Rule,


Flextech Television

===========================================================================================================

scsi/aic7xxx.c:

   * Register IRQ with the kernel.  Only allow sharing IRQs with
   * PCI devices.
   */
  if (!(p->chip & AHC_PCI))
  {
    result = (request_irq(p->irq, do_aic7xxx_isr, 0, "aic7xxx", p));
  }
  else
  {
    result = (request_irq(p->irq, do_aic7xxx_isr, SA_SHIRQ,
              "aic7xxx", p));
    if (result < 0)
    {
      result = (request_irq(p->irq, do_aic7xxx_isr, SA_INTERRUPT | SA_SHIRQ,
              "aic7xxx", p));
    }
  }
  if (result < 0)
  {
    printk(KERN_WARNING "(scsi%d) Couldn't register IRQ %d, ignoring "
           "controller.\n", p->host_no, p->irq);
    p->irq = 0;
    return (0);



scsi/advansys.c:

           /*
            * If request_irq() fails with the SA_INTERRUPT flag set,
            * then try again without the SA_INTERRUPT flag set. This
            * allows IRQ sharing to work even with other drivers that
            * do not set the SA_INTERRUPT flag.
            *
            * If SA_INTERRUPT is not set, then interrupts are enabled
            * before the driver interrupt function is called.
            */
            if (((ret = request_irq(shp->irq, advansys_interrupt,
                            SA_INTERRUPT | (share_irq == TRUE ? SA_SHIRQ : 0),
                            "advansys", boardp)) != 0) &&
                ((ret = request_irq(shp->irq, advansys_interrupt,
                            (share_irq == TRUE ? SA_SHIRQ : 0),
                            "advansys", boardp)) != 0))


net/3c59x.c:

        /* Use the now-standard shared IRQ implementation. */
        if (request_irq(dev->irq, &vortex_interrupt, SA_SHIRQ, dev->name, dev))


net/tlan.c:

int TLan_Open( struct device *dev )
{
        TLanPrivateInfo *priv = (TLanPrivateInfo *) dev->priv;
        int             err;

        priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
        if ( priv->sa_int ) {
                TLAN_DBG( TLAN_DEBUG_GNRL, "TLAN:   Using SA_INTERRUPT\n" );
                err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ |
SA_INTERRUPT, TLanSignature, dev );
        } else {
                err = request_irq( dev->irq, TLan_HandleInterrupt, SA_SHIRQ,
TLanSignature, dev );
        }
        if ( err ) {
                printk( "TLAN:  Cannot open %s because IRQ %d is already in
use.\n", dev->name, dev->irq );
                return -EAGAIN;
        }


net/tulip.c:
        if (request_irq(dev->irq, &tulip_interrupt, SA_SHIRQ, dev->name, dev))
                return -EAGAIN;