Commit 8d1cc86a authored by Roland Dreier's avatar Roland Dreier

IPoIB: Convert to NAPI

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: default avatarRoland Dreier <rolandd@cisco.com>
parent ed23a727
...@@ -311,6 +311,7 @@ extern struct workqueue_struct *ipoib_workqueue; ...@@ -311,6 +311,7 @@ extern struct workqueue_struct *ipoib_workqueue;
/* functions */ /* functions */
int ipoib_poll(struct net_device *dev, int *budget);
void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr); void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr);
struct ipoib_ah *ipoib_create_ah(struct net_device *dev, struct ipoib_ah *ipoib_create_ah(struct net_device *dev,
......
...@@ -416,7 +416,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -416,7 +416,7 @@ void ipoib_cm_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb->dev = dev; skb->dev = dev;
/* XXX get correct PACKET_ type here */ /* XXX get correct PACKET_ type here */
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
netif_rx_ni(skb); netif_receive_skb(skb);
repost: repost:
if (unlikely(ipoib_cm_post_receive(dev, wr_id))) if (unlikely(ipoib_cm_post_receive(dev, wr_id)))
......
...@@ -226,7 +226,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -226,7 +226,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
skb->dev = dev; skb->dev = dev;
/* XXX get correct PACKET_ type here */ /* XXX get correct PACKET_ type here */
skb->pkt_type = PACKET_HOST; skb->pkt_type = PACKET_HOST;
netif_rx_ni(skb); netif_receive_skb(skb);
} else { } else {
ipoib_dbg_data(priv, "dropping loopback packet\n"); ipoib_dbg_data(priv, "dropping loopback packet\n");
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
...@@ -280,28 +280,63 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc) ...@@ -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); 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) struct ipoib_dev_priv *priv = netdev_priv(dev);
ipoib_cm_handle_rx_wc(dev, wc); int max = min(*budget, dev->quota);
else if (wc->wr_id & IPOIB_OP_RECV) int done;
ipoib_ib_handle_rx_wc(dev, wc); int t;
else int empty;
ipoib_ib_handle_tx_wc(dev, wc); 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) void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
{ {
struct net_device *dev = (struct net_device *) dev_ptr; netif_rx_schedule(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);
} }
static inline int post_send(struct ipoib_dev_priv *priv, static inline int post_send(struct ipoib_dev_priv *priv,
...@@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev) ...@@ -514,9 +549,10 @@ int ipoib_ib_dev_stop(struct net_device *dev)
struct ib_qp_attr qp_attr; struct ib_qp_attr qp_attr;
unsigned long begin; unsigned long begin;
struct ipoib_tx_buf *tx_req; struct ipoib_tx_buf *tx_req;
int i; int i, n;
clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags); clear_bit(IPOIB_FLAG_INITIALIZED, &priv->flags);
netif_poll_disable(dev);
ipoib_cm_dev_stop(dev); ipoib_cm_dev_stop(dev);
...@@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev) ...@@ -568,6 +604,18 @@ int ipoib_ib_dev_stop(struct net_device *dev)
goto timeout; 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); msleep(1);
} }
...@@ -596,6 +644,9 @@ int ipoib_ib_dev_stop(struct net_device *dev) ...@@ -596,6 +644,9 @@ int ipoib_ib_dev_stop(struct net_device *dev)
msleep(1); msleep(1);
} }
netif_poll_enable(dev);
ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
return 0; return 0;
} }
......
...@@ -948,6 +948,8 @@ static void ipoib_setup(struct net_device *dev) ...@@ -948,6 +948,8 @@ static void ipoib_setup(struct net_device *dev)
dev->hard_header = ipoib_hard_header; dev->hard_header = ipoib_hard_header;
dev->set_multicast_list = ipoib_set_mcast_list; dev->set_multicast_list = ipoib_set_mcast_list;
dev->neigh_setup = ipoib_neigh_setup_dev; dev->neigh_setup = ipoib_neigh_setup_dev;
dev->poll = ipoib_poll;
dev->weight = 100;
dev->watchdog_timeo = HZ; dev->watchdog_timeo = HZ;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment