aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband/ulp
diff options
context:
space:
mode:
authorRoland Dreier <rolandd@cisco.com>2007-07-10 16:43:53 -0400
committerRoland Dreier <rolandd@cisco.com>2007-07-10 16:43:53 -0400
commit1b844afe9e67d6cd441ae6df71051b4004f31dd2 (patch)
tree4242f07678723cded8e36bd3e4e60d926e08647e /drivers/infiniband/ulp
parent8909c571fa1e62e254c4045394e6eaccfadec6f4 (diff)
IPoIB: Recycle loopback skbs instead of freeing and reallocating
InfiniBand HCAs replicate multicast packets back to the QP that sent them if that QP is attached to the destination multicast group. This means that IPoIB multicasts are often replicated back to the receive queue of the interface that generated them. To avoid confusing the network stack, we drop these duplicates within the IPoIB driver. However, there's no reason to free the skb that received the duplicate and then immediately allocate a new skb to post to the receive queue. We can be more efficient and just repost the same skb. Signed-off-by: Roland Dreier <rolandd@cisco.com>
Diffstat (limited to 'drivers/infiniband/ulp')
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c33
1 files changed, 17 insertions, 16 deletions
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 8404f05b2b6e..10944888cffd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -197,6 +197,13 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
197 } 197 }
198 198
199 /* 199 /*
200 * Drop packets that this interface sent, ie multicast packets
201 * that the HCA has replicated.
202 */
203 if (wc->slid == priv->local_lid && wc->src_qp == priv->qp->qp_num)
204 goto repost;
205
206 /*
200 * If we can't allocate a new RX buffer, dump 207 * If we can't allocate a new RX buffer, dump
201 * this packet and reuse the old buffer. 208 * this packet and reuse the old buffer.
202 */ 209 */
@@ -213,24 +220,18 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
213 skb_put(skb, wc->byte_len); 220 skb_put(skb, wc->byte_len);
214 skb_pull(skb, IB_GRH_BYTES); 221 skb_pull(skb, IB_GRH_BYTES);
215 222
216 if (wc->slid != priv->local_lid || 223 skb->protocol = ((struct ipoib_header *) skb->data)->proto;
217 wc->src_qp != priv->qp->qp_num) { 224 skb_reset_mac_header(skb);
218 skb->protocol = ((struct ipoib_header *) skb->data)->proto; 225 skb_pull(skb, IPOIB_ENCAP_LEN);
219 skb_reset_mac_header(skb);
220 skb_pull(skb, IPOIB_ENCAP_LEN);
221 226
222 dev->last_rx = jiffies; 227 dev->last_rx = jiffies;
223 ++priv->stats.rx_packets; 228 ++priv->stats.rx_packets;
224 priv->stats.rx_bytes += skb->len; 229 priv->stats.rx_bytes += skb->len;
225 230
226 skb->dev = dev; 231 skb->dev = dev;
227 /* XXX get correct PACKET_ type here */ 232 /* XXX get correct PACKET_ type here */
228 skb->pkt_type = PACKET_HOST; 233 skb->pkt_type = PACKET_HOST;
229 netif_receive_skb(skb); 234 netif_receive_skb(skb);
230 } else {
231 ipoib_dbg_data(priv, "dropping loopback packet\n");
232 dev_kfree_skb_any(skb);
233 }
234 235
235repost: 236repost:
236 if (unlikely(ipoib_ib_post_receive(dev, wr_id))) 237 if (unlikely(ipoib_ib_post_receive(dev, wr_id)))