diff options
| -rw-r--r-- | drivers/net/ns83820.c | 31 |
1 files changed, 17 insertions, 14 deletions
diff --git a/drivers/net/ns83820.c b/drivers/net/ns83820.c index d0ed8646902f..0e76859c90a2 100644 --- a/drivers/net/ns83820.c +++ b/drivers/net/ns83820.c | |||
| @@ -803,7 +803,7 @@ static int ns83820_setup_rx(struct net_device *ndev) | |||
| 803 | 803 | ||
| 804 | writel(dev->IMR_cache, dev->base + IMR); | 804 | writel(dev->IMR_cache, dev->base + IMR); |
| 805 | writel(1, dev->base + IER); | 805 | writel(1, dev->base + IER); |
| 806 | spin_unlock_irq(&dev->misc_lock); | 806 | spin_unlock(&dev->misc_lock); |
| 807 | 807 | ||
| 808 | kick_rx(ndev); | 808 | kick_rx(ndev); |
| 809 | 809 | ||
| @@ -1012,8 +1012,6 @@ static void do_tx_done(struct net_device *ndev) | |||
| 1012 | struct ns83820 *dev = PRIV(ndev); | 1012 | struct ns83820 *dev = PRIV(ndev); |
| 1013 | u32 cmdsts, tx_done_idx, *desc; | 1013 | u32 cmdsts, tx_done_idx, *desc; |
| 1014 | 1014 | ||
| 1015 | spin_lock_irq(&dev->tx_lock); | ||
| 1016 | |||
| 1017 | dprintk("do_tx_done(%p)\n", ndev); | 1015 | dprintk("do_tx_done(%p)\n", ndev); |
| 1018 | tx_done_idx = dev->tx_done_idx; | 1016 | tx_done_idx = dev->tx_done_idx; |
| 1019 | desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); | 1017 | desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); |
| @@ -1069,7 +1067,6 @@ static void do_tx_done(struct net_device *ndev) | |||
| 1069 | netif_start_queue(ndev); | 1067 | netif_start_queue(ndev); |
| 1070 | netif_wake_queue(ndev); | 1068 | netif_wake_queue(ndev); |
| 1071 | } | 1069 | } |
| 1072 | spin_unlock_irq(&dev->tx_lock); | ||
| 1073 | } | 1070 | } |
| 1074 | 1071 | ||
| 1075 | static void ns83820_cleanup_tx(struct ns83820 *dev) | 1072 | static void ns83820_cleanup_tx(struct ns83820 *dev) |
| @@ -1281,11 +1278,13 @@ static struct ethtool_ops ops = { | |||
| 1281 | .get_link = ns83820_get_link | 1278 | .get_link = ns83820_get_link |
| 1282 | }; | 1279 | }; |
| 1283 | 1280 | ||
| 1281 | /* this function is called in irq context from the ISR */ | ||
| 1284 | static void ns83820_mib_isr(struct ns83820 *dev) | 1282 | static void ns83820_mib_isr(struct ns83820 *dev) |
| 1285 | { | 1283 | { |
| 1286 | spin_lock(&dev->misc_lock); | 1284 | unsigned long flags; |
| 1285 | spin_lock_irqsave(&dev->misc_lock, flags); | ||
| 1287 | ns83820_update_stats(dev); | 1286 | ns83820_update_stats(dev); |
| 1288 | spin_unlock(&dev->misc_lock); | 1287 | spin_unlock_irqrestore(&dev->misc_lock, flags); |
| 1289 | } | 1288 | } |
| 1290 | 1289 | ||
| 1291 | static void ns83820_do_isr(struct net_device *ndev, u32 isr); | 1290 | static void ns83820_do_isr(struct net_device *ndev, u32 isr); |
| @@ -1307,6 +1306,8 @@ static irqreturn_t ns83820_irq(int foo, void *data, struct pt_regs *regs) | |||
| 1307 | static void ns83820_do_isr(struct net_device *ndev, u32 isr) | 1306 | static void ns83820_do_isr(struct net_device *ndev, u32 isr) |
| 1308 | { | 1307 | { |
| 1309 | struct ns83820 *dev = PRIV(ndev); | 1308 | struct ns83820 *dev = PRIV(ndev); |
| 1309 | unsigned long flags; | ||
| 1310 | |||
| 1310 | #ifdef DEBUG | 1311 | #ifdef DEBUG |
| 1311 | if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC)) | 1312 | if (isr & ~(ISR_PHY | ISR_RXDESC | ISR_RXEARLY | ISR_RXOK | ISR_RXERR | ISR_TXIDLE | ISR_TXOK | ISR_TXDESC)) |
| 1312 | Dprintk("odd isr? 0x%08x\n", isr); | 1313 | Dprintk("odd isr? 0x%08x\n", isr); |
| @@ -1321,10 +1322,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr) | |||
| 1321 | if ((ISR_RXDESC | ISR_RXOK) & isr) { | 1322 | if ((ISR_RXDESC | ISR_RXOK) & isr) { |
| 1322 | prefetch(dev->rx_info.next_rx_desc); | 1323 | prefetch(dev->rx_info.next_rx_desc); |
| 1323 | 1324 | ||
| 1324 | spin_lock_irq(&dev->misc_lock); | 1325 | spin_lock_irqsave(&dev->misc_lock, flags); |
| 1325 | dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK); | 1326 | dev->IMR_cache &= ~(ISR_RXDESC | ISR_RXOK); |
| 1326 | writel(dev->IMR_cache, dev->base + IMR); | 1327 | writel(dev->IMR_cache, dev->base + IMR); |
| 1327 | spin_unlock_irq(&dev->misc_lock); | 1328 | spin_unlock_irqrestore(&dev->misc_lock, flags); |
| 1328 | 1329 | ||
| 1329 | tasklet_schedule(&dev->rx_tasklet); | 1330 | tasklet_schedule(&dev->rx_tasklet); |
| 1330 | //rx_irq(ndev); | 1331 | //rx_irq(ndev); |
| @@ -1370,16 +1371,18 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr) | |||
| 1370 | * work has accumulated | 1371 | * work has accumulated |
| 1371 | */ | 1372 | */ |
| 1372 | if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) { | 1373 | if ((ISR_TXDESC | ISR_TXIDLE | ISR_TXOK | ISR_TXERR) & isr) { |
| 1374 | spin_lock_irqsave(&dev->tx_lock, flags); | ||
| 1373 | do_tx_done(ndev); | 1375 | do_tx_done(ndev); |
| 1376 | spin_unlock_irqrestore(&dev->tx_lock, flags); | ||
| 1374 | 1377 | ||
| 1375 | /* Disable TxOk if there are no outstanding tx packets. | 1378 | /* Disable TxOk if there are no outstanding tx packets. |
| 1376 | */ | 1379 | */ |
| 1377 | if ((dev->tx_done_idx == dev->tx_free_idx) && | 1380 | if ((dev->tx_done_idx == dev->tx_free_idx) && |
| 1378 | (dev->IMR_cache & ISR_TXOK)) { | 1381 | (dev->IMR_cache & ISR_TXOK)) { |
| 1379 | spin_lock_irq(&dev->misc_lock); | 1382 | spin_lock_irqsave(&dev->misc_lock, flags); |
| 1380 | dev->IMR_cache &= ~ISR_TXOK; | 1383 | dev->IMR_cache &= ~ISR_TXOK; |
| 1381 | writel(dev->IMR_cache, dev->base + IMR); | 1384 | writel(dev->IMR_cache, dev->base + IMR); |
| 1382 | spin_unlock_irq(&dev->misc_lock); | 1385 | spin_unlock_irqrestore(&dev->misc_lock, flags); |
| 1383 | } | 1386 | } |
| 1384 | } | 1387 | } |
| 1385 | 1388 | ||
| @@ -1390,10 +1393,10 @@ static void ns83820_do_isr(struct net_device *ndev, u32 isr) | |||
| 1390 | * nature are expected, we must enable TxOk. | 1393 | * nature are expected, we must enable TxOk. |
| 1391 | */ | 1394 | */ |
| 1392 | if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) { | 1395 | if ((ISR_TXIDLE & isr) && (dev->tx_done_idx != dev->tx_free_idx)) { |
| 1393 | spin_lock_irq(&dev->misc_lock); | 1396 | spin_lock_irqsave(&dev->misc_lock, flags); |
| 1394 | dev->IMR_cache |= ISR_TXOK; | 1397 | dev->IMR_cache |= ISR_TXOK; |
| 1395 | writel(dev->IMR_cache, dev->base + IMR); | 1398 | writel(dev->IMR_cache, dev->base + IMR); |
| 1396 | spin_unlock_irq(&dev->misc_lock); | 1399 | spin_unlock_irqrestore(&dev->misc_lock, flags); |
| 1397 | } | 1400 | } |
| 1398 | 1401 | ||
| 1399 | /* MIB interrupt: one of the statistics counters is about to overflow */ | 1402 | /* MIB interrupt: one of the statistics counters is about to overflow */ |
| @@ -1455,7 +1458,7 @@ static void ns83820_tx_timeout(struct net_device *ndev) | |||
| 1455 | u32 tx_done_idx, *desc; | 1458 | u32 tx_done_idx, *desc; |
| 1456 | unsigned long flags; | 1459 | unsigned long flags; |
| 1457 | 1460 | ||
| 1458 | local_irq_save(flags); | 1461 | spin_lock_irqsave(&dev->tx_lock, flags); |
| 1459 | 1462 | ||
| 1460 | tx_done_idx = dev->tx_done_idx; | 1463 | tx_done_idx = dev->tx_done_idx; |
| 1461 | desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); | 1464 | desc = dev->tx_descs + (tx_done_idx * DESC_SIZE); |
| @@ -1482,7 +1485,7 @@ static void ns83820_tx_timeout(struct net_device *ndev) | |||
| 1482 | ndev->name, | 1485 | ndev->name, |
| 1483 | tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS])); | 1486 | tx_done_idx, dev->tx_free_idx, le32_to_cpu(desc[DESC_CMDSTS])); |
| 1484 | 1487 | ||
| 1485 | local_irq_restore(flags); | 1488 | spin_unlock_irqrestore(&dev->tx_lock, flags); |
| 1486 | } | 1489 | } |
| 1487 | 1490 | ||
| 1488 | static void ns83820_tx_watch(unsigned long data) | 1491 | static void ns83820_tx_watch(unsigned long data) |
