diff options
author | Roger Luethi <rl@hellgate.ch> | 2006-08-15 02:00:17 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-08-19 17:44:29 -0400 |
commit | 633949a145df19d6d338b0f227f033a0a1c5562a (patch) | |
tree | d000e88532f0420eeb42c2525ae3a8d44818a29f /drivers/net | |
parent | a4d09272480e57cd4aa1156cac7aba9b08885bf9 (diff) |
[PATCH] via-rhine: NAPI support
Add NAPI support to the via-rhine driver so that it can handle higher
speeds and doesn't get overloaded by interrupts as easily.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Roger Luethi <rl@hellgate.ch>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/Kconfig | 14 | ||||
-rw-r--r-- | drivers/net/via-rhine.c | 77 |
2 files changed, 79 insertions, 12 deletions
diff --git a/drivers/net/Kconfig b/drivers/net/Kconfig index ea1796e767b7..30b3671d833d 100644 --- a/drivers/net/Kconfig +++ b/drivers/net/Kconfig | |||
@@ -1724,6 +1724,20 @@ config VIA_RHINE_MMIO | |||
1724 | 1724 | ||
1725 | If unsure, say Y. | 1725 | If unsure, say Y. |
1726 | 1726 | ||
1727 | config VIA_RHINE_NAPI | ||
1728 | bool "Use Rx Polling (NAPI)" | ||
1729 | depends on VIA_RHINE | ||
1730 | help | ||
1731 | NAPI is a new driver API designed to reduce CPU and interrupt load | ||
1732 | when the driver is receiving lots of packets from the card. | ||
1733 | |||
1734 | If your estimated Rx load is 10kpps or more, or if the card will be | ||
1735 | deployed on potentially unfriendly networks (e.g. in a firewall), | ||
1736 | then say Y here. | ||
1737 | |||
1738 | See <file:Documentation/networking/NAPI_HOWTO.txt> for more | ||
1739 | information. | ||
1740 | |||
1727 | config LAN_SAA9730 | 1741 | config LAN_SAA9730 |
1728 | bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" | 1742 | bool "Philips SAA9730 Ethernet support (EXPERIMENTAL)" |
1729 | depends on NET_PCI && EXPERIMENTAL && MIPS | 1743 | depends on NET_PCI && EXPERIMENTAL && MIPS |
diff --git a/drivers/net/via-rhine.c b/drivers/net/via-rhine.c index d3d0ec970318..fee824002d10 100644 --- a/drivers/net/via-rhine.c +++ b/drivers/net/via-rhine.c | |||
@@ -30,8 +30,8 @@ | |||
30 | */ | 30 | */ |
31 | 31 | ||
32 | #define DRV_NAME "via-rhine" | 32 | #define DRV_NAME "via-rhine" |
33 | #define DRV_VERSION "1.4.0" | 33 | #define DRV_VERSION "1.4.1" |
34 | #define DRV_RELDATE "June-27-2006" | 34 | #define DRV_RELDATE "July-24-2006" |
35 | 35 | ||
36 | 36 | ||
37 | /* A few user-configurable values. | 37 | /* A few user-configurable values. |
@@ -63,7 +63,11 @@ static const int multicast_filter_limit = 32; | |||
63 | There are no ill effects from too-large receive rings. */ | 63 | There are no ill effects from too-large receive rings. */ |
64 | #define TX_RING_SIZE 16 | 64 | #define TX_RING_SIZE 16 |
65 | #define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ | 65 | #define TX_QUEUE_LEN 10 /* Limit ring entries actually used. */ |
66 | #ifdef CONFIG_VIA_RHINE_NAPI | ||
67 | #define RX_RING_SIZE 64 | ||
68 | #else | ||
66 | #define RX_RING_SIZE 16 | 69 | #define RX_RING_SIZE 16 |
70 | #endif | ||
67 | 71 | ||
68 | 72 | ||
69 | /* Operational parameters that usually are not changed. */ | 73 | /* Operational parameters that usually are not changed. */ |
@@ -396,7 +400,7 @@ static void rhine_tx_timeout(struct net_device *dev); | |||
396 | static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); | 400 | static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev); |
397 | static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); | 401 | static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs *regs); |
398 | static void rhine_tx(struct net_device *dev); | 402 | static void rhine_tx(struct net_device *dev); |
399 | static void rhine_rx(struct net_device *dev); | 403 | static int rhine_rx(struct net_device *dev, int limit); |
400 | static void rhine_error(struct net_device *dev, int intr_status); | 404 | static void rhine_error(struct net_device *dev, int intr_status); |
401 | static void rhine_set_rx_mode(struct net_device *dev); | 405 | static void rhine_set_rx_mode(struct net_device *dev); |
402 | static struct net_device_stats *rhine_get_stats(struct net_device *dev); | 406 | static struct net_device_stats *rhine_get_stats(struct net_device *dev); |
@@ -564,6 +568,32 @@ static void rhine_poll(struct net_device *dev) | |||
564 | } | 568 | } |
565 | #endif | 569 | #endif |
566 | 570 | ||
571 | #ifdef CONFIG_VIA_RHINE_NAPI | ||
572 | static int rhine_napipoll(struct net_device *dev, int *budget) | ||
573 | { | ||
574 | struct rhine_private *rp = netdev_priv(dev); | ||
575 | void __iomem *ioaddr = rp->base; | ||
576 | int done, limit = min(dev->quota, *budget); | ||
577 | |||
578 | done = rhine_rx(dev, limit); | ||
579 | *budget -= done; | ||
580 | dev->quota -= done; | ||
581 | |||
582 | if (done < limit) { | ||
583 | netif_rx_complete(dev); | ||
584 | |||
585 | iowrite16(IntrRxDone | IntrRxErr | IntrRxEmpty| IntrRxOverflow | | ||
586 | IntrRxDropped | IntrRxNoBuf | IntrTxAborted | | ||
587 | IntrTxDone | IntrTxError | IntrTxUnderrun | | ||
588 | IntrPCIErr | IntrStatsMax | IntrLinkChange, | ||
589 | ioaddr + IntrEnable); | ||
590 | return 0; | ||
591 | } | ||
592 | else | ||
593 | return 1; | ||
594 | } | ||
595 | #endif | ||
596 | |||
567 | static void rhine_hw_init(struct net_device *dev, long pioaddr) | 597 | static void rhine_hw_init(struct net_device *dev, long pioaddr) |
568 | { | 598 | { |
569 | struct rhine_private *rp = netdev_priv(dev); | 599 | struct rhine_private *rp = netdev_priv(dev); |
@@ -744,6 +774,10 @@ static int __devinit rhine_init_one(struct pci_dev *pdev, | |||
744 | #ifdef CONFIG_NET_POLL_CONTROLLER | 774 | #ifdef CONFIG_NET_POLL_CONTROLLER |
745 | dev->poll_controller = rhine_poll; | 775 | dev->poll_controller = rhine_poll; |
746 | #endif | 776 | #endif |
777 | #ifdef CONFIG_VIA_RHINE_NAPI | ||
778 | dev->poll = rhine_napipoll; | ||
779 | dev->weight = 64; | ||
780 | #endif | ||
747 | if (rp->quirks & rqRhineI) | 781 | if (rp->quirks & rqRhineI) |
748 | dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; | 782 | dev->features |= NETIF_F_SG|NETIF_F_HW_CSUM; |
749 | 783 | ||
@@ -1165,6 +1199,7 @@ static void rhine_tx_timeout(struct net_device *dev) | |||
1165 | dev->trans_start = jiffies; | 1199 | dev->trans_start = jiffies; |
1166 | rp->stats.tx_errors++; | 1200 | rp->stats.tx_errors++; |
1167 | netif_wake_queue(dev); | 1201 | netif_wake_queue(dev); |
1202 | netif_poll_enable(dev); | ||
1168 | } | 1203 | } |
1169 | 1204 | ||
1170 | static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) | 1205 | static int rhine_start_tx(struct sk_buff *skb, struct net_device *dev) |
@@ -1268,8 +1303,18 @@ static irqreturn_t rhine_interrupt(int irq, void *dev_instance, struct pt_regs * | |||
1268 | dev->name, intr_status); | 1303 | dev->name, intr_status); |
1269 | 1304 | ||
1270 | if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | | 1305 | if (intr_status & (IntrRxDone | IntrRxErr | IntrRxDropped | |
1271 | IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) | 1306 | IntrRxWakeUp | IntrRxEmpty | IntrRxNoBuf)) { |
1272 | rhine_rx(dev); | 1307 | #ifdef CONFIG_VIA_RHINE_NAPI |
1308 | iowrite16(IntrTxAborted | | ||
1309 | IntrTxDone | IntrTxError | IntrTxUnderrun | | ||
1310 | IntrPCIErr | IntrStatsMax | IntrLinkChange, | ||
1311 | ioaddr + IntrEnable); | ||
1312 | |||
1313 | netif_rx_schedule(dev); | ||
1314 | #else | ||
1315 | rhine_rx(dev, RX_RING_SIZE); | ||
1316 | #endif | ||
1317 | } | ||
1273 | 1318 | ||
1274 | if (intr_status & (IntrTxErrSummary | IntrTxDone)) { | 1319 | if (intr_status & (IntrTxErrSummary | IntrTxDone)) { |
1275 | if (intr_status & IntrTxErrSummary) { | 1320 | if (intr_status & IntrTxErrSummary) { |
@@ -1367,13 +1412,12 @@ static void rhine_tx(struct net_device *dev) | |||
1367 | spin_unlock(&rp->lock); | 1412 | spin_unlock(&rp->lock); |
1368 | } | 1413 | } |
1369 | 1414 | ||
1370 | /* This routine is logically part of the interrupt handler, but isolated | 1415 | /* Process up to limit frames from receive ring */ |
1371 | for clarity and better register allocation. */ | 1416 | static int rhine_rx(struct net_device *dev, int limit) |
1372 | static void rhine_rx(struct net_device *dev) | ||
1373 | { | 1417 | { |
1374 | struct rhine_private *rp = netdev_priv(dev); | 1418 | struct rhine_private *rp = netdev_priv(dev); |
1419 | int count; | ||
1375 | int entry = rp->cur_rx % RX_RING_SIZE; | 1420 | int entry = rp->cur_rx % RX_RING_SIZE; |
1376 | int boguscnt = rp->dirty_rx + RX_RING_SIZE - rp->cur_rx; | ||
1377 | 1421 | ||
1378 | if (debug > 4) { | 1422 | if (debug > 4) { |
1379 | printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n", | 1423 | printk(KERN_DEBUG "%s: rhine_rx(), entry %d status %8.8x.\n", |
@@ -1382,16 +1426,18 @@ static void rhine_rx(struct net_device *dev) | |||
1382 | } | 1426 | } |
1383 | 1427 | ||
1384 | /* If EOP is set on the next entry, it's a new packet. Send it up. */ | 1428 | /* If EOP is set on the next entry, it's a new packet. Send it up. */ |
1385 | while (!(rp->rx_head_desc->rx_status & cpu_to_le32(DescOwn))) { | 1429 | for (count = 0; count < limit; ++count) { |
1386 | struct rx_desc *desc = rp->rx_head_desc; | 1430 | struct rx_desc *desc = rp->rx_head_desc; |
1387 | u32 desc_status = le32_to_cpu(desc->rx_status); | 1431 | u32 desc_status = le32_to_cpu(desc->rx_status); |
1388 | int data_size = desc_status >> 16; | 1432 | int data_size = desc_status >> 16; |
1389 | 1433 | ||
1434 | if (desc_status & DescOwn) | ||
1435 | break; | ||
1436 | |||
1390 | if (debug > 4) | 1437 | if (debug > 4) |
1391 | printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", | 1438 | printk(KERN_DEBUG "rhine_rx() status is %8.8x.\n", |
1392 | desc_status); | 1439 | desc_status); |
1393 | if (--boguscnt < 0) | 1440 | |
1394 | break; | ||
1395 | if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { | 1441 | if ((desc_status & (RxWholePkt | RxErr)) != RxWholePkt) { |
1396 | if ((desc_status & RxWholePkt) != RxWholePkt) { | 1442 | if ((desc_status & RxWholePkt) != RxWholePkt) { |
1397 | printk(KERN_WARNING "%s: Oversized Ethernet " | 1443 | printk(KERN_WARNING "%s: Oversized Ethernet " |
@@ -1460,7 +1506,11 @@ static void rhine_rx(struct net_device *dev) | |||
1460 | PCI_DMA_FROMDEVICE); | 1506 | PCI_DMA_FROMDEVICE); |
1461 | } | 1507 | } |
1462 | skb->protocol = eth_type_trans(skb, dev); | 1508 | skb->protocol = eth_type_trans(skb, dev); |
1509 | #ifdef CONFIG_VIA_RHINE_NAPI | ||
1510 | netif_receive_skb(skb); | ||
1511 | #else | ||
1463 | netif_rx(skb); | 1512 | netif_rx(skb); |
1513 | #endif | ||
1464 | dev->last_rx = jiffies; | 1514 | dev->last_rx = jiffies; |
1465 | rp->stats.rx_bytes += pkt_len; | 1515 | rp->stats.rx_bytes += pkt_len; |
1466 | rp->stats.rx_packets++; | 1516 | rp->stats.rx_packets++; |
@@ -1487,6 +1537,8 @@ static void rhine_rx(struct net_device *dev) | |||
1487 | } | 1537 | } |
1488 | rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); | 1538 | rp->rx_ring[entry].rx_status = cpu_to_le32(DescOwn); |
1489 | } | 1539 | } |
1540 | |||
1541 | return count; | ||
1490 | } | 1542 | } |
1491 | 1543 | ||
1492 | /* | 1544 | /* |
@@ -1776,6 +1828,7 @@ static int rhine_close(struct net_device *dev) | |||
1776 | spin_lock_irq(&rp->lock); | 1828 | spin_lock_irq(&rp->lock); |
1777 | 1829 | ||
1778 | netif_stop_queue(dev); | 1830 | netif_stop_queue(dev); |
1831 | netif_poll_disable(dev); | ||
1779 | 1832 | ||
1780 | if (debug > 1) | 1833 | if (debug > 1) |
1781 | printk(KERN_DEBUG "%s: Shutting down ethercard, " | 1834 | printk(KERN_DEBUG "%s: Shutting down ethercard, " |