Hi Ayaz,

I know, I'm late, but:

Ayaz Abdulla wrote:


-       disable_irq(dev->irq);
+
+       if (!(np->msi_flags & NV_MSI_X_ENABLED) ||
+ ((np->msi_flags & NV_MSI_X_ENABLED) && + ((np->msi_flags & NV_MSI_X_VECTORS_MASK) == 0x1))) {
+               disable_irq(dev->irq);
+       } else {
+               disable_irq(np->msi_x_entry[NV_MSI_X_VECTOR_RX].vector);
+       }
What about adding a helper function?
static int nv_using_msi(dev)
{
   if (...)
      return 1;
   return0;
}

        if (nv_alloc_rx(dev)) {
                spin_lock(&np->lock);
                if (!np->in_shutdown)
                        mod_timer(&np->oom_kick, jiffies + OOM_REFILL);
                spin_unlock(&np->lock);

I think this is wrong, it must be spin_lock_irq() or _irqsave().
Previously, the driver knew that the nic used only one interrupt. Thus every codepath that runs either within the irq handler, or within disable_irq()/enable_irq() blocks, just used spin_lock(&np->lock). The MSI-X patch changes that: The driver has now up to 3 interrupts. Thus the rx interrupt handler could be interrupted by the tx irq handler. If the rx handler owns the spinlock, then this would deadlock.

@@ -1010,7 +1063,7 @@
        }

        if (np->tx_skbuff[skbnr]) {
-               dev_kfree_skb_irq(np->tx_skbuff[skbnr]);
+               dev_kfree_skb_any(np->tx_skbuff[skbnr]);
                np->tx_skbuff[skbnr] = NULL;
                return 1;
        } else {
What's the purpose of this change? It seems to be unrelated to the remaining patch.


+static irqreturn_t nv_nic_irq_tx(int foo, void *data, struct pt_regs *regs)
+{
+       struct net_device *dev = (struct net_device *) data;
+       struct fe_priv *np = netdev_priv(dev);
+       u8 __iomem *base = get_hwbase(dev);
+       u32 events;
+       int i;
+
+       dprintk(KERN_DEBUG "%s: nv_nic_irq_tx\n", dev->name);
+
+       for (i=0; ; i++) {
+               events = readl(base + NvRegMSIXIrqStatus) & NVREG_IRQ_TX_ALL;
+               writel(NVREG_IRQ_TX_ALL, base + NvRegMSIXIrqStatus);
+               pci_push(base);
+               dprintk(KERN_DEBUG "%s: tx irq: %08x\n", dev->name, events);
+               if (!(events & np->irqmask))
+                       break;
+
+               spin_lock(&np->lock);
Same as above - probably spin_lock_irq() is required. Theoretically, it might be possible to split the spinlock into multiple parts, but I doubt that this is worth teh effort.

--
   Manfred
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to