|
@@ -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);
|
|
@@ -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,
|
|
@@ -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);
|
|
|
|
|
@@ -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);
|
|
|
}
|
|
|
|
|
@@ -596,6 +644,9 @@ timeout:
|
|
|
msleep(1);
|
|
|
}
|
|
|
|
|
|
+ netif_poll_enable(dev);
|
|
|
+ ib_req_notify_cq(priv->cq, IB_CQ_NEXT_COMP);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|