[ofa-general] [PATCH] ipoib: defer skb_orphan() until irqs enabled

Eli Cohen eli at dev.mellanox.co.il
Wed Sep 10 06:51:16 PDT 2008


On Tue, Sep 09, 2008 at 02:32:44PM -0700, Roland Dreier wrote:
> By the way, looking at this stuff again, it seems we have (a possibly
> quite unlikely) race where a send can complete before the xmit method
> finishes, and we end up running skb_orphan on an skb that another
> context has already freed.  I'll have to think about how we can fix
> that -- but any good ideas are appreciated...
> 

We can check if there are outstanding WRs after poll_tx is called. If
there are no outstanding WRs, it means that the SKB has been freed. If
there are outstanding WRs, it means that the last post has not been
freed so we can call skb_orphan(). Like the following patch (on top of
Arthur's):


diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 711a3ac..332526a 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -532,7 +532,7 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
 	struct ipoib_tx_buf *tx_req;
 	int hlen;
 	void *phead;
-	int ret = 1; /* assume the worst */
+	int sent;
 
 	if (skb_is_gso(skb)) {
 		hlen = skb_transport_offset(skb) + tcp_hdrlen(skb);
@@ -594,7 +594,7 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
 		--priv->tx_outstanding;
 		ipoib_dma_unmap_tx(priv->ca, tx_req);
 		dev_kfree_skb_any(skb);
-		ret = 1;
+		sent = 0;
 		if (netif_queue_stopped(dev))
 			netif_wake_queue(dev);
 	} else {
@@ -602,14 +602,14 @@ int ipoib_send(struct net_device *dev, struct sk_buff *skb,
 
 		address->last_send = priv->tx_head;
 		++priv->tx_head;
-		ret = 0;
+		sent = 1;
 	}
 
 	if (unlikely(priv->tx_outstanding > MAX_SEND_CQE))
 		while (poll_tx(priv))
 			; /* nothing */
 
-	return ret;
+	return !(sent && priv->tx_outstanding);
 }
 
 static void __ipoib_reap_ah(struct net_device *dev)





More information about the general mailing list