diff options
author | Don Fry <brazilnut@us.ibm.com> | 2006-09-13 13:16:53 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-13 13:23:52 -0400 |
commit | 7de745e56244156233e5cdd62b462e52e638d408 (patch) | |
tree | fbc0a3e546de813a5276c0c8a5454d46b1329fbc | |
parent | 3904c324148930bad5d9b97fdf66c63e7682b546 (diff) |
[PATCH] pcnet32: NAPI implementation
Implement NAPI changes to pcnet32 driver. Compile default is off.
Listed as experimental.
Len and Don both worked on a NAPI implementation and have both tested
these changes.
An e1000 blasting short packets to the pcnet32 will lockup Don's system
until the receive storm stops. Without NAPI Len's system watchdog would
expire causing the system to reboot. With NAPI the system will stay
operational.
Tested ia32 and ppc64. Tested '970A, '971, '972, '973, '975, '976, and
'978.
The Kconfig changes came from Len. Don is to blame for all the others.
Signed-off-by: Len Sorensen <lsorense@csclub.uwaterloo.ca>
Signed-off-by: Don Fry <brazilnut@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r-- | drivers/net/Kconfig | 17 | ||||
-rw-r--r-- | drivers/net/pcnet32.c | 132 |
2 files changed, 121 insertions, 28 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index de4f9e1f2ca5..a36fc60bd889 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1300,6 +1300,23 @@ config PCNET32 | |||
1300 | <file:Documentation/networking/net-modules.txt>. The module | 1300 | <file:Documentation/networking/net-modules.txt>. The module |
1301 | will be called pcnet32. | 1301 | will be called pcnet32. |
1302 | 1302 | ||
1303 | config PCNET32_NAPI | ||
1304 | bool "Use RX polling (NAPI) (EXPERIMENTAL)" | ||
1305 | depends on PCNET32 && EXPERIMENTAL | ||
1306 | help | ||
1307 | NAPI is a new driver API designed to reduce CPU and interrupt load | ||
1308 | when the driver is receiving lots of packets from the card. It is | ||
1309 | still somewhat experimental and thus not yet enabled by default. | ||
1310 | |||
1311 | If your estimated Rx load is 10kpps or more, or if the card will be | ||
1312 | deployed on potentially unfriendly networks (e.g. in a firewall), | ||
1313 | then say Y here. | ||
1314 | |||
1315 | See <file:Documentation/networking/NAPI_HOWTO.txt> for more | ||
1316 | information. | ||
1317 | |||
1318 | If in doubt, say N. | ||
1319 | |||
1303 | config AMD8111_ETH | 1320 | config AMD8111_ETH |
1304 | tristate "AMD 8111 (new PCI lance) support" | 1321 | tristate "AMD 8111 (new PCI lance) support" |
1305 | depends on NET_PCI && PCI | 1322 | depends on NET_PCI && PCI |
diff --git a/drivers/net/pcnet32.c b/drivers/net/pcnet32.c index bf72aa80ccb6..de05aeb734da 100644 --- a/drivers/net/pcnet32.c +++ b/drivers/net/pcnet32.c | |||
@@ -21,9 +21,15 @@ | |||
21 | * | 21 | * |
22 | *************************************************************************/ | 22 | *************************************************************************/ |
23 | 23 | ||
24 | #include <linux/config.h> | ||
25 | |||
24 | #define DRV_NAME "pcnet32" | 26 | #define DRV_NAME "pcnet32" |
25 | #define DRV_VERSION "1.32" | 27 | #ifdef CONFIG_PCNET32_NAPI |
26 | #define DRV_RELDATE "18.Mar.2006" | 28 | #define DRV_VERSION "1.33-NAPI" |
29 | #else | ||
30 | #define DRV_VERSION "1.33" | ||
31 | #endif | ||
32 | #define DRV_RELDATE "27.Jun.2006" | ||
27 | #define PFX DRV_NAME ": " | 33 | #define PFX DRV_NAME ": " |
28 | 34 | ||
29 | static const char *const version = | 35 | static const char *const version = |
@@ -882,7 +888,11 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
882 | rc = 1; /* default to fail */ | 888 | rc = 1; /* default to fail */ |
883 | 889 | ||
884 | if (netif_running(dev)) | 890 | if (netif_running(dev)) |
891 | #ifdef CONFIG_PCNET32_NAPI | ||
892 | pcnet32_netif_stop(dev); | ||
893 | #else | ||
885 | pcnet32_close(dev); | 894 | pcnet32_close(dev); |
895 | #endif | ||
886 | 896 | ||
887 | spin_lock_irqsave(&lp->lock, flags); | 897 | spin_lock_irqsave(&lp->lock, flags); |
888 | lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */ | 898 | lp->a.write_csr(ioaddr, CSR0, CSR0_STOP); /* stop the chip */ |
@@ -1014,6 +1024,16 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
1014 | x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ | 1024 | x = a->read_bcr(ioaddr, 32); /* reset internal loopback */ |
1015 | a->write_bcr(ioaddr, 32, (x & ~0x0002)); | 1025 | a->write_bcr(ioaddr, 32, (x & ~0x0002)); |
1016 | 1026 | ||
1027 | #ifdef CONFIG_PCNET32_NAPI | ||
1028 | if (netif_running(dev)) { | ||
1029 | pcnet32_netif_start(dev); | ||
1030 | pcnet32_restart(dev, CSR0_NORMAL); | ||
1031 | } else { | ||
1032 | pcnet32_purge_rx_ring(dev); | ||
1033 | lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ | ||
1034 | } | ||
1035 | spin_unlock_irqrestore(&lp->lock, flags); | ||
1036 | #else | ||
1017 | if (netif_running(dev)) { | 1037 | if (netif_running(dev)) { |
1018 | spin_unlock_irqrestore(&lp->lock, flags); | 1038 | spin_unlock_irqrestore(&lp->lock, flags); |
1019 | pcnet32_open(dev); | 1039 | pcnet32_open(dev); |
@@ -1022,6 +1042,7 @@ static int pcnet32_loopback_test(struct net_device *dev, uint64_t * data1) | |||
1022 | lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ | 1042 | lp->a.write_bcr(ioaddr, 20, 4); /* return to 16bit mode */ |
1023 | spin_unlock_irqrestore(&lp->lock, flags); | 1043 | spin_unlock_irqrestore(&lp->lock, flags); |
1024 | } | 1044 | } |
1045 | #endif | ||
1025 | 1046 | ||
1026 | return (rc); | 1047 | return (rc); |
1027 | } /* end pcnet32_loopback_test */ | 1048 | } /* end pcnet32_loopback_test */ |
@@ -1227,23 +1248,25 @@ static void pcnet32_rx_entry(struct net_device *dev, | |||
1227 | } | 1248 | } |
1228 | lp->stats.rx_bytes += skb->len; | 1249 | lp->stats.rx_bytes += skb->len; |
1229 | skb->protocol = eth_type_trans(skb, dev); | 1250 | skb->protocol = eth_type_trans(skb, dev); |
1251 | #ifdef CONFIG_PCNET32_NAPI | ||
1252 | netif_receive_skb(skb); | ||
1253 | #else | ||
1230 | netif_rx(skb); | 1254 | netif_rx(skb); |
1255 | #endif | ||
1231 | dev->last_rx = jiffies; | 1256 | dev->last_rx = jiffies; |
1232 | lp->stats.rx_packets++; | 1257 | lp->stats.rx_packets++; |
1233 | return; | 1258 | return; |
1234 | } | 1259 | } |
1235 | 1260 | ||
1236 | 1261 | static int pcnet32_rx(struct net_device *dev, int quota) | |
1237 | static void pcnet32_rx(struct net_device *dev) | ||
1238 | { | 1262 | { |
1239 | struct pcnet32_private *lp = dev->priv; | 1263 | struct pcnet32_private *lp = dev->priv; |
1240 | int entry = lp->cur_rx & lp->rx_mod_mask; | 1264 | int entry = lp->cur_rx & lp->rx_mod_mask; |
1241 | struct pcnet32_rx_head *rxp = &lp->rx_ring[entry]; | 1265 | struct pcnet32_rx_head *rxp = &lp->rx_ring[entry]; |
1242 | int npackets = 0; | 1266 | int npackets = 0; |
1243 | int boguscnt = lp->rx_ring_size / 2; | ||
1244 | 1267 | ||
1245 | /* If we own the next entry, it's a new packet. Send it up. */ | 1268 | /* If we own the next entry, it's a new packet. Send it up. */ |
1246 | while (boguscnt > npackets && (short)le16_to_cpu(rxp->status) >= 0) { | 1269 | while (quota > npackets && (short)le16_to_cpu(rxp->status) >= 0) { |
1247 | pcnet32_rx_entry(dev, lp, rxp, entry); | 1270 | pcnet32_rx_entry(dev, lp, rxp, entry); |
1248 | npackets += 1; | 1271 | npackets += 1; |
1249 | /* | 1272 | /* |
@@ -1257,10 +1280,10 @@ static void pcnet32_rx(struct net_device *dev) | |||
1257 | rxp = &lp->rx_ring[entry]; | 1280 | rxp = &lp->rx_ring[entry]; |
1258 | } | 1281 | } |
1259 | 1282 | ||
1260 | return; | 1283 | return npackets; |
1261 | } | 1284 | } |
1262 | 1285 | ||
1263 | static int pcnet32_tx(struct net_device *dev, u16 csr0) | 1286 | static int pcnet32_tx(struct net_device *dev) |
1264 | { | 1287 | { |
1265 | struct pcnet32_private *lp = dev->priv; | 1288 | struct pcnet32_private *lp = dev->priv; |
1266 | unsigned int dirty_tx = lp->dirty_tx; | 1289 | unsigned int dirty_tx = lp->dirty_tx; |
@@ -1298,8 +1321,8 @@ static int pcnet32_tx(struct net_device *dev, u16 csr0) | |||
1298 | /* Remove this verbosity later! */ | 1321 | /* Remove this verbosity later! */ |
1299 | if (netif_msg_tx_err(lp)) | 1322 | if (netif_msg_tx_err(lp)) |
1300 | printk(KERN_ERR | 1323 | printk(KERN_ERR |
1301 | "%s: Tx FIFO error! CSR0=%4.4x\n", | 1324 | "%s: Tx FIFO error!\n", |
1302 | dev->name, csr0); | 1325 | dev->name); |
1303 | must_restart = 1; | 1326 | must_restart = 1; |
1304 | } | 1327 | } |
1305 | #else | 1328 | #else |
@@ -1310,8 +1333,8 @@ static int pcnet32_tx(struct net_device *dev, u16 csr0) | |||
1310 | /* Remove this verbosity later! */ | 1333 | /* Remove this verbosity later! */ |
1311 | if (netif_msg_tx_err(lp)) | 1334 | if (netif_msg_tx_err(lp)) |
1312 | printk(KERN_ERR | 1335 | printk(KERN_ERR |
1313 | "%s: Tx FIFO error! CSR0=%4.4x\n", | 1336 | "%s: Tx FIFO error!\n", |
1314 | dev->name, csr0); | 1337 | dev->name); |
1315 | must_restart = 1; | 1338 | must_restart = 1; |
1316 | } | 1339 | } |
1317 | } | 1340 | } |
@@ -1358,6 +1381,52 @@ static int pcnet32_tx(struct net_device *dev, u16 csr0) | |||
1358 | return must_restart; | 1381 | return must_restart; |
1359 | } | 1382 | } |
1360 | 1383 | ||
1384 | #ifdef CONFIG_PCNET32_NAPI | ||
1385 | static int pcnet32_poll(struct net_device *dev, int *budget) | ||
1386 | { | ||
1387 | struct pcnet32_private *lp = dev->priv; | ||
1388 | int quota = min(dev->quota, *budget); | ||
1389 | unsigned long ioaddr = dev->base_addr; | ||
1390 | unsigned long flags; | ||
1391 | u16 val; | ||
1392 | |||
1393 | quota = pcnet32_rx(dev, quota); | ||
1394 | |||
1395 | spin_lock_irqsave(&lp->lock, flags); | ||
1396 | if (pcnet32_tx(dev)) { | ||
1397 | /* reset the chip to clear the error condition, then restart */ | ||
1398 | lp->a.reset(ioaddr); | ||
1399 | lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ | ||
1400 | pcnet32_restart(dev, CSR0_START); | ||
1401 | netif_wake_queue(dev); | ||
1402 | } | ||
1403 | spin_unlock_irqrestore(&lp->lock, flags); | ||
1404 | |||
1405 | *budget -= quota; | ||
1406 | dev->quota -= quota; | ||
1407 | |||
1408 | if (dev->quota == 0) { | ||
1409 | return 1; | ||
1410 | } | ||
1411 | |||
1412 | netif_rx_complete(dev); | ||
1413 | |||
1414 | spin_lock_irqsave(&lp->lock, flags); | ||
1415 | |||
1416 | /* clear interrupt masks */ | ||
1417 | val = lp->a.read_csr(ioaddr, CSR3); | ||
1418 | val &= 0x00ff; | ||
1419 | lp->a.write_csr(ioaddr, CSR3, val); | ||
1420 | |||
1421 | /* Set interrupt enable. */ | ||
1422 | lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); | ||
1423 | mmiowb(); | ||
1424 | spin_unlock_irqrestore(&lp->lock, flags); | ||
1425 | |||
1426 | return 0; | ||
1427 | } | ||
1428 | #endif | ||
1429 | |||
1361 | #define PCNET32_REGS_PER_PHY 32 | 1430 | #define PCNET32_REGS_PER_PHY 32 |
1362 | #define PCNET32_MAX_PHYS 32 | 1431 | #define PCNET32_MAX_PHYS 32 |
1363 | static int pcnet32_get_regs_len(struct net_device *dev) | 1432 | static int pcnet32_get_regs_len(struct net_device *dev) |
@@ -1894,6 +1963,10 @@ pcnet32_probe1(unsigned long ioaddr, int shared, struct pci_dev *pdev) | |||
1894 | dev->ethtool_ops = &pcnet32_ethtool_ops; | 1963 | dev->ethtool_ops = &pcnet32_ethtool_ops; |
1895 | dev->tx_timeout = pcnet32_tx_timeout; | 1964 | dev->tx_timeout = pcnet32_tx_timeout; |
1896 | dev->watchdog_timeo = (5 * HZ); | 1965 | dev->watchdog_timeo = (5 * HZ); |
1966 | dev->weight = lp->rx_ring_size / 2; | ||
1967 | #ifdef CONFIG_PCNET32_NAPI | ||
1968 | dev->poll = pcnet32_poll; | ||
1969 | #endif | ||
1897 | 1970 | ||
1898 | #ifdef CONFIG_NET_POLL_CONTROLLER | 1971 | #ifdef CONFIG_NET_POLL_CONTROLLER |
1899 | dev->poll_controller = pcnet32_poll_controller; | 1972 | dev->poll_controller = pcnet32_poll_controller; |
@@ -2497,7 +2570,6 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2497 | unsigned long ioaddr; | 2570 | unsigned long ioaddr; |
2498 | u16 csr0; | 2571 | u16 csr0; |
2499 | int boguscnt = max_interrupt_work; | 2572 | int boguscnt = max_interrupt_work; |
2500 | int must_restart; | ||
2501 | 2573 | ||
2502 | if (!dev) { | 2574 | if (!dev) { |
2503 | if (pcnet32_debug & NETIF_MSG_INTR) | 2575 | if (pcnet32_debug & NETIF_MSG_INTR) |
@@ -2519,20 +2591,11 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2519 | /* Acknowledge all of the current interrupt sources ASAP. */ | 2591 | /* Acknowledge all of the current interrupt sources ASAP. */ |
2520 | lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f); | 2592 | lp->a.write_csr(ioaddr, CSR0, csr0 & ~0x004f); |
2521 | 2593 | ||
2522 | must_restart = 0; | ||
2523 | |||
2524 | if (netif_msg_intr(lp)) | 2594 | if (netif_msg_intr(lp)) |
2525 | printk(KERN_DEBUG | 2595 | printk(KERN_DEBUG |
2526 | "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", | 2596 | "%s: interrupt csr0=%#2.2x new csr=%#2.2x.\n", |
2527 | dev->name, csr0, lp->a.read_csr(ioaddr, CSR0)); | 2597 | dev->name, csr0, lp->a.read_csr(ioaddr, CSR0)); |
2528 | 2598 | ||
2529 | if (csr0 & 0x0400) /* Rx interrupt */ | ||
2530 | pcnet32_rx(dev); | ||
2531 | |||
2532 | if (csr0 & 0x0200) { /* Tx-done interrupt */ | ||
2533 | must_restart = pcnet32_tx(dev, csr0); | ||
2534 | } | ||
2535 | |||
2536 | /* Log misc errors. */ | 2599 | /* Log misc errors. */ |
2537 | if (csr0 & 0x4000) | 2600 | if (csr0 & 0x4000) |
2538 | lp->stats.tx_errors++; /* Tx babble. */ | 2601 | lp->stats.tx_errors++; /* Tx babble. */ |
@@ -2546,10 +2609,8 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2546 | * sometimes problems and will fill up the receive | 2609 | * sometimes problems and will fill up the receive |
2547 | * ring with error descriptors. In this situation we | 2610 | * ring with error descriptors. In this situation we |
2548 | * don't get a rx interrupt, but a missed frame | 2611 | * don't get a rx interrupt, but a missed frame |
2549 | * interrupt sooner or later. So we try to clean up | 2612 | * interrupt sooner or later. |
2550 | * our receive ring here. | ||
2551 | */ | 2613 | */ |
2552 | pcnet32_rx(dev); | ||
2553 | lp->stats.rx_errors++; /* Missed a Rx frame. */ | 2614 | lp->stats.rx_errors++; /* Missed a Rx frame. */ |
2554 | } | 2615 | } |
2555 | if (csr0 & 0x0800) { | 2616 | if (csr0 & 0x0800) { |
@@ -2559,19 +2620,34 @@ pcnet32_interrupt(int irq, void *dev_id, struct pt_regs *regs) | |||
2559 | dev->name, csr0); | 2620 | dev->name, csr0); |
2560 | /* unlike for the lance, there is no restart needed */ | 2621 | /* unlike for the lance, there is no restart needed */ |
2561 | } | 2622 | } |
2562 | 2623 | #ifdef CONFIG_PCNET32_NAPI | |
2563 | if (must_restart) { | 2624 | if (netif_rx_schedule_prep(dev)) { |
2625 | u16 val; | ||
2626 | /* set interrupt masks */ | ||
2627 | val = lp->a.read_csr(ioaddr, CSR3); | ||
2628 | val |= 0x5f00; | ||
2629 | lp->a.write_csr(ioaddr, CSR3, val); | ||
2630 | mmiowb(); | ||
2631 | __netif_rx_schedule(dev); | ||
2632 | break; | ||
2633 | } | ||
2634 | #else | ||
2635 | pcnet32_rx(dev, dev->weight); | ||
2636 | if (pcnet32_tx(dev)) { | ||
2564 | /* reset the chip to clear the error condition, then restart */ | 2637 | /* reset the chip to clear the error condition, then restart */ |
2565 | lp->a.reset(ioaddr); | 2638 | lp->a.reset(ioaddr); |
2566 | lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ | 2639 | lp->a.write_csr(ioaddr, CSR4, 0x0915); /* auto tx pad */ |
2567 | pcnet32_restart(dev, CSR0_START); | 2640 | pcnet32_restart(dev, CSR0_START); |
2568 | netif_wake_queue(dev); | 2641 | netif_wake_queue(dev); |
2569 | } | 2642 | } |
2643 | #endif | ||
2570 | csr0 = lp->a.read_csr(ioaddr, CSR0); | 2644 | csr0 = lp->a.read_csr(ioaddr, CSR0); |
2571 | } | 2645 | } |
2572 | 2646 | ||
2647 | #ifndef CONFIG_PCNET32_NAPI | ||
2573 | /* Set interrupt enable. */ | 2648 | /* Set interrupt enable. */ |
2574 | lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); | 2649 | lp->a.write_csr(ioaddr, CSR0, CSR0_INTEN); |
2650 | #endif | ||
2575 | 2651 | ||
2576 | if (netif_msg_intr(lp)) | 2652 | if (netif_msg_intr(lp)) |
2577 | printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", | 2653 | printk(KERN_DEBUG "%s: exiting interrupt, csr0=%#4.4x.\n", |