aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
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/infiniband
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/infiniband')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h4
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c43
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c11
3 files changed, 29 insertions, 29 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 285c143115cc..35f3ca42bd60 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -228,6 +228,8 @@ struct ipoib_dev_priv {
228 228
229 struct net_device *dev; 229 struct net_device *dev;
230 230
231 struct napi_struct napi;
232
231 unsigned long flags; 233 unsigned long flags;
232 234
233 struct mutex mcast_mutex; 235 struct mutex mcast_mutex;
@@ -351,7 +353,7 @@ extern struct workqueue_struct *ipoib_workqueue;
351 353
352/* functions */ 354/* functions */
353 355
354int ipoib_poll(struct net_device *dev, int *budget); 356int ipoib_poll(struct napi_struct *napi, int budget);
355void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); 357void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
356 358
357struct ipoib_ah *ipoib_create_ah(struct net_device *dev, 359struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 10944888cffd..481e4b6bd949 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -281,63 +281,58 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
281 wc->status, wr_id, wc->vendor_err); 281 wc->status, wr_id, wc->vendor_err);
282} 282}
283 283
284int ipoib_poll(struct net_device *dev, int *budget) 284int ipoib_poll(struct napi_struct *napi, int budget)
285{ 285{
286 struct ipoib_dev_priv *priv = netdev_priv(dev); 286 struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
287 int max = min(*budget, dev->quota); 287 struct net_device *dev = priv->dev;
288 int done; 288 int done;
289 int t; 289 int t;
290 int empty;
291 int n, i; 290 int n, i;
292 291
293 done = 0; 292 done = 0;
294 empty = 0;
295 293
296 while (max) { 294poll_more:
295 while (done < budget) {
296 int max = (budget - done);
297
297 t = min(IPOIB_NUM_WC, max); 298 t = min(IPOIB_NUM_WC, max);
298 n = ib_poll_cq(priv->cq, t, priv->ibwc); 299 n = ib_poll_cq(priv->cq, t, priv->ibwc);
299 300
300 for (i = 0; i < n; ++i) { 301 for (i = 0; i < n; i++) {
301 struct ib_wc *wc = priv->ibwc + i; 302 struct ib_wc *wc = priv->ibwc + i;
302 303
303 if (wc->wr_id & IPOIB_CM_OP_SRQ) { 304 if (wc->wr_id & IPOIB_CM_OP_SRQ) {
304 ++done; 305 ++done;
305 --max;
306 ipoib_cm_handle_rx_wc(dev, wc); 306 ipoib_cm_handle_rx_wc(dev, wc);
307 } else if (wc->wr_id & IPOIB_OP_RECV) { 307 } else if (wc->wr_id & IPOIB_OP_RECV) {
308 ++done; 308 ++done;
309 --max;
310 ipoib_ib_handle_rx_wc(dev, wc); 309 ipoib_ib_handle_rx_wc(dev, wc);
311 } else 310 } else
312 ipoib_ib_handle_tx_wc(dev, wc); 311 ipoib_ib_handle_tx_wc(dev, wc);
313 } 312 }
314 313
315 if (n != t) { 314 if (n != t)
316 empty = 1;
317 break; 315 break;
318 }
319 } 316 }
320 317
321 dev->quota -= done; 318 if (done < budget) {
322 *budget -= done; 319 netif_rx_complete(dev, napi);
323
324 if (empty) {
325 netif_rx_complete(dev);
326 if (unlikely(ib_req_notify_cq(priv->cq, 320 if (unlikely(ib_req_notify_cq(priv->cq,
327 IB_CQ_NEXT_COMP | 321 IB_CQ_NEXT_COMP |
328 IB_CQ_REPORT_MISSED_EVENTS)) && 322 IB_CQ_REPORT_MISSED_EVENTS)) &&
329 netif_rx_reschedule(dev, 0)) 323 netif_rx_reschedule(dev, napi))
330 return 1; 324 goto poll_more;
331
332 return 0;
333 } 325 }
334 326
335 return 1; 327 return done;
336} 328}
337 329
338void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr) 330void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
339{ 331{
340 netif_rx_schedule(dev_ptr); 332 struct net_device *dev = dev_ptr;
333 struct ipoib_dev_priv *priv = netdev_priv(dev);
334
335 netif_rx_schedule(dev, &priv->napi);
341} 336}
342 337
343static inline int post_send(struct ipoib_dev_priv *priv, 338static inline int post_send(struct ipoib_dev_priv *priv,
@@ -577,7 +572,6 @@ int ipoib_ib_dev_stop(struct net_device *dev, int flush)
577 int i; 572 int i;
578 573
579 clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); 574 clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
580 netif_poll_disable(dev);
581 575
582 ipoib_cm_dev_stop(dev); 576 ipoib_cm_dev_stop(dev);
583 577
@@ -660,7 +654,6 @@ timeout:
660 msleep(1); 654 msleep(1);
661 } 655 }
662 656
663 netif_poll_enable(dev);
664 ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP); 657 ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
665 658
666 return 0; 659 return 0;
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index 894b1dcdf3eb..a59ff07ec3cd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -98,16 +98,20 @@ int ipoib_open(struct net_device *dev)
98 98
99 ipoib_dbg(priv, "bringing up interface\n"); 99 ipoib_dbg(priv, "bringing up interface\n");
100 100
101 napi_enable(&priv->napi);
101 set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 102 set_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
102 103
103 if (ipoib_pkey_dev_delay_open(dev)) 104 if (ipoib_pkey_dev_delay_open(dev))
104 return 0; 105 return 0;
105 106
106 if (ipoib_ib_dev_open(dev)) 107 if (ipoib_ib_dev_open(dev)) {
108 napi_disable(&priv->napi);
107 return -EINVAL; 109 return -EINVAL;
110 }
108 111
109 if (ipoib_ib_dev_up(dev)) { 112 if (ipoib_ib_dev_up(dev)) {
110 ipoib_ib_dev_stop(dev, 1); 113 ipoib_ib_dev_stop(dev, 1);
114 napi_disable(&priv->napi);
111 return -EINVAL; 115 return -EINVAL;
112 } 116 }
113 117
@@ -140,6 +144,7 @@ static int ipoib_stop(struct net_device *dev)
140 ipoib_dbg(priv, "stopping interface\n"); 144 ipoib_dbg(priv, "stopping interface\n");
141 145
142 clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags); 146 clear_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags);
147 napi_disable(&priv->napi);
143 148
144 netif_stop_queue(dev); 149 netif_stop_queue(dev);
145 150
@@ -948,8 +953,8 @@ static void ipoib_setup(struct net_device *dev)
948 dev->hard_header = ipoib_hard_header; 953 dev->hard_header = ipoib_hard_header;
949 dev->set_multicast_list = ipoib_set_mcast_list; 954 dev->set_multicast_list = ipoib_set_mcast_list;
950 dev->neigh_setup = ipoib_neigh_setup_dev; 955 dev->neigh_setup = ipoib_neigh_setup_dev;
951 dev->poll = ipoib_poll; 956
952 dev->weight = 100; 957 netif_napi_add(dev, &priv->napi, ipoib_poll, 100);
953 958
954 dev->watchdog_timeo = HZ; 959 dev->watchdog_timeo = HZ;
955 960