diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r-- | drivers/net/forcedeth.c | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index e4d697894364..c980ce9719af 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
@@ -3277,6 +3277,20 @@ static void nv_link_irq(struct net_device *dev) | |||
3277 | dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); | 3277 | dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); |
3278 | } | 3278 | } |
3279 | 3279 | ||
3280 | static void nv_msi_workaround(struct fe_priv *np) | ||
3281 | { | ||
3282 | |||
3283 | /* Need to toggle the msi irq mask within the ethernet device, | ||
3284 | * otherwise, future interrupts will not be detected. | ||
3285 | */ | ||
3286 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
3287 | u8 __iomem *base = np->base; | ||
3288 | |||
3289 | writel(0, base + NvRegMSIIrqMask); | ||
3290 | writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); | ||
3291 | } | ||
3292 | } | ||
3293 | |||
3280 | static irqreturn_t nv_nic_irq(int foo, void *data) | 3294 | static irqreturn_t nv_nic_irq(int foo, void *data) |
3281 | { | 3295 | { |
3282 | struct net_device *dev = (struct net_device *) data; | 3296 | struct net_device *dev = (struct net_device *) data; |
@@ -3299,6 +3313,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) | |||
3299 | if (!(events & np->irqmask)) | 3313 | if (!(events & np->irqmask)) |
3300 | break; | 3314 | break; |
3301 | 3315 | ||
3316 | nv_msi_workaround(np); | ||
3317 | |||
3302 | spin_lock(&np->lock); | 3318 | spin_lock(&np->lock); |
3303 | nv_tx_done(dev); | 3319 | nv_tx_done(dev); |
3304 | spin_unlock(&np->lock); | 3320 | spin_unlock(&np->lock); |
@@ -3414,6 +3430,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) | |||
3414 | if (!(events & np->irqmask)) | 3430 | if (!(events & np->irqmask)) |
3415 | break; | 3431 | break; |
3416 | 3432 | ||
3433 | nv_msi_workaround(np); | ||
3434 | |||
3417 | spin_lock(&np->lock); | 3435 | spin_lock(&np->lock); |
3418 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); | 3436 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); |
3419 | spin_unlock(&np->lock); | 3437 | spin_unlock(&np->lock); |
@@ -3754,6 +3772,8 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) | |||
3754 | if (!(events & NVREG_IRQ_TIMER)) | 3772 | if (!(events & NVREG_IRQ_TIMER)) |
3755 | return IRQ_RETVAL(0); | 3773 | return IRQ_RETVAL(0); |
3756 | 3774 | ||
3775 | nv_msi_workaround(np); | ||
3776 | |||
3757 | spin_lock(&np->lock); | 3777 | spin_lock(&np->lock); |
3758 | np->intr_test = 1; | 3778 | np->intr_test = 1; |
3759 | spin_unlock(&np->lock); | 3779 | spin_unlock(&np->lock); |