|
@@ -786,7 +786,8 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
|
|
|
|
|
|
dev_kfree_skb_any(tx_req->skb);
|
|
|
|
|
|
- spin_lock_irqsave(&priv->tx_lock, flags);
|
|
|
+ netif_tx_lock(dev);
|
|
|
+
|
|
|
++tx->tx_tail;
|
|
|
if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
|
|
|
netif_queue_stopped(dev) &&
|
|
@@ -801,7 +802,7 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
|
|
|
"(status=%d, wrid=%d vend_err %x)\n",
|
|
|
wc->status, wr_id, wc->vendor_err);
|
|
|
|
|
|
- spin_lock(&priv->lock);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
neigh = tx->neigh;
|
|
|
|
|
|
if (neigh) {
|
|
@@ -821,10 +822,10 @@ void ipoib_cm_handle_tx_wc(struct net_device *dev, struct ib_wc *wc)
|
|
|
|
|
|
clear_bit(IPOIB_FLAG_OPER_UP, &tx->flags);
|
|
|
|
|
|
- spin_unlock(&priv->lock);
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
}
|
|
|
|
|
|
- spin_unlock_irqrestore(&priv->tx_lock, flags);
|
|
|
+ netif_tx_unlock(dev);
|
|
|
}
|
|
|
|
|
|
int ipoib_cm_dev_open(struct net_device *dev)
|
|
@@ -1149,7 +1150,6 @@ static void ipoib_cm_tx_destroy(struct ipoib_cm_tx *p)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(p->dev);
|
|
|
struct ipoib_cm_tx_buf *tx_req;
|
|
|
- unsigned long flags;
|
|
|
unsigned long begin;
|
|
|
|
|
|
ipoib_dbg(priv, "Destroy active connection 0x%x head 0x%x tail 0x%x\n",
|
|
@@ -1180,12 +1180,12 @@ timeout:
|
|
|
DMA_TO_DEVICE);
|
|
|
dev_kfree_skb_any(tx_req->skb);
|
|
|
++p->tx_tail;
|
|
|
- spin_lock_irqsave(&priv->tx_lock, flags);
|
|
|
+ netif_tx_lock_bh(p->dev);
|
|
|
if (unlikely(--priv->tx_outstanding == ipoib_sendq_size >> 1) &&
|
|
|
netif_queue_stopped(p->dev) &&
|
|
|
test_bit(IPOIB_FLAG_ADMIN_UP, &priv->flags))
|
|
|
netif_wake_queue(p->dev);
|
|
|
- spin_unlock_irqrestore(&priv->tx_lock, flags);
|
|
|
+ netif_tx_unlock_bh(p->dev);
|
|
|
}
|
|
|
|
|
|
if (p->qp)
|
|
@@ -1202,6 +1202,7 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
|
|
|
struct ipoib_dev_priv *priv = netdev_priv(tx->dev);
|
|
|
struct net_device *dev = priv->dev;
|
|
|
struct ipoib_neigh *neigh;
|
|
|
+ unsigned long flags;
|
|
|
int ret;
|
|
|
|
|
|
switch (event->event) {
|
|
@@ -1220,8 +1221,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
|
|
|
case IB_CM_REJ_RECEIVED:
|
|
|
case IB_CM_TIMEWAIT_EXIT:
|
|
|
ipoib_dbg(priv, "CM error %d.\n", event->event);
|
|
|
- spin_lock_irq(&priv->tx_lock);
|
|
|
- spin_lock(&priv->lock);
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
neigh = tx->neigh;
|
|
|
|
|
|
if (neigh) {
|
|
@@ -1239,8 +1240,8 @@ static int ipoib_cm_tx_handler(struct ib_cm_id *cm_id,
|
|
|
queue_work(ipoib_workqueue, &priv->cm.reap_task);
|
|
|
}
|
|
|
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irq(&priv->tx_lock);
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
break;
|
|
|
default:
|
|
|
break;
|
|
@@ -1294,19 +1295,24 @@ static void ipoib_cm_tx_start(struct work_struct *work)
|
|
|
struct ib_sa_path_rec pathrec;
|
|
|
u32 qpn;
|
|
|
|
|
|
- spin_lock_irqsave(&priv->tx_lock, flags);
|
|
|
- spin_lock(&priv->lock);
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
+
|
|
|
while (!list_empty(&priv->cm.start_list)) {
|
|
|
p = list_entry(priv->cm.start_list.next, typeof(*p), list);
|
|
|
list_del_init(&p->list);
|
|
|
neigh = p->neigh;
|
|
|
qpn = IPOIB_QPN(neigh->neighbour->ha);
|
|
|
memcpy(&pathrec, &p->path->pathrec, sizeof pathrec);
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irqrestore(&priv->tx_lock, flags);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
+
|
|
|
ret = ipoib_cm_tx_init(p, qpn, &pathrec);
|
|
|
- spin_lock_irqsave(&priv->tx_lock, flags);
|
|
|
- spin_lock(&priv->lock);
|
|
|
+
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
+
|
|
|
if (ret) {
|
|
|
neigh = p->neigh;
|
|
|
if (neigh) {
|
|
@@ -1320,44 +1326,52 @@ static void ipoib_cm_tx_start(struct work_struct *work)
|
|
|
kfree(p);
|
|
|
}
|
|
|
}
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irqrestore(&priv->tx_lock, flags);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
}
|
|
|
|
|
|
static void ipoib_cm_tx_reap(struct work_struct *work)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
|
|
|
cm.reap_task);
|
|
|
+ struct net_device *dev = priv->dev;
|
|
|
struct ipoib_cm_tx *p;
|
|
|
+ unsigned long flags;
|
|
|
+
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
|
|
|
- spin_lock_irq(&priv->tx_lock);
|
|
|
- spin_lock(&priv->lock);
|
|
|
while (!list_empty(&priv->cm.reap_list)) {
|
|
|
p = list_entry(priv->cm.reap_list.next, typeof(*p), list);
|
|
|
list_del(&p->list);
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irq(&priv->tx_lock);
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
ipoib_cm_tx_destroy(p);
|
|
|
- spin_lock_irq(&priv->tx_lock);
|
|
|
- spin_lock(&priv->lock);
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
}
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irq(&priv->tx_lock);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
}
|
|
|
|
|
|
static void ipoib_cm_skb_reap(struct work_struct *work)
|
|
|
{
|
|
|
struct ipoib_dev_priv *priv = container_of(work, struct ipoib_dev_priv,
|
|
|
cm.skb_task);
|
|
|
+ struct net_device *dev = priv->dev;
|
|
|
struct sk_buff *skb;
|
|
|
-
|
|
|
+ unsigned long flags;
|
|
|
unsigned mtu = priv->mcast_mtu;
|
|
|
|
|
|
- spin_lock_irq(&priv->tx_lock);
|
|
|
- spin_lock(&priv->lock);
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
+
|
|
|
while ((skb = skb_dequeue(&priv->cm.skb_queue))) {
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irq(&priv->tx_lock);
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
+
|
|
|
if (skb->protocol == htons(ETH_P_IP))
|
|
|
icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu));
|
|
|
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
|
@@ -1365,11 +1379,13 @@ static void ipoib_cm_skb_reap(struct work_struct *work)
|
|
|
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, priv->dev);
|
|
|
#endif
|
|
|
dev_kfree_skb_any(skb);
|
|
|
- spin_lock_irq(&priv->tx_lock);
|
|
|
- spin_lock(&priv->lock);
|
|
|
+
|
|
|
+ netif_tx_lock_bh(dev);
|
|
|
+ spin_lock_irqsave(&priv->lock, flags);
|
|
|
}
|
|
|
- spin_unlock(&priv->lock);
|
|
|
- spin_unlock_irq(&priv->tx_lock);
|
|
|
+
|
|
|
+ spin_unlock_irqrestore(&priv->lock, flags);
|
|
|
+ netif_tx_unlock_bh(dev);
|
|
|
}
|
|
|
|
|
|
void ipoib_cm_skb_too_long(struct net_device *dev, struct sk_buff *skb,
|