Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6046136c authored by Eli Cohen's avatar Eli Cohen Committed by Roland Dreier
Browse files

IPoIB: Use checksum offload support if available



For HCAs that support checksum offload (ie that set IB_DEVICE_UD_IP_CSUM
in the device capabilities flags), have IPoIB set NETIF_F_IP_CSUM and
use the HCA to generate and verify IP checksums.

Signed-off-by: default avatarEli Cohen <eli@mellanox.co.il>
Signed-off-by: default avatarRoland Dreier <rolandd@cisco.com>
parent 33718363
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ enum {
	IPOIB_MCAST_STARTED	  = 8,
	IPOIB_FLAG_ADMIN_CM	  = 9,
	IPOIB_FLAG_UMCAST	  = 10,
	IPOIB_FLAG_CSUM		  = 11,

	IPOIB_MAX_BACKOFF_SECONDS = 16,

+8 −0
Original line number Diff line number Diff line
@@ -1383,6 +1383,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
		set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
		ipoib_warn(priv, "enabling connected mode "
			   "will cause multicast packet drops\n");

		dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG);
		priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;

		ipoib_flush_paths(dev);
		return count;
	}
@@ -1391,6 +1395,10 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
		clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
		dev->mtu = min(priv->mcast_mtu, dev->mtu);
		ipoib_flush_paths(dev);

		if (test_bit(IPOIB_FLAG_CSUM, &priv->flags))
			dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;

		return count;
	}

+9 −0
Original line number Diff line number Diff line
@@ -231,6 +231,10 @@ 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;

	if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
		skb->ip_summed = CHECKSUM_UNNECESSARY;

	netif_receive_skb(skb);

repost:
@@ -442,6 +446,11 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
		return;
	}

	if (skb->ip_summed == CHECKSUM_PARTIAL)
		priv->tx_wr.send_flags |= IB_SEND_IP_CSUM;
	else
		priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;

	if (unlikely(post_send(priv, priv->tx_head & (ipoib_sendq_size - 1),
			       address->ah, qpn,
			       tx_req->mapping, skb_headlen(skb),
+23 −1
Original line number Diff line number Diff line
@@ -1105,6 +1105,7 @@ static struct net_device *ipoib_add_port(const char *format,
					 struct ib_device *hca, u8 port)
{
	struct ipoib_dev_priv *priv;
	struct ib_device_attr *device_attr;
	int result = -ENOMEM;

	priv = ipoib_intf_alloc(format);
@@ -1120,6 +1121,28 @@ static struct net_device *ipoib_add_port(const char *format,
		goto device_init_failed;
	}

	device_attr = kmalloc(sizeof *device_attr, GFP_KERNEL);
	if (!device_attr) {
		printk(KERN_WARNING "%s: allocation of %zu bytes failed\n",
		       hca->name, sizeof *device_attr);
		goto device_init_failed;
	}

	result = ib_query_device(hca, device_attr);
	if (result) {
		printk(KERN_WARNING "%s: ib_query_device failed (ret = %d)\n",
		       hca->name, result);
		kfree(device_attr);
		goto device_init_failed;
	}

	if (device_attr->device_cap_flags & IB_DEVICE_UD_IP_CSUM) {
		set_bit(IPOIB_FLAG_CSUM, &priv->flags);
		priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
	}

	kfree(device_attr);

	/*
	 * Set the full membership bit, so that we join the right
	 * broadcast group, etc.
@@ -1137,7 +1160,6 @@ static struct net_device *ipoib_add_port(const char *format,
	} else
		memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid));


	result = ipoib_dev_init(priv->dev, hca, port);
	if (result < 0) {
		printk(KERN_WARNING "%s: failed to initialize port %d (ret = %d)\n",