forcedeth: fix irq clearing and napi spin lock changes
This patch clears the irqstatus register with the exact same events it has read from it. Since the read-write operation is not atomic, a new irqstatus bit could have been set in between these operations and would then be cleared accidentally. Secondly, we now don't need any spin lock protection when scheduling/completing napi poll as the isr will not execute anymore (as we turn off all interrupts now). Signed-off-by: Ayaz Abdulla <aabdulla@nvidia.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
committed by
David S. Miller
parent
6cef67a02f
commit
1b2bb76f57
@@ -3464,10 +3464,10 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
|
|||||||
|
|
||||||
if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
|
if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
|
||||||
np->events = readl(base + NvRegIrqStatus);
|
np->events = readl(base + NvRegIrqStatus);
|
||||||
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
|
writel(np->events, base + NvRegIrqStatus);
|
||||||
} else {
|
} else {
|
||||||
np->events = readl(base + NvRegMSIXIrqStatus);
|
np->events = readl(base + NvRegMSIXIrqStatus);
|
||||||
writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
|
writel(np->events, base + NvRegMSIXIrqStatus);
|
||||||
}
|
}
|
||||||
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events);
|
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events);
|
||||||
if (!(np->events & np->irqmask))
|
if (!(np->events & np->irqmask))
|
||||||
@@ -3476,15 +3476,12 @@ static irqreturn_t nv_nic_irq(int foo, void *data)
|
|||||||
nv_msi_workaround(np);
|
nv_msi_workaround(np);
|
||||||
|
|
||||||
#ifdef CONFIG_FORCEDETH_NAPI
|
#ifdef CONFIG_FORCEDETH_NAPI
|
||||||
spin_lock(&np->lock);
|
|
||||||
napi_schedule(&np->napi);
|
napi_schedule(&np->napi);
|
||||||
|
|
||||||
/* Disable furthur irq's
|
/* Disable furthur irq's
|
||||||
(msix not enabled with napi) */
|
(msix not enabled with napi) */
|
||||||
writel(0, base + NvRegIrqMask);
|
writel(0, base + NvRegIrqMask);
|
||||||
|
|
||||||
spin_unlock(&np->lock);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -3568,10 +3565,10 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
|
|||||||
|
|
||||||
if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
|
if (!(np->msi_flags & NV_MSI_X_ENABLED)) {
|
||||||
np->events = readl(base + NvRegIrqStatus);
|
np->events = readl(base + NvRegIrqStatus);
|
||||||
writel(NVREG_IRQSTAT_MASK, base + NvRegIrqStatus);
|
writel(np->events, base + NvRegIrqStatus);
|
||||||
} else {
|
} else {
|
||||||
np->events = readl(base + NvRegMSIXIrqStatus);
|
np->events = readl(base + NvRegMSIXIrqStatus);
|
||||||
writel(NVREG_IRQSTAT_MASK, base + NvRegMSIXIrqStatus);
|
writel(np->events, base + NvRegMSIXIrqStatus);
|
||||||
}
|
}
|
||||||
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events);
|
dprintk(KERN_DEBUG "%s: irq: %08x\n", dev->name, np->events);
|
||||||
if (!(np->events & np->irqmask))
|
if (!(np->events & np->irqmask))
|
||||||
@@ -3580,15 +3577,12 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data)
|
|||||||
nv_msi_workaround(np);
|
nv_msi_workaround(np);
|
||||||
|
|
||||||
#ifdef CONFIG_FORCEDETH_NAPI
|
#ifdef CONFIG_FORCEDETH_NAPI
|
||||||
spin_lock(&np->lock);
|
|
||||||
napi_schedule(&np->napi);
|
napi_schedule(&np->napi);
|
||||||
|
|
||||||
/* Disable furthur irq's
|
/* Disable furthur irq's
|
||||||
(msix not enabled with napi) */
|
(msix not enabled with napi) */
|
||||||
writel(0, base + NvRegIrqMask);
|
writel(0, base + NvRegIrqMask);
|
||||||
|
|
||||||
spin_unlock(&np->lock);
|
|
||||||
|
|
||||||
#else
|
#else
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
@@ -3758,13 +3752,9 @@ static int nv_napi_poll(struct napi_struct *napi, int budget)
|
|||||||
if (rx_work < budget) {
|
if (rx_work < budget) {
|
||||||
/* re-enable interrupts
|
/* re-enable interrupts
|
||||||
(msix not enabled in napi) */
|
(msix not enabled in napi) */
|
||||||
spin_lock_irqsave(&np->lock, flags);
|
|
||||||
|
|
||||||
__napi_complete(napi);
|
__napi_complete(napi);
|
||||||
|
|
||||||
writel(np->irqmask, base + NvRegIrqMask);
|
writel(np->irqmask, base + NvRegIrqMask);
|
||||||
|
|
||||||
spin_unlock_irqrestore(&np->lock, flags);
|
|
||||||
}
|
}
|
||||||
return rx_work;
|
return rx_work;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user