aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/forcedeth.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/forcedeth.c')
-rw-r--r--drivers/net/forcedeth.c36
1 files changed, 34 insertions, 2 deletions
diff --git a/drivers/net/forcedeth.c b/drivers/net/forcedeth.c
index 35f66d4a4595..20d4fe96a81c 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
3276static 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
3276static irqreturn_t nv_nic_irq(int foo, void *data) 3290static 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);
@@ -4174,12 +4194,23 @@ static int nv_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
4174 4194
4175 netif_carrier_off(dev); 4195 netif_carrier_off(dev);
4176 if (netif_running(dev)) { 4196 if (netif_running(dev)) {
4197 unsigned long flags;
4198
4177 nv_disable_irq(dev); 4199 nv_disable_irq(dev);
4178 netif_tx_lock_bh(dev); 4200 netif_tx_lock_bh(dev);
4179 spin_lock(&np->lock); 4201 /* with plain spinlock lockdep complains */
4202 spin_lock_irqsave(&np->lock, flags);
4180 /* stop engines */ 4203 /* stop engines */
4204 /* FIXME:
4205 * this can take some time, and interrupts are disabled
4206 * due to spin_lock_irqsave, but let's hope no daemon
4207 * is going to change the settings very often...
4208 * Worst case:
4209 * NV_RXSTOP_DELAY1MAX + NV_TXSTOP_DELAY1MAX
4210 * + some minor delays, which is up to a second approximately
4211 */
4181 nv_stop_rxtx(dev); 4212 nv_stop_rxtx(dev);
4182 spin_unlock(&np->lock); 4213 spin_unlock_irqrestore(&np->lock, flags);
4183 netif_tx_unlock_bh(dev); 4214 netif_tx_unlock_bh(dev);
4184 } 4215 }
4185 4216
@@ -5823,6 +5854,7 @@ static int nv_resume(struct pci_dev *pdev)
5823 writel(txreg, base + NvRegTransmitPoll); 5854 writel(txreg, base + NvRegTransmitPoll);
5824 5855
5825 rc = nv_open(dev); 5856 rc = nv_open(dev);
5857 nv_set_multicast(dev);
5826out: 5858out:
5827 return rc; 5859 return rc;
5828} 5860}