aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/s2io.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/s2io.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/s2io.c')
-rw-r--r--drivers/net/s2io.c35
1 files changed, 15 insertions, 20 deletions
diff --git a/drivers/net/s2io.c b/drivers/net/s2io.c
index 24feb00600ee..dd012322cdbe 100644
--- a/drivers/net/s2io.c
+++ b/drivers/net/s2io.c
@@ -2568,7 +2568,7 @@ static void free_rx_buffers(struct s2io_nic *sp)
2568 2568
2569/** 2569/**
2570 * s2io_poll - Rx interrupt handler for NAPI support 2570 * s2io_poll - Rx interrupt handler for NAPI support
2571 * @dev : pointer to the device structure. 2571 * @napi : pointer to the napi structure.
2572 * @budget : The number of packets that were budgeted to be processed 2572 * @budget : The number of packets that were budgeted to be processed
2573 * during one pass through the 'Poll" function. 2573 * during one pass through the 'Poll" function.
2574 * Description: 2574 * Description:
@@ -2579,9 +2579,10 @@ static void free_rx_buffers(struct s2io_nic *sp)
2579 * 0 on success and 1 if there are No Rx packets to be processed. 2579 * 0 on success and 1 if there are No Rx packets to be processed.
2580 */ 2580 */
2581 2581
2582static int s2io_poll(struct net_device *dev, int *budget) 2582static int s2io_poll(struct napi_struct *napi, int budget)
2583{ 2583{
2584 struct s2io_nic *nic = dev->priv; 2584 struct s2io_nic *nic = container_of(napi, struct s2io_nic, napi);
2585 struct net_device *dev = nic->dev;
2585 int pkt_cnt = 0, org_pkts_to_process; 2586 int pkt_cnt = 0, org_pkts_to_process;
2586 struct mac_info *mac_control; 2587 struct mac_info *mac_control;
2587 struct config_param *config; 2588 struct config_param *config;
@@ -2592,9 +2593,7 @@ static int s2io_poll(struct net_device *dev, int *budget)
2592 mac_control = &nic->mac_control; 2593 mac_control = &nic->mac_control;
2593 config = &nic->config; 2594 config = &nic->config;
2594 2595
2595 nic->pkts_to_process = *budget; 2596 nic->pkts_to_process = budget;
2596 if (nic->pkts_to_process > dev->quota)
2597 nic->pkts_to_process = dev->quota;
2598 org_pkts_to_process = nic->pkts_to_process; 2597 org_pkts_to_process = nic->pkts_to_process;
2599 2598
2600 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int); 2599 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_int);
@@ -2608,12 +2607,8 @@ static int s2io_poll(struct net_device *dev, int *budget)
2608 goto no_rx; 2607 goto no_rx;
2609 } 2608 }
2610 } 2609 }
2611 if (!pkt_cnt)
2612 pkt_cnt = 1;
2613 2610
2614 dev->quota -= pkt_cnt; 2611 netif_rx_complete(dev, napi);
2615 *budget -= pkt_cnt;
2616 netif_rx_complete(dev);
2617 2612
2618 for (i = 0; i < config->rx_ring_num; i++) { 2613 for (i = 0; i < config->rx_ring_num; i++) {
2619 if (fill_rx_buffers(nic, i) == -ENOMEM) { 2614 if (fill_rx_buffers(nic, i) == -ENOMEM) {
@@ -2626,12 +2621,9 @@ static int s2io_poll(struct net_device *dev, int *budget)
2626 writeq(0x0, &bar0->rx_traffic_mask); 2621 writeq(0x0, &bar0->rx_traffic_mask);
2627 readl(&bar0->rx_traffic_mask); 2622 readl(&bar0->rx_traffic_mask);
2628 atomic_dec(&nic->isr_cnt); 2623 atomic_dec(&nic->isr_cnt);
2629 return 0; 2624 return pkt_cnt;
2630 2625
2631no_rx: 2626no_rx:
2632 dev->quota -= pkt_cnt;
2633 *budget -= pkt_cnt;
2634
2635 for (i = 0; i < config->rx_ring_num; i++) { 2627 for (i = 0; i < config->rx_ring_num; i++) {
2636 if (fill_rx_buffers(nic, i) == -ENOMEM) { 2628 if (fill_rx_buffers(nic, i) == -ENOMEM) {
2637 DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name); 2629 DBG_PRINT(INFO_DBG, "%s:Out of memory", dev->name);
@@ -2640,7 +2632,7 @@ no_rx:
2640 } 2632 }
2641 } 2633 }
2642 atomic_dec(&nic->isr_cnt); 2634 atomic_dec(&nic->isr_cnt);
2643 return 1; 2635 return pkt_cnt;
2644} 2636}
2645 2637
2646#ifdef CONFIG_NET_POLL_CONTROLLER 2638#ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3809,6 +3801,8 @@ static int s2io_open(struct net_device *dev)
3809 netif_carrier_off(dev); 3801 netif_carrier_off(dev);
3810 sp->last_link_state = 0; 3802 sp->last_link_state = 0;
3811 3803
3804 napi_enable(&sp->napi);
3805
3812 /* Initialize H/W and enable interrupts */ 3806 /* Initialize H/W and enable interrupts */
3813 err = s2io_card_up(sp); 3807 err = s2io_card_up(sp);
3814 if (err) { 3808 if (err) {
@@ -3828,6 +3822,7 @@ static int s2io_open(struct net_device *dev)
3828 return 0; 3822 return 0;
3829 3823
3830hw_init_failed: 3824hw_init_failed:
3825 napi_disable(&sp->napi);
3831 if (sp->intr_type == MSI_X) { 3826 if (sp->intr_type == MSI_X) {
3832 if (sp->entries) { 3827 if (sp->entries) {
3833 kfree(sp->entries); 3828 kfree(sp->entries);
@@ -3861,6 +3856,7 @@ static int s2io_close(struct net_device *dev)
3861 struct s2io_nic *sp = dev->priv; 3856 struct s2io_nic *sp = dev->priv;
3862 3857
3863 netif_stop_queue(dev); 3858 netif_stop_queue(dev);
3859 napi_disable(&sp->napi);
3864 /* Reset card, kill tasklet and free Tx and Rx buffers. */ 3860 /* Reset card, kill tasklet and free Tx and Rx buffers. */
3865 s2io_card_down(sp); 3861 s2io_card_down(sp);
3866 3862
@@ -4232,8 +4228,8 @@ static irqreturn_t s2io_isr(int irq, void *dev_id)
4232 4228
4233 if (napi) { 4229 if (napi) {
4234 if (reason & GEN_INTR_RXTRAFFIC) { 4230 if (reason & GEN_INTR_RXTRAFFIC) {
4235 if ( likely ( netif_rx_schedule_prep(dev)) ) { 4231 if (likely (netif_rx_schedule_prep(dev, &sp->napi))) {
4236 __netif_rx_schedule(dev); 4232 __netif_rx_schedule(dev, &sp->napi);
4237 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask); 4233 writeq(S2IO_MINUS_ONE, &bar0->rx_traffic_mask);
4238 } 4234 }
4239 else 4235 else
@@ -7215,8 +7211,7 @@ s2io_init_nic(struct pci_dev *pdev, const struct pci_device_id *pre)
7215 * will use eth_mac_addr() for dev->set_mac_address 7211 * will use eth_mac_addr() for dev->set_mac_address
7216 * mac address will be set every time dev->open() is called 7212 * mac address will be set every time dev->open() is called
7217 */ 7213 */
7218 dev->poll = s2io_poll; 7214 netif_napi_add(dev, &sp->napi, s2io_poll, 32);
7219 dev->weight = 32;
7220 7215
7221#ifdef CONFIG_NET_POLL_CONTROLLER 7216#ifdef CONFIG_NET_POLL_CONTROLLER
7222 dev->poll_controller = s2io_netpoll; 7217 dev->poll_controller = s2io_netpoll;