aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/netxen/netxen_nic_main.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/netxen/netxen_nic_main.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/netxen/netxen_nic_main.c')
-rw-r--r--drivers/net/netxen/netxen_nic_main.c39
1 files changed, 19 insertions, 20 deletions
diff --git a/drivers/net/netxen/netxen_nic_main.c b/drivers/net/netxen/netxen_nic_main.c
index 3122d0101638..a10bbefbdadd 100644
--- a/drivers/net/netxen/netxen_nic_main.c
+++ b/drivers/net/netxen/netxen_nic_main.c
@@ -68,7 +68,7 @@ static void netxen_tx_timeout(struct net_device *netdev);
68static void netxen_tx_timeout_task(struct work_struct *work); 68static void netxen_tx_timeout_task(struct work_struct *work);
69static void netxen_watchdog(unsigned long); 69static void netxen_watchdog(unsigned long);
70static int netxen_handle_int(struct netxen_adapter *, struct net_device *); 70static int netxen_handle_int(struct netxen_adapter *, struct net_device *);
71static int netxen_nic_poll(struct net_device *dev, int *budget); 71static int netxen_nic_poll(struct napi_struct *napi, int budget);
72#ifdef CONFIG_NET_POLL_CONTROLLER 72#ifdef CONFIG_NET_POLL_CONTROLLER
73static void netxen_nic_poll_controller(struct net_device *netdev); 73static void netxen_nic_poll_controller(struct net_device *netdev);
74#endif 74#endif
@@ -402,6 +402,9 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
402 adapter->netdev = netdev; 402 adapter->netdev = netdev;
403 adapter->pdev = pdev; 403 adapter->pdev = pdev;
404 404
405 netif_napi_add(netdev, &adapter->napi,
406 netxen_nic_poll, NETXEN_NETDEV_WEIGHT);
407
405 /* this will be read from FW later */ 408 /* this will be read from FW later */
406 adapter->intr_scheme = -1; 409 adapter->intr_scheme = -1;
407 410
@@ -422,8 +425,6 @@ netxen_nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
422 netxen_nic_change_mtu(netdev, netdev->mtu); 425 netxen_nic_change_mtu(netdev, netdev->mtu);
423 426
424 SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops); 427 SET_ETHTOOL_OPS(netdev, &netxen_nic_ethtool_ops);
425 netdev->poll = netxen_nic_poll;
426 netdev->weight = NETXEN_NETDEV_WEIGHT;
427#ifdef CONFIG_NET_POLL_CONTROLLER 428#ifdef CONFIG_NET_POLL_CONTROLLER
428 netdev->poll_controller = netxen_nic_poll_controller; 429 netdev->poll_controller = netxen_nic_poll_controller;
429#endif 430#endif
@@ -885,6 +886,8 @@ static int netxen_nic_open(struct net_device *netdev)
885 if (!adapter->driver_mismatch) 886 if (!adapter->driver_mismatch)
886 mod_timer(&adapter->watchdog_timer, jiffies); 887 mod_timer(&adapter->watchdog_timer, jiffies);
887 888
889 napi_enable(&adapter->napi);
890
888 netxen_nic_enable_int(adapter); 891 netxen_nic_enable_int(adapter);
889 892
890 /* Done here again so that even if phantom sw overwrote it, 893 /* Done here again so that even if phantom sw overwrote it,
@@ -894,6 +897,7 @@ static int netxen_nic_open(struct net_device *netdev)
894 del_timer_sync(&adapter->watchdog_timer); 897 del_timer_sync(&adapter->watchdog_timer);
895 printk(KERN_ERR "%s: Failed to initialize port %d\n", 898 printk(KERN_ERR "%s: Failed to initialize port %d\n",
896 netxen_nic_driver_name, adapter->portnum); 899 netxen_nic_driver_name, adapter->portnum);
900 napi_disable(&adapter->napi);
897 return -EIO; 901 return -EIO;
898 } 902 }
899 if (adapter->macaddr_set) 903 if (adapter->macaddr_set)
@@ -923,6 +927,7 @@ static int netxen_nic_close(struct net_device *netdev)
923 927
924 netif_carrier_off(netdev); 928 netif_carrier_off(netdev);
925 netif_stop_queue(netdev); 929 netif_stop_queue(netdev);
930 napi_disable(&adapter->napi);
926 931
927 netxen_nic_disable_int(adapter); 932 netxen_nic_disable_int(adapter);
928 933
@@ -1243,11 +1248,11 @@ netxen_handle_int(struct netxen_adapter *adapter, struct net_device *netdev)
1243 netxen_nic_disable_int(adapter); 1248 netxen_nic_disable_int(adapter);
1244 1249
1245 if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) { 1250 if (netxen_nic_rx_has_work(adapter) || netxen_nic_tx_has_work(adapter)) {
1246 if (netif_rx_schedule_prep(netdev)) { 1251 if (netif_rx_schedule_prep(netdev, &adapter->napi)) {
1247 /* 1252 /*
1248 * Interrupts are already disabled. 1253 * Interrupts are already disabled.
1249 */ 1254 */
1250 __netif_rx_schedule(netdev); 1255 __netif_rx_schedule(netdev, &adapter->napi);
1251 } else { 1256 } else {
1252 static unsigned int intcount = 0; 1257 static unsigned int intcount = 0;
1253 if ((++intcount & 0xfff) == 0xfff) 1258 if ((++intcount & 0xfff) == 0xfff)
@@ -1305,14 +1310,13 @@ irqreturn_t netxen_intr(int irq, void *data)
1305 return IRQ_HANDLED; 1310 return IRQ_HANDLED;
1306} 1311}
1307 1312
1308static int netxen_nic_poll(struct net_device *netdev, int *budget) 1313static int netxen_nic_poll(struct napi_struct *napi, int budget)
1309{ 1314{
1310 struct netxen_adapter *adapter = netdev_priv(netdev); 1315 struct netxen_adapter *adapter = container_of(napi, struct netxen_adapter, napi);
1311 int work_to_do = min(*budget, netdev->quota); 1316 struct net_device *netdev = adapter->netdev;
1312 int done = 1; 1317 int done = 1;
1313 int ctx; 1318 int ctx;
1314 int this_work_done; 1319 int work_done;
1315 int work_done = 0;
1316 1320
1317 DPRINTK(INFO, "polling for %d descriptors\n", *budget); 1321 DPRINTK(INFO, "polling for %d descriptors\n", *budget);
1318 1322
@@ -1330,16 +1334,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
1330 * packets are on one context, it gets only half of the quota, 1334 * packets are on one context, it gets only half of the quota,
1331 * and ends up not processing it. 1335 * and ends up not processing it.
1332 */ 1336 */
1333 this_work_done = netxen_process_rcv_ring(adapter, ctx, 1337 work_done += netxen_process_rcv_ring(adapter, ctx,
1334 work_to_do / 1338 budget / MAX_RCV_CTX);
1335 MAX_RCV_CTX);
1336 work_done += this_work_done;
1337 } 1339 }
1338 1340
1339 netdev->quota -= work_done; 1341 if (work_done >= budget && netxen_nic_rx_has_work(adapter) != 0)
1340 *budget -= work_done;
1341
1342 if (work_done >= work_to_do && netxen_nic_rx_has_work(adapter) != 0)
1343 done = 0; 1342 done = 0;
1344 1343
1345 if (netxen_process_cmd_ring((unsigned long)adapter) == 0) 1344 if (netxen_process_cmd_ring((unsigned long)adapter) == 0)
@@ -1348,11 +1347,11 @@ static int netxen_nic_poll(struct net_device *netdev, int *budget)
1348 DPRINTK(INFO, "new work_done: %d work_to_do: %d\n", 1347 DPRINTK(INFO, "new work_done: %d work_to_do: %d\n",
1349 work_done, work_to_do); 1348 work_done, work_to_do);
1350 if (done) { 1349 if (done) {
1351 netif_rx_complete(netdev); 1350 netif_rx_complete(netdev, napi);
1352 netxen_nic_enable_int(adapter); 1351 netxen_nic_enable_int(adapter);
1353 } 1352 }
1354 1353
1355 return !done; 1354 return work_done;
1356} 1355}
1357 1356
1358#ifdef CONFIG_NET_POLL_CONTROLLER 1357#ifdef CONFIG_NET_POLL_CONTROLLER