|
@@ -264,7 +264,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
|
|
likely(wc->wc_flags & IB_WC_IP_CSUM_OK))
|
|
likely(wc->wc_flags & IB_WC_IP_CSUM_OK))
|
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
skb->ip_summed = CHECKSUM_UNNECESSARY;
|
|
|
|
|
|
- napi_gro_receive(&priv->napi, skb);
|
|
|
|
|
|
+ napi_gro_receive(&priv->recv_napi, skb);
|
|
|
|
|
|
repost:
|
|
repost:
|
|
if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
|
|
if (unlikely(ipoib_ib_post_receive(dev, wr_id)))
|
|
@@ -406,9 +406,10 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
|
|
dev_kfree_skb_any(tx_req->skb);
|
|
dev_kfree_skb_any(tx_req->skb);
|
|
|
|
|
|
++priv->tx_tail;
|
|
++priv->tx_tail;
|
|
- if (unlikely((priv->tx_head - priv->tx_tail) == ipoib_sendq_size >> 1) &&
|
|
|
|
- netif_queue_stopped(dev) &&
|
|
|
|
- test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
|
|
|
|
|
|
+
|
|
|
|
+ if (unlikely(netif_queue_stopped(dev) &&
|
|
|
|
+ ((priv->tx_head - priv->tx_tail) <= ipoib_sendq_size >> 1) &&
|
|
|
|
+ test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags)))
|
|
netif_wake_queue(dev);
|
|
netif_wake_queue(dev);
|
|
|
|
|
|
if (wc->status != IB_WC_SUCCESS &&
|
|
if (wc->status != IB_WC_SUCCESS &&
|
|
@@ -430,17 +431,23 @@ static void ipoib_ib_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
|
|
static int poll_tx(struct ipoib_dev_priv *priv)
|
|
static int poll_tx(struct ipoib_dev_priv *priv)
|
|
{
|
|
{
|
|
int n, i;
|
|
int n, i;
|
|
|
|
+ struct ib_wc *wc;
|
|
|
|
|
|
n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
|
|
n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
|
|
- for (i = 0; i < n; ++i)
|
|
|
|
- ipoib_ib_handle_tx_wc(priv->dev, priv->send_wc + i);
|
|
|
|
-
|
|
|
|
|
|
+ for (i = 0; i < n; ++i) {
|
|
|
|
+ wc = priv->send_wc + i;
|
|
|
|
+ if (wc->wr_id & IPOIB_OP_CM)
|
|
|
|
+ ipoib_cm_handle_tx_wc(priv->dev, priv->send_wc + i);
|
|
|
|
+ else
|
|
|
|
+ ipoib_ib_handle_tx_wc(priv->dev, priv->send_wc + i);
|
|
|
|
+ }
|
|
return n == MAX_SEND_CQE;
|
|
return n == MAX_SEND_CQE;
|
|
}
|
|
}
|
|
|
|
|
|
-int ipoib_poll(struct napi_struct *napi, int budget)
|
|
|
|
|
|
+int ipoib_rx_poll(struct napi_struct *napi, int budget)
|
|
{
|
|
{
|
|
- struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv, napi);
|
|
|
|
|
|
+ struct ipoib_dev_priv *priv =
|
|
|
|
+ container_of(napi, struct ipoib_dev_priv, recv_napi);
|
|
struct net_device *dev = priv->dev;
|
|
struct net_device *dev = priv->dev;
|
|
int done;
|
|
int done;
|
|
int t;
|
|
int t;
|
|
@@ -464,8 +471,9 @@ poll_more:
|
|
ipoib_cm_handle_rx_wc(dev, wc);
|
|
ipoib_cm_handle_rx_wc(dev, wc);
|
|
else
|
|
else
|
|
ipoib_ib_handle_rx_wc(dev, wc);
|
|
ipoib_ib_handle_rx_wc(dev, wc);
|
|
- } else
|
|
|
|
- ipoib_cm_handle_tx_wc(priv->dev, wc);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ pr_warn("%s: Got unexpected wqe id\n", __func__);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
|
|
|
|
if (n != t)
|
|
if (n != t)
|
|
@@ -484,33 +492,47 @@ poll_more:
|
|
return done;
|
|
return done;
|
|
}
|
|
}
|
|
|
|
|
|
-void ipoib_ib_completion(struct ib_cq *cq, void *dev_ptr)
|
|
|
|
|
|
+int ipoib_tx_poll(struct napi_struct *napi, int budget)
|
|
{
|
|
{
|
|
- struct net_device *dev = dev_ptr;
|
|
|
|
- struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
|
|
|
|
+ struct ipoib_dev_priv *priv = container_of(napi, struct ipoib_dev_priv,
|
|
|
|
+ send_napi);
|
|
|
|
+ struct net_device *dev = priv->dev;
|
|
|
|
+ int n, i;
|
|
|
|
+ struct ib_wc *wc;
|
|
|
|
|
|
- napi_schedule(&priv->napi);
|
|
|
|
-}
|
|
|
|
|
|
+poll_more:
|
|
|
|
+ n = ib_poll_cq(priv->send_cq, MAX_SEND_CQE, priv->send_wc);
|
|
|
|
|
|
-static void drain_tx_cq(struct net_device *dev)
|
|
|
|
-{
|
|
|
|
- struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
|
|
|
|
+ for (i = 0; i < n; i++) {
|
|
|
|
+ wc = priv->send_wc + i;
|
|
|
|
+ if (wc->wr_id & IPOIB_OP_CM)
|
|
|
|
+ ipoib_cm_handle_tx_wc(dev, wc);
|
|
|
|
+ else
|
|
|
|
+ ipoib_ib_handle_tx_wc(dev, wc);
|
|
|
|
+ }
|
|
|
|
|
|
- netif_tx_lock(dev);
|
|
|
|
- while (poll_tx(priv))
|
|
|
|
- ; /* nothing */
|
|
|
|
|
|
+ if (n < budget) {
|
|
|
|
+ napi_complete(napi);
|
|
|
|
+ if (unlikely(ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP |
|
|
|
|
+ IB_CQ_REPORT_MISSED_EVENTS)) &&
|
|
|
|
+ napi_reschedule(napi))
|
|
|
|
+ goto poll_more;
|
|
|
|
+ }
|
|
|
|
+ return n < 0 ? 0 : n;
|
|
|
|
+}
|
|
|
|
|
|
- if (netif_queue_stopped(dev))
|
|
|
|
- mod_timer(&priv->poll_timer, jiffies + 1);
|
|
|
|
|
|
+void ipoib_ib_rx_completion(struct ib_cq *cq, void *ctx_ptr)
|
|
|
|
+{
|
|
|
|
+ struct ipoib_dev_priv *priv = ctx_ptr;
|
|
|
|
|
|
- netif_tx_unlock(dev);
|
|
|
|
|
|
+ napi_schedule(&priv->recv_napi);
|
|
}
|
|
}
|
|
|
|
|
|
-void ipoib_send_comp_handler(struct ib_cq *cq, void *dev_ptr)
|
|
|
|
|
|
+void ipoib_ib_tx_completion(struct ib_cq *cq, void *ctx_ptr)
|
|
{
|
|
{
|
|
- struct ipoib_dev_priv *priv = ipoib_priv(dev_ptr);
|
|
|
|
|
|
+ struct ipoib_dev_priv *priv = ctx_ptr;
|
|
|
|
|
|
- mod_timer(&priv->poll_timer, jiffies);
|
|
|
|
|
|
+ napi_schedule(&priv->send_napi);
|
|
}
|
|
}
|
|
|
|
|
|
static inline int post_send(struct ipoib_dev_priv *priv,
|
|
static inline int post_send(struct ipoib_dev_priv *priv,
|
|
@@ -614,14 +636,17 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
|
|
/* increase the tx_head after send success, but use it for queue state */
|
|
/* increase the tx_head after send success, but use it for queue state */
|
|
if (priv->tx_head - priv->tx_tail == ipoib_sendq_size - 1) {
|
|
if (priv->tx_head - priv->tx_tail == ipoib_sendq_size - 1) {
|
|
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
|
|
ipoib_dbg(priv, "TX ring full, stopping kernel net queue\n");
|
|
- if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP))
|
|
|
|
- ipoib_warn(priv, "request notify on send CQ failed\n");
|
|
|
|
netif_stop_queue(dev);
|
|
netif_stop_queue(dev);
|
|
}
|
|
}
|
|
|
|
|
|
skb_orphan(skb);
|
|
skb_orphan(skb);
|
|
skb_dst_drop(skb);
|
|
skb_dst_drop(skb);
|
|
|
|
|
|
|
|
+ if (netif_queue_stopped(dev))
|
|
|
|
+ if (ib_req_notify_cq(priv->send_cq, IB_CQ_NEXT_COMP |
|
|
|
|
+ IB_CQ_REPORT_MISSED_EVENTS))
|
|
|
|
+ ipoib_warn(priv, "request notify on send CQ failed\n");
|
|
|
|
+
|
|
rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
|
|
rc = post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
|
|
address, dqpn, tx_req, phead, hlen);
|
|
address, dqpn, tx_req, phead, hlen);
|
|
if (unlikely(rc)) {
|
|
if (unlikely(rc)) {
|
|
@@ -638,11 +663,6 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
|
|
rc = priv->tx_head;
|
|
rc = priv->tx_head;
|
|
++priv->tx_head;
|
|
++priv->tx_head;
|
|
}
|
|
}
|
|
-
|
|
|
|
- if (unlikely(priv->tx_head - priv->tx_tail > MAX_SEND_CQE))
|
|
|
|
- while (poll_tx(priv))
|
|
|
|
- ; /* nothing */
|
|
|
|
-
|
|
|
|
return rc;
|
|
return rc;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -731,6 +751,22 @@ static void check_qp_movement_and_print(struct ipoib_dev_priv *priv,
|
|
new_state, qp_attr.qp_state);
|
|
new_state, qp_attr.qp_state);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+static void ipoib_napi_enable(struct net_device *dev)
|
|
|
|
+{
|
|
|
|
+ struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
|
|
+
|
|
|
|
+ napi_enable(&priv->recv_napi);
|
|
|
|
+ napi_enable(&priv->send_napi);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void ipoib_napi_disable(struct net_device *dev)
|
|
|
|
+{
|
|
|
|
+ struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
|
|
+
|
|
|
|
+ napi_disable(&priv->recv_napi);
|
|
|
|
+ napi_disable(&priv->send_napi);
|
|
|
|
+}
|
|
|
|
+
|
|
int ipoib_ib_dev_stop_default(struct net_device *dev)
|
|
int ipoib_ib_dev_stop_default(struct net_device *dev)
|
|
{
|
|
{
|
|
struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
@@ -740,7 +776,7 @@ int ipoib_ib_dev_stop_default(struct net_device *dev)
|
|
int i;
|
|
int i;
|
|
|
|
|
|
if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
|
|
if (test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
|
|
- napi_disable(&priv->napi);
|
|
|
|
|
|
+ ipoib_napi_disable(dev);
|
|
|
|
|
|
ipoib_cm_dev_stop(dev);
|
|
ipoib_cm_dev_stop(dev);
|
|
|
|
|
|
@@ -797,7 +833,6 @@ int ipoib_ib_dev_stop_default(struct net_device *dev)
|
|
ipoib_dbg(priv, "All sends and receives done.\n");
|
|
ipoib_dbg(priv, "All sends and receives done.\n");
|
|
|
|
|
|
timeout:
|
|
timeout:
|
|
- del_timer_sync(&priv->poll_timer);
|
|
|
|
qp_attr.qp_state = IB_QPS_RESET;
|
|
qp_attr.qp_state = IB_QPS_RESET;
|
|
if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
|
|
if (ib_modify_qp(priv->qp, &qp_attr, IB_QP_STATE))
|
|
ipoib_warn(priv, "Failed to modify QP to RESET state\n");
|
|
ipoib_warn(priv, "Failed to modify QP to RESET state\n");
|
|
@@ -819,13 +854,6 @@ int ipoib_ib_dev_stop(struct net_device *dev)
|
|
return 0;
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
-void ipoib_ib_tx_timer_func(struct timer_list *t)
|
|
|
|
-{
|
|
|
|
- struct ipoib_dev_priv *priv = from_timer(priv, t, poll_timer);
|
|
|
|
-
|
|
|
|
- drain_tx_cq(priv->dev);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
int ipoib_ib_dev_open_default(struct net_device *dev)
|
|
int ipoib_ib_dev_open_default(struct net_device *dev)
|
|
{
|
|
{
|
|
struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
struct ipoib_dev_priv *priv = ipoib_priv(dev);
|
|
@@ -850,7 +878,7 @@ int ipoib_ib_dev_open_default(struct net_device *dev)
|
|
}
|
|
}
|
|
|
|
|
|
if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
|
|
if (!test_bit(IPOIB_FLAG_INITIALIZED, &priv->flags))
|
|
- napi_enable(&priv->napi);
|
|
|
|
|
|
+ ipoib_napi_enable(dev);
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
out:
|
|
out:
|
|
@@ -965,8 +993,9 @@ void ipoib_drain_cq(struct net_device *dev)
|
|
ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
|
|
ipoib_cm_handle_rx_wc(dev, priv->ibwc + i);
|
|
else
|
|
else
|
|
ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
|
|
ipoib_ib_handle_rx_wc(dev, priv->ibwc + i);
|
|
- } else
|
|
|
|
- ipoib_cm_handle_tx_wc(dev, priv->ibwc + i);
|
|
|
|
|
|
+ } else {
|
|
|
|
+ pr_warn("%s: Got unexpected wqe id\n", __func__);
|
|
|
|
+ }
|
|
}
|
|
}
|
|
} while (n == IPOIB_NUM_WC);
|
|
} while (n == IPOIB_NUM_WC);
|
|
|
|
|