[ofa-general] [PATCH] IB/ipoib: Add checksum offload support
Eli Cohen
eli at dev.mellanox.co.il
Wed Feb 27 07:07:08 PST 2008
IB/ipoib: Add checksum offload support
If the HCA supports checksum offload it will have IB_DEVICE_UD_IP_CSUM set in
its capability flags and this will cause ipoib to set NETIF_F_IP_CSUM. It also
means that the HCA can verify checksum of incoming packets.
Signed-off-by: Eli Cohen <eli at mellanox.co.il>
---
drivers/infiniband/ulp/ipoib/ipoib.h | 2 +
drivers/infiniband/ulp/ipoib/ipoib_cm.c | 7 ++++++
drivers/infiniband/ulp/ipoib/ipoib_ib.c | 12 ++++++++++
drivers/infiniband/ulp/ipoib/ipoib_main.c | 33 +++++++++++++++++++++++++++++
4 files changed, 54 insertions(+), 0 deletions(-)
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index 054fab8..19a41ff 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -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,
@@ -318,6 +319,7 @@ struct ipoib_dev_priv {
struct dentry *mcg_dentry;
struct dentry *path_dentry;
#endif
+ int hca_caps;
};
struct ipoib_ah {
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 52b1beb..3bdb4dd 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1380,6 +1380,9 @@ 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);
+
ipoib_flush_paths(dev);
return count;
}
@@ -1388,6 +1391,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 (priv->hca_caps & IB_DEVICE_UD_IP_CSUM)
+ dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
+
return count;
}
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 08c4396..7450ce0 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -37,6 +37,7 @@
#include <linux/delay.h>
#include <linux/dma-mapping.h>
+#include <linux/ip.h>
#include <rdma/ib_cache.h>
@@ -231,6 +232,11 @@ 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;
+
+ /* check rx csum */
+ if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok))
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
+
netif_receive_skb(skb);
repost:
@@ -442,6 +448,12 @@ void ipoib_send(struct net_device *dev, struct sk_buff *skb,
return;
}
+ if (dev->flags & NETIF_F_IP_CSUM &&
+ 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),
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index f96477a..2c2a922 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -1100,11 +1100,26 @@ int ipoib_add_pkey_attr(struct net_device *dev)
return device_create_file(&dev->dev, &dev_attr_pkey);
}
+static void set_csum(struct net_device *dev)
+{
+ struct ipoib_dev_priv *priv = netdev_priv(dev);
+
+ if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
+ return;
+
+ if (!(priv->hca_caps & IB_DEVICE_UD_IP_CSUM))
+ return;
+
+ dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM;
+ set_bit(IPOIB_FLAG_CSUM, &priv->flags);
+}
+
static struct net_device *ipoib_add_port(const char *format,
struct ib_device *hca, u8 port)
{
struct ipoib_dev_priv *priv;
int result = -ENOMEM;
+ struct ib_device_attr *device_attr;
priv = ipoib_intf_alloc(format);
if (!priv)
@@ -1119,6 +1134,23 @@ 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 %lu 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_pkey port %d failed (ret = %d)\n",
+ hca->name, port, result);
+ kfree(device_attr);
+ goto device_init_failed;
+ }
+ priv->hca_caps = device_attr->device_cap_flags;
+ kfree(device_attr);
+
/*
* Set the full membership bit, so that we join the right
* broadcast group, etc.
@@ -1136,6 +1168,7 @@ 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));
+ set_csum(priv->dev);
result = ipoib_dev_init(priv->dev, hca, port);
if (result < 0) {
--
1.5.4.2
More information about the general
mailing list