aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/spider_net.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-10-03 19:41:36 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-10-10 19:47:45 -0400
commitbea3348eef27e6044b6161fd04c3152215f96411 (patch)
treef0990b263e5ce42505d290a4c346fe990bcd4c33 /drivers/net/spider_net.c
parentdde4e47e8fe333a5649a3fa0e7db1fa7c08d6158 (diff)
[NET]: Make NAPI polling independent of struct net_device objects.
Several devices have multiple independant RX queues per net device, and some have a single interrupt doorbell for several queues. In either case, it's easier to support layouts like that if the structure representing the poll is independant from the net device itself. The signature of the ->poll() call back goes from: int foo_poll(struct net_device *dev, int *budget) to int foo_poll(struct napi_struct *napi, int budget) The caller is returned the number of RX packets processed (or the number of "NAPI credits" consumed if you want to get abstract). The callee no longer messes around bumping dev->quota, *budget, etc. because that is all handled in the caller upon return. The napi_struct is to be embedded in the device driver private data structures. Furthermore, it is the driver's responsibility to disable all NAPI instances in it's ->stop() device close handler. Since the napi_struct is privatized into the driver's private data structures, only the driver knows how to get at all of the napi_struct instances it may have per-device. With lots of help and suggestions from Rusty Russell, Roland Dreier, Michael Chan, Jeff Garzik, and Jamal Hadi Salim. Bug fixes from Thomas Graf, Roland Dreier, Peter Zijlstra, Joseph Fannin, Scott Wood, Hans J. Koch, and Michael Chan. [ Ported to current tree and all drivers converted. Integrated Stephen's follow-on kerneldoc additions, and restored poll_list handling to the old style to fix mutual exclusion issues. -DaveM ] Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/spider_net.c')
-rw-r--r--drivers/net/spider_net.c60
1 files changed, 27 insertions, 33 deletions
diff --git a/drivers/net/spider_net.c b/drivers/net/spider_net.c
index 82d837ab4db9..6d8f2bb7e0f9 100644
--- a/drivers/net/spider_net.c
+++ b/drivers/net/spider_net.c
@@ -1278,34 +1278,26 @@ bad_desc:
1278 * (using netif_receive_skb). If all/enough packets are up, the driver 1278 * (using netif_receive_skb). If all/enough packets are up, the driver
1279 * reenables interrupts and returns 0. If not, 1 is returned. 1279 * reenables interrupts and returns 0. If not, 1 is returned.
1280 */ 1280 */
1281static int 1281static int spider_net_poll(struct napi_struct *napi, int budget)
1282spider_net_poll(struct net_device *netdev, int *budget)
1283{ 1282{
1284 struct spider_net_card *card = netdev_priv(netdev); 1283 struct spider_net_card *card = container_of(napi, struct spider_net_card, napi);
1285 int packets_to_do, packets_done = 0; 1284 struct net_device *netdev = card->netdev;
1286 int no_more_packets = 0; 1285 int packets_done = 0;
1287 1286
1288 packets_to_do = min(*budget, netdev->quota); 1287 while (packets_done < budget) {
1289 1288 if (!spider_net_decode_one_descr(card))
1290 while (packets_to_do) {
1291 if (spider_net_decode_one_descr(card)) {
1292 packets_done++;
1293 packets_to_do--;
1294 } else {
1295 /* no more packets for the stack */
1296 no_more_packets = 1;
1297 break; 1289 break;
1298 } 1290
1291 packets_done++;
1299 } 1292 }
1300 1293
1301 if ((packets_done == 0) && (card->num_rx_ints != 0)) { 1294 if ((packets_done == 0) && (card->num_rx_ints != 0)) {
1302 no_more_packets = spider_net_resync_tail_ptr(card); 1295 if (!spider_net_resync_tail_ptr(card))
1296 packets_done = budget;
1303 spider_net_resync_head_ptr(card); 1297 spider_net_resync_head_ptr(card);
1304 } 1298 }
1305 card->num_rx_ints = 0; 1299 card->num_rx_ints = 0;
1306 1300
1307 netdev->quota -= packets_done;
1308 *budget -= packets_done;
1309 spider_net_refill_rx_chain(card); 1301 spider_net_refill_rx_chain(card);
1310 spider_net_enable_rxdmac(card); 1302 spider_net_enable_rxdmac(card);
1311 1303
@@ -1313,14 +1305,13 @@ spider_net_poll(struct net_device *netdev, int *budget)
1313 1305
1314 /* if all packets are in the stack, enable interrupts and return 0 */ 1306 /* if all packets are in the stack, enable interrupts and return 0 */
1315 /* if not, return 1 */ 1307 /* if not, return 1 */
1316 if (no_more_packets) { 1308 if (packets_done < budget) {
1317 netif_rx_complete(netdev); 1309 netif_rx_complete(netdev, napi);
1318 spider_net_rx_irq_on(card); 1310 spider_net_rx_irq_on(card);
1319 card->ignore_rx_ramfull = 0; 1311 card->ignore_rx_ramfull = 0;
1320 return 0;
1321 } 1312 }
1322 1313
1323 return 1; 1314 return packets_done;
1324} 1315}
1325 1316
1326/** 1317/**
@@ -1560,7 +1551,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
1560 spider_net_refill_rx_chain(card); 1551 spider_net_refill_rx_chain(card);
1561 spider_net_enable_rxdmac(card); 1552 spider_net_enable_rxdmac(card);
1562 card->num_rx_ints ++; 1553 card->num_rx_ints ++;
1563 netif_rx_schedule(card->netdev); 1554 netif_rx_schedule(card->netdev,
1555 &card->napi);
1564 } 1556 }
1565 show_error = 0; 1557 show_error = 0;
1566 break; 1558 break;
@@ -1580,7 +1572,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
1580 spider_net_refill_rx_chain(card); 1572 spider_net_refill_rx_chain(card);
1581 spider_net_enable_rxdmac(card); 1573 spider_net_enable_rxdmac(card);
1582 card->num_rx_ints ++; 1574 card->num_rx_ints ++;
1583 netif_rx_schedule(card->netdev); 1575 netif_rx_schedule(card->netdev,
1576 &card->napi);
1584 show_error = 0; 1577 show_error = 0;
1585 break; 1578 break;
1586 1579
@@ -1594,7 +1587,8 @@ spider_net_handle_error_irq(struct spider_net_card *card, u32 status_reg)
1594 spider_net_refill_rx_chain(card); 1587 spider_net_refill_rx_chain(card);
1595 spider_net_enable_rxdmac(card); 1588 spider_net_enable_rxdmac(card);
1596 card->num_rx_ints ++; 1589 card->num_rx_ints ++;
1597 netif_rx_schedule(card->netdev); 1590 netif_rx_schedule(card->netdev,
1591 &card->napi);
1598 show_error = 0; 1592 show_error = 0;
1599 break; 1593 break;
1600 1594
@@ -1686,11 +1680,11 @@ spider_net_interrupt(int irq, void *ptr)
1686 1680
1687 if (status_reg & SPIDER_NET_RXINT ) { 1681 if (status_reg & SPIDER_NET_RXINT ) {
1688 spider_net_rx_irq_off(card); 1682 spider_net_rx_irq_off(card);
1689 netif_rx_schedule(netdev); 1683 netif_rx_schedule(netdev, &card->napi);
1690 card->num_rx_ints ++; 1684 card->num_rx_ints ++;
1691 } 1685 }
1692 if (status_reg & SPIDER_NET_TXINT) 1686 if (status_reg & SPIDER_NET_TXINT)
1693 netif_rx_schedule(netdev); 1687 netif_rx_schedule(netdev, &card->napi);
1694 1688
1695 if (status_reg & SPIDER_NET_LINKINT) 1689 if (status_reg & SPIDER_NET_LINKINT)
1696 spider_net_link_reset(netdev); 1690 spider_net_link_reset(netdev);
@@ -2034,7 +2028,7 @@ spider_net_open(struct net_device *netdev)
2034 2028
2035 netif_start_queue(netdev); 2029 netif_start_queue(netdev);
2036 netif_carrier_on(netdev); 2030 netif_carrier_on(netdev);
2037 netif_poll_enable(netdev); 2031 napi_enable(&card->napi);
2038 2032
2039 spider_net_enable_interrupts(card); 2033 spider_net_enable_interrupts(card);
2040 2034
@@ -2204,7 +2198,7 @@ spider_net_stop(struct net_device *netdev)
2204{ 2198{
2205 struct spider_net_card *card = netdev_priv(netdev); 2199 struct spider_net_card *card = netdev_priv(netdev);
2206 2200
2207 netif_poll_disable(netdev); 2201 napi_disable(&card->napi);
2208 netif_carrier_off(netdev); 2202 netif_carrier_off(netdev);
2209 netif_stop_queue(netdev); 2203 netif_stop_queue(netdev);
2210 del_timer_sync(&card->tx_timer); 2204 del_timer_sync(&card->tx_timer);
@@ -2304,9 +2298,6 @@ spider_net_setup_netdev_ops(struct net_device *netdev)
2304 /* tx watchdog */ 2298 /* tx watchdog */
2305 netdev->tx_timeout = &spider_net_tx_timeout; 2299 netdev->tx_timeout = &spider_net_tx_timeout;
2306 netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT; 2300 netdev->watchdog_timeo = SPIDER_NET_WATCHDOG_TIMEOUT;
2307 /* NAPI */
2308 netdev->poll = &spider_net_poll;
2309 netdev->weight = SPIDER_NET_NAPI_WEIGHT;
2310 /* HW VLAN */ 2301 /* HW VLAN */
2311#ifdef CONFIG_NET_POLL_CONTROLLER 2302#ifdef CONFIG_NET_POLL_CONTROLLER
2312 /* poll controller */ 2303 /* poll controller */
@@ -2351,6 +2342,9 @@ spider_net_setup_netdev(struct spider_net_card *card)
2351 2342
2352 card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT; 2343 card->options.rx_csum = SPIDER_NET_RX_CSUM_DEFAULT;
2353 2344
2345 netif_napi_add(netdev, &card->napi,
2346 spider_net_poll, SPIDER_NET_NAPI_WEIGHT);
2347
2354 spider_net_setup_netdev_ops(netdev); 2348 spider_net_setup_netdev_ops(netdev);
2355 2349
2356 netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX; 2350 netdev->features = NETIF_F_IP_CSUM | NETIF_F_LLTX;