Skip to content

Commit

Permalink
IPoIB: Convert to NAPI
Browse files Browse the repository at this point in the history
Convert the IP-over-InfiniBand network device driver over to using
NAPI to handle completions for the main CQ.  This covers all receives
as well as datagram mode sends; send completions for connected mode
connections are still handled from interrupt context.

Signed-off-by: Roland Dreier <rolandd@cisco.com>
  • Loading branch information
Roland Dreier committed May 7, 2007
1 parent ed23a72 commit 8d1cc86
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 20 deletions.
1 change: 1 addition & 0 deletions drivers/infiniband/ulp/ipoib/ipoib.h
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ extern struct workqueue_struct *ipoib_workqueue;

/* functions */

int ipoib_poll(struct net_device *dev, int *budget);
void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);

struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
Expand Down
2 changes: 1 addition & 1 deletion drivers/infiniband/ulp/ipoib/ipoib_cm.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,7 +416,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb->dev = dev;
/* XXX get correct PACKET_ type here */
skb->pkt_type = PACKET_HOST;
netif_rx_ni(skb);
netif_receive_skb(skb);

repost:
if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
Expand Down
89 changes: 70 additions & 19 deletions drivers/infiniband/ulp/ipoib/ipoib_ib.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb->dev = dev;
/* XXX get correct PACKET_ type here */
skb->pkt_type = PACKET_HOST;
netif_rx_ni(skb);
netif_receive_skb(skb);
} else {
ipoib_dbg_data(priv, "dropping loopback packet\n");
dev_kfree_skb_any(skb);
Expand Down Expand Up @@ -280,28 +280,63 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
wc->status, wr_id, wc->vendor_err);
}

static void ipoib_ib_handle_wc(struct net_device *dev, struct ib_wc *wc)
int ipoib_poll(struct net_device *dev, int *budget)
{
if (wc->wr_id & IPOIB_CM_OP_SRQ)
ipoib_cm_handle_rx_wc(dev, wc);
else if (wc->wr_id & IPOIB_OP_RECV)
ipoib_ib_handle_rx_wc(dev, wc);
else
ipoib_ib_handle_tx_wc(dev, wc);
struct ipoib_dev_priv *priv = netdev_priv(dev);
int max = min(*budget, dev->quota);
int done;
int t;
int empty;
int n, i;

done = 0;
empty = 0;

while (max) {
t = min(IPOIB_NUM_WC, max);
n = ib_poll_cq(priv->cq, t, priv->ibwc);

for (i = 0; i < n; ++i) {
struct ib_wc *wc = priv->ibwc + i;

if (wc->wr_id & IPOIB_CM_OP_SRQ) {
++done;
--max;
ipoib_cm_handle_rx_wc(dev, wc);
} else if (wc->wr_id & IPOIB_OP_RECV) {
++done;
--max;
ipoib_ib_handle_rx_wc(dev, wc);
} else
ipoib_ib_handle_tx_wc(dev, wc);
}

if (n != t) {
empty = 1;
break;
}
}

dev->quota -= done;
*budget -= done;

if (empty) {
netif_rx_complete(dev);
if (unlikely(ib_req_notify_cq(priv->cq,
IB_CQ_NEXT_COMP |
IB_CQ_REPORT_MISSED_EVENTS)) &&
netif_rx_reschedule(dev, 0))
return 1;

return 0;
}

return 1;
}

void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
{
struct net_device *dev = (struct net_device *) dev_ptr;
struct ipoib_dev_priv *priv = netdev_priv(dev);
int n, i;

ib_req_notify_cq(cq, IB_CQ_NEXT_COMP);
do {
n = ib_poll_cq(cq, IPOIB_NUM_WC, priv->ibwc);
for (i = 0; i < n; ++i)
ipoib_ib_handle_wc(dev, priv->ibwc + i);
} while (n == IPOIB_NUM_WC);
netif_rx_schedule(dev_ptr);
}

static inline int post_send(struct ipoib_dev_priv *priv,
Expand Down Expand Up @@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev)
struct ib_qp_attr qp_attr;
unsigned long begin;
struct ipoib_tx_buf *tx_req;
int i;
int i, n;

clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
netif_poll_disable(dev);

ipoib_cm_dev_stop(dev);

Expand Down Expand Up @@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev)
goto timeout;
}

do {
n = ib_poll_cq(priv->cq, IPOIB_NUM_WC, priv->ibwc);
for (i = 0; i < n; ++i) {
if (priv->ibwc[i].wr_id & IPOIB_CM_OP_SRQ)
ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
else if (priv->ibwc[i].wr_id & IPOIB_OP_RECV)
ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
else
ipoib_ib_handle_tx_wc(dev, priv->ibwc + i);
}
} while (n == IPOIB_NUM_WC);

msleep(1);
}

Expand Down Expand Up @@ -596,6 +644,9 @@ int ipoib_ib_dev_stop(struct net_device *dev)
msleep(1);
}

netif_poll_enable(dev);
ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);

return 0;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/infiniband/ulp/ipoib/ipoib_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -948,6 +948,8 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header = ipoib_hard_header;
dev->set_multicast_list = ipoib_set_mcast_list;
dev->neigh_setup = ipoib_neigh_setup_dev;
dev->poll = ipoib_poll;
dev->weight = 100;

dev->watchdog_timeo = HZ;

Expand Down

0 comments on commit 8d1cc86

Please sign in to comment.