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) |