diff options
Diffstat (limited to 'drivers/net/forcedeth.c')
| -rw-r--r-- | drivers/net/forcedeth.c | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c index 35f66d4a4595..2cb244763292 100644 --- a/drivers/net/forcedeth.c +++ b/drivers/net/forcedeth.c | |||
| @@ -3273,6 +3273,20 @@ static void nv_link_irq(struct net_device *dev) | |||
| 3273 | dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); | 3273 | dprintk(KERN_DEBUG "%s: link change notification done.\n", dev->name); |
| 3274 | } | 3274 | } |
| 3275 | 3275 | ||
| 3276 | static void nv_msi_workaround(struct fe_priv *np) | ||
| 3277 | { | ||
| 3278 | |||
| 3279 | /* Need to toggle the msi irq mask within the ethernet device, | ||
| 3280 | * otherwise, future interrupts will not be detected. | ||
| 3281 | */ | ||
| 3282 | if (np->msi_flags & NV_MSI_ENABLED) { | ||
| 3283 | u8 __iomem *base = np->base; | ||
| 3284 | |||
| 3285 | writel(0, base + NvRegMSIIrqMask); | ||
| 3286 | writel(NVREG_MSI_VECTOR_0_ENABLED, base + NvRegMSIIrqMask); | ||
| 3287 | } | ||
| 3288 | } | ||
| 3289 | |||
| 3276 | static irqreturn_t nv_nic_irq(int foo, void *data) | 3290 | static irqreturn_t nv_nic_irq(int foo, void *data) |
| 3277 | { | 3291 | { |
| 3278 | struct net_device *dev = (struct net_device *) data; | 3292 | struct net_device *dev = (struct net_device *) data; |
| @@ -3295,6 +3309,8 @@ static irqreturn_t nv_nic_irq(int foo, void *data) | |||
| 3295 | if (!(events & np->irqmask)) | 3309 | if (!(events & np->irqmask)) |
| 3296 | break; | 3310 | break; |
| 3297 | 3311 | ||
| 3312 | nv_msi_workaround(np); | ||
| 3313 | |||
| 3298 | spin_lock(&np->lock); | 3314 | spin_lock(&np->lock); |
| 3299 | nv_tx_done(dev); | 3315 | nv_tx_done(dev); |
| 3300 | spin_unlock(&np->lock); | 3316 | spin_unlock(&np->lock); |
| @@ -3410,6 +3426,8 @@ static irqreturn_t nv_nic_irq_optimized(int foo, void *data) | |||
| 3410 | if (!(events & np->irqmask)) | 3426 | if (!(events & np->irqmask)) |
| 3411 | break; | 3427 | break; |
| 3412 | 3428 | ||
| 3429 | nv_msi_workaround(np); | ||
| 3430 | |||
| 3413 | spin_lock(&np->lock); | 3431 | spin_lock(&np->lock); |
| 3414 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); | 3432 | nv_tx_done_optimized(dev, TX_WORK_PER_LOOP); |
| 3415 | spin_unlock(&np->lock); | 3433 | spin_unlock(&np->lock); |
| @@ -3750,6 +3768,8 @@ static irqreturn_t nv_nic_irq_test(int foo, void *data) | |||
| 3750 | if (!(events & NVREG_IRQ_TIMER)) | 3768 | if (!(events & NVREG_IRQ_TIMER)) |
| 3751 | return IRQ_RETVAL(0); | 3769 | return IRQ_RETVAL(0); |
| 3752 | 3770 | ||
| 3771 | nv_msi_workaround(np); | ||
| 3772 | |||
| 3753 | spin_lock(&np->lock); | 3773 | spin_lock(&np->lock); |
| 3754 | np->intr_test = 1; | 3774 | np->intr_test = 1; |
| 3755 | spin_unlock(&np->lock); | 3775 | spin_unlock(&np->lock); |
| @@ -5823,6 +5843,7 @@ static int nv_resume(struct pci_dev *pdev) | |||
| 5823 | writel(txreg, base + NvRegTransmitPoll); | 5843 | writel(txreg, base + NvRegTransmitPoll); |
| 5824 | 5844 | ||
| 5825 | rc = nv_open(dev); | 5845 | rc = nv_open(dev); |
| 5846 | nv_set_multicast(dev); | ||
| 5826 | out: | 5847 | out: |
| 5827 | return rc; | 5848 | return rc; |
| 5828 | } | 5849 | } |
