aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb3/cxgb3_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/cxgb3/cxgb3_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/cxgb3/cxgb3_main.c')
-rw-r--r--drivers/net/cxgb3/cxgb3_main.c96
1 files changed, 27 insertions, 69 deletions
diff --git a/drivers/net/cxgb3/cxgb3_main.c b/drivers/net/cxgb3/cxgb3_main.c
index 5ab319cfe5de..5db7d4e27ec0 100644
--- a/drivers/net/cxgb3/cxgb3_main.c
+++ b/drivers/net/cxgb3/cxgb3_main.c
@@ -339,49 +339,17 @@ static void setup_rss(struct adapter *adap)
339 V_RRCPLCPUSIZE(6), cpus, rspq_map); 339 V_RRCPLCPUSIZE(6), cpus, rspq_map);
340} 340}
341 341
342/* 342static void init_napi(struct adapter *adap)
343 * If we have multiple receive queues per port serviced by NAPI we need one
344 * netdevice per queue as NAPI operates on netdevices. We already have one
345 * netdevice, namely the one associated with the interface, so we use dummy
346 * ones for any additional queues. Note that these netdevices exist purely
347 * so that NAPI has something to work with, they do not represent network
348 * ports and are not registered.
349 */
350static int init_dummy_netdevs(struct adapter *adap)
351{ 343{
352 int i, j, dummy_idx = 0; 344 int i;
353 struct net_device *nd;
354
355 for_each_port(adap, i) {
356 struct net_device *dev = adap->port[i];
357 const struct port_info *pi = netdev_priv(dev);
358
359 for (j = 0; j < pi->nqsets - 1; j++) {
360 if (!adap->dummy_netdev[dummy_idx]) {
361 struct port_info *p;
362
363 nd = alloc_netdev(sizeof(*p), "", ether_setup);
364 if (!nd)
365 goto free_all;
366 345
367 p = netdev_priv(nd); 346 for (i = 0; i < SGE_QSETS; i++) {
368 p->adapter = adap; 347 struct sge_qset *qs = &adap->sge.qs[i];
369 nd->weight = 64;
370 set_bit(__LINK_STATE_START, &nd->state);
371 adap->dummy_netdev[dummy_idx] = nd;
372 }
373 strcpy(adap->dummy_netdev[dummy_idx]->name, dev->name);
374 dummy_idx++;
375 }
376 }
377 return 0;
378 348
379free_all: 349 if (qs->adap)
380 while (--dummy_idx >= 0) { 350 netif_napi_add(qs->netdev, &qs->napi, qs->napi.poll,
381 free_netdev(adap->dummy_netdev[dummy_idx]); 351 64);
382 adap->dummy_netdev[dummy_idx] = NULL;
383 } 352 }
384 return -ENOMEM;
385} 353}
386 354
387/* 355/*
@@ -392,20 +360,18 @@ free_all:
392static void quiesce_rx(struct adapter *adap) 360static void quiesce_rx(struct adapter *adap)
393{ 361{
394 int i; 362 int i;
395 struct net_device *dev;
396 363
397 for_each_port(adap, i) { 364 for (i = 0; i < SGE_QSETS; i++)
398 dev = adap->port[i]; 365 if (adap->sge.qs[i].adap)
399 while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) 366 napi_disable(&adap->sge.qs[i].napi);
400 msleep(1); 367}
401 }
402 368
403 for (i = 0; i < ARRAY_SIZE(adap->dummy_netdev); i++) { 369static void enable_all_napi(struct adapter *adap)
404 dev = adap->dummy_netdev[i]; 370{
405 if (dev) 371 int i;
406 while (test_bit(__LINK_STATE_RX_SCHED, &dev->state)) 372 for (i = 0; i < SGE_QSETS; i++)
407 msleep(1); 373 if (adap->sge.qs[i].adap)
408 } 374 napi_enable(&adap->sge.qs[i].napi);
409} 375}
410 376
411/** 377/**
@@ -418,7 +384,7 @@ static void quiesce_rx(struct adapter *adap)
418 */ 384 */
419static int setup_sge_qsets(struct adapter *adap) 385static int setup_sge_qsets(struct adapter *adap)
420{ 386{
421 int i, j, err, irq_idx = 0, qset_idx = 0, dummy_dev_idx = 0; 387 int i, j, err, irq_idx = 0, qset_idx = 0;
422 unsigned int ntxq = SGE_TXQ_PER_SET; 388 unsigned int ntxq = SGE_TXQ_PER_SET;
423 389
424 if (adap->params.rev > 0 && !(adap->flags & USING_MSI)) 390 if (adap->params.rev > 0 && !(adap->flags & USING_MSI))
@@ -426,15 +392,14 @@ static int setup_sge_qsets(struct adapter *adap)
426 392
427 for_each_port(adap, i) { 393 for_each_port(adap, i) {
428 struct net_device *dev = adap->port[i]; 394 struct net_device *dev = adap->port[i];
429 const struct port_info *pi = netdev_priv(dev); 395 struct port_info *pi = netdev_priv(dev);
430 396
397 pi->qs = &adap->sge.qs[pi->first_qset];
431 for (j = 0; j < pi->nqsets; ++j, ++qset_idx) { 398 for (j = 0; j < pi->nqsets; ++j, ++qset_idx) {
432 err = t3_sge_alloc_qset(adap, qset_idx, 1, 399 err = t3_sge_alloc_qset(adap, qset_idx, 1,
433 (adap->flags & USING_MSIX) ? qset_idx + 1 : 400 (adap->flags & USING_MSIX) ? qset_idx + 1 :
434 irq_idx, 401 irq_idx,
435 &adap->params.sge.qset[qset_idx], ntxq, 402 &adap->params.sge.qset[qset_idx], ntxq, dev);
436 j == 0 ? dev :
437 adap-> dummy_netdev[dummy_dev_idx++]);
438 if (err) { 403 if (err) {
439 t3_free_sge_resources(adap); 404 t3_free_sge_resources(adap);
440 return err; 405 return err;
@@ -845,21 +810,18 @@ static int cxgb_up(struct adapter *adap)
845 goto out; 810 goto out;
846 } 811 }
847 812
848 err = init_dummy_netdevs(adap);
849 if (err)
850 goto out;
851
852 err = t3_init_hw(adap, 0); 813 err = t3_init_hw(adap, 0);
853 if (err) 814 if (err)
854 goto out; 815 goto out;
855 816
856 t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12)); 817 t3_write_reg(adap, A_ULPRX_TDDP_PSZ, V_HPZ0(PAGE_SHIFT - 12));
857 818
858 err = setup_sge_qsets(adap); 819 err = setup_sge_qsets(adap);
859 if (err) 820 if (err)
860 goto out; 821 goto out;
861 822
862 setup_rss(adap); 823 setup_rss(adap);
824 init_napi(adap);
863 adap->flags |= FULL_INIT_DONE; 825 adap->flags |= FULL_INIT_DONE;
864 } 826 }
865 827
@@ -886,6 +848,7 @@ static int cxgb_up(struct adapter *adap)
886 adap->name, adap))) 848 adap->name, adap)))
887 goto irq_err; 849 goto irq_err;
888 850
851 enable_all_napi(adap);
889 t3_sge_start(adap); 852 t3_sge_start(adap);
890 t3_intr_enable(adap); 853 t3_intr_enable(adap);
891 854
@@ -1012,8 +975,10 @@ static int cxgb_open(struct net_device *dev)
1012 int other_ports = adapter->open_device_map & PORT_MASK; 975 int other_ports = adapter->open_device_map & PORT_MASK;
1013 int err; 976 int err;
1014 977
1015 if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) 978 if (!adapter->open_device_map && (err = cxgb_up(adapter)) < 0) {
979 quiesce_rx(adapter);
1016 return err; 980 return err;
981 }
1017 982
1018 set_bit(pi->port_id, &adapter->open_device_map); 983 set_bit(pi->port_id, &adapter->open_device_map);
1019 if (is_offload(adapter) && !ofld_disable) { 984 if (is_offload(adapter) && !ofld_disable) {
@@ -2524,7 +2489,6 @@ static int __devinit init_one(struct pci_dev *pdev,
2524#ifdef CONFIG_NET_POLL_CONTROLLER 2489#ifdef CONFIG_NET_POLL_CONTROLLER
2525 netdev->poll_controller = cxgb_netpoll; 2490 netdev->poll_controller = cxgb_netpoll;
2526#endif 2491#endif
2527 netdev->weight = 64;
2528 2492
2529 SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops); 2493 SET_ETHTOOL_OPS(netdev, &cxgb_ethtool_ops);
2530 } 2494 }
@@ -2625,12 +2589,6 @@ static void __devexit remove_one(struct pci_dev *pdev)
2625 t3_free_sge_resources(adapter); 2589 t3_free_sge_resources(adapter);
2626 cxgb_disable_msi(adapter); 2590 cxgb_disable_msi(adapter);
2627 2591
2628 for (i = 0; i < ARRAY_SIZE(adapter->dummy_netdev); i++)
2629 if (adapter->dummy_netdev[i]) {
2630 free_netdev(adapter->dummy_netdev[i]);
2631 adapter->dummy_netdev[i] = NULL;
2632 }
2633
2634 for_each_port(adapter, i) 2592 for_each_port(adapter, i)
2635 if (adapter->port[i]) 2593 if (adapter->port[i])
2636 free_netdev(adapter->port[i]); 2594 free_netdev(adapter->port[i]);