aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/infiniband
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-05-20 16:43:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-05-20 16:43:21 -0400
commit06f4e926d256d902dd9a53dcb400fd74974ce087 (patch)
tree0b438b67f5f0eff6fd617bc497a9dace6164a488 /drivers/infiniband
parent8e7bfcbab3825d1b404d615cb1b54f44ff81f981 (diff)
parentd93515611bbc70c2fe4db232e5feb448ed8e4cc9 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1446 commits) macvlan: fix panic if lowerdev in a bond tg3: Add braces around 5906 workaround. tg3: Fix NETIF_F_LOOPBACK error macvlan: remove one synchronize_rcu() call networking: NET_CLS_ROUTE4 depends on INET irda: Fix error propagation in ircomm_lmp_connect_response() irda: Kill set but unused variable 'bytes' in irlan_check_command_param() irda: Kill set but unused variable 'clen' in ircomm_connect_indication() rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport() be2net: Kill set but unused variable 'req' in lancer_fw_download() irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication() atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined. rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer(). rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler() rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection() rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window() pkt_sched: Kill set but unused variable 'protocol' in tc_classify() isdn: capi: Use pr_debug() instead of ifdefs. tg3: Update version to 3.119 tg3: Apply rx_discards fix to 5719/5720 ... Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c as per Davem.
Diffstat (limited to 'drivers/infiniband')
-rw-r--r--drivers/infiniband/core/addr.c9
-rw-r--r--drivers/infiniband/hw/cxgb3/iwch_cm.c3
-rw-r--r--drivers/infiniband/hw/cxgb4/cm.c3
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.c5
-rw-r--r--drivers/infiniband/hw/nes/nes_hw.h1
-rw-r--r--drivers/infiniband/hw/nes/nes_nic.c59
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib.h1
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_cm.c11
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ethtool.c28
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_ib.c2
-rw-r--r--drivers/infiniband/ulp/ipoib/ipoib_main.c24
11 files changed, 40 insertions, 106 deletions
diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c
index 4ffc224faa7f..8e21d457b899 100644
--- a/drivers/infiniband/core/addr.c
+++ b/drivers/infiniband/core/addr.c
@@ -185,15 +185,20 @@ static int addr4_resolve(struct sockaddr_in *src_in,
185 __be32 dst_ip = dst_in->sin_addr.s_addr; 185 __be32 dst_ip = dst_in->sin_addr.s_addr;
186 struct rtable *rt; 186 struct rtable *rt;
187 struct neighbour *neigh; 187 struct neighbour *neigh;
188 struct flowi4 fl4;
188 int ret; 189 int ret;
189 190
190 rt = ip_route_output(&init_net, dst_ip, src_ip, 0, addr->bound_dev_if); 191 memset(&fl4, 0, sizeof(fl4));
192 fl4.daddr = dst_ip;
193 fl4.saddr = src_ip;
194 fl4.flowi4_oif = addr->bound_dev_if;
195 rt = ip_route_output_key(&init_net, &fl4);
191 if (IS_ERR(rt)) { 196 if (IS_ERR(rt)) {
192 ret = PTR_ERR(rt); 197 ret = PTR_ERR(rt);
193 goto out; 198 goto out;
194 } 199 }
195 src_in->sin_family = AF_INET; 200 src_in->sin_family = AF_INET;
196 src_in->sin_addr.s_addr = rt->rt_src; 201 src_in->sin_addr.s_addr = fl4.saddr;
197 202
198 if (rt->dst.dev->flags & IFF_LOOPBACK) { 203 if (rt->dst.dev->flags & IFF_LOOPBACK) {
199 ret = rdma_translate_ip((struct sockaddr *) dst_in, addr); 204 ret = rdma_translate_ip((struct sockaddr *) dst_in, addr);
diff --git a/drivers/infiniband/hw/cxgb3/iwch_cm.c b/drivers/infiniband/hw/cxgb3/iwch_cm.c
index 3216bcad7e82..239184138994 100644
--- a/drivers/infiniband/hw/cxgb3/iwch_cm.c
+++ b/drivers/infiniband/hw/cxgb3/iwch_cm.c
@@ -338,8 +338,9 @@ static struct rtable *find_route(struct t3cdev *dev, __be32 local_ip,
338 __be16 peer_port, u8 tos) 338 __be16 peer_port, u8 tos)
339{ 339{
340 struct rtable *rt; 340 struct rtable *rt;
341 struct flowi4 fl4;
341 342
342 rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip, 343 rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
343 peer_port, local_port, IPPROTO_TCP, 344 peer_port, local_port, IPPROTO_TCP,
344 tos, 0); 345 tos, 0);
345 if (IS_ERR(rt)) 346 if (IS_ERR(rt))
diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c
index d7ee70fc9173..f660cd04ec2f 100644
--- a/drivers/infiniband/hw/cxgb4/cm.c
+++ b/drivers/infiniband/hw/cxgb4/cm.c
@@ -315,8 +315,9 @@ static struct rtable *find_route(struct c4iw_dev *dev, __be32 local_ip,
315 __be16 peer_port, u8 tos) 315 __be16 peer_port, u8 tos)
316{ 316{
317 struct rtable *rt; 317 struct rtable *rt;
318 struct flowi4 fl4;
318 319
319 rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip, 320 rt = ip_route_output_ports(&init_net, &fl4, NULL, peer_ip, local_ip,
320 peer_port, local_port, IPPROTO_TCP, 321 peer_port, local_port, IPPROTO_TCP,
321 tos, 0); 322 tos, 0);
322 if (IS_ERR(rt)) 323 if (IS_ERR(rt))
diff --git a/drivers/infiniband/hw/nes/nes_hw.c b/drivers/infiniband/hw/nes/nes_hw.c
index 10d0a5ec9add..96fa9a4cafdf 100644
--- a/drivers/infiniband/hw/nes/nes_hw.c
+++ b/drivers/infiniband/hw/nes/nes_hw.c
@@ -2885,9 +2885,8 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2885 if ((cqe_errv & 2885 if ((cqe_errv &
2886 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR | 2886 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_TCPUDP_CSUM_ERR |
2887 NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) { 2887 NES_NIC_ERRV_BITS_IPH_ERR | NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2888 if (nesvnic->rx_checksum_disabled == 0) { 2888 if (nesvnic->netdev->features & NETIF_F_RXCSUM)
2889 rx_skb->ip_summed = CHECKSUM_UNNECESSARY; 2889 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2890 }
2891 } else 2890 } else
2892 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet." 2891 nes_debug(NES_DBG_CQ, "%s: unsuccessfully checksummed TCP or UDP packet."
2893 " errv = 0x%X, pkt_type = 0x%X.\n", 2892 " errv = 0x%X, pkt_type = 0x%X.\n",
@@ -2897,7 +2896,7 @@ void nes_nic_ce_handler(struct nes_device *nesdev, struct nes_hw_nic_cq *cq)
2897 if ((cqe_errv & 2896 if ((cqe_errv &
2898 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR | 2897 (NES_NIC_ERRV_BITS_IPV4_CSUM_ERR | NES_NIC_ERRV_BITS_IPH_ERR |
2899 NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) { 2898 NES_NIC_ERRV_BITS_WQE_OVERRUN)) == 0) {
2900 if (nesvnic->rx_checksum_disabled == 0) { 2899 if (nesvnic->netdev->features & NETIF_F_RXCSUM) {
2901 rx_skb->ip_summed = CHECKSUM_UNNECESSARY; 2900 rx_skb->ip_summed = CHECKSUM_UNNECESSARY;
2902 /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n", 2901 /* nes_debug(NES_DBG_CQ, "%s: Reporting successfully checksummed IPv4 packet.\n",
2903 nesvnic->netdev->name); */ 2902 nesvnic->netdev->name); */
diff --git a/drivers/infiniband/hw/nes/nes_hw.h b/drivers/infiniband/hw/nes/nes_hw.h
index d2abe07133a5..91594116f947 100644
--- a/drivers/infiniband/hw/nes/nes_hw.h
+++ b/drivers/infiniband/hw/nes/nes_hw.h
@@ -1245,7 +1245,6 @@ struct nes_vnic {
1245 u8 next_qp_nic_index; 1245 u8 next_qp_nic_index;
1246 u8 of_device_registered; 1246 u8 of_device_registered;
1247 u8 rdma_enabled; 1247 u8 rdma_enabled;
1248 u8 rx_checksum_disabled;
1249 u32 lro_max_aggr; 1248 u32 lro_max_aggr;
1250 struct net_lro_mgr lro_mgr; 1249 struct net_lro_mgr lro_mgr;
1251 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS]; 1250 struct net_lro_desc lro_desc[NES_MAX_LRO_DESCRIPTORS];
diff --git a/drivers/infiniband/hw/nes/nes_nic.c b/drivers/infiniband/hw/nes/nes_nic.c
index e96b8fb5d44c..d3a1c41cfd27 100644
--- a/drivers/infiniband/hw/nes/nes_nic.c
+++ b/drivers/infiniband/hw/nes/nes_nic.c
@@ -1093,34 +1093,6 @@ static const char nes_ethtool_stringset[][ETH_GSTRING_LEN] = {
1093}; 1093};
1094#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset) 1094#define NES_ETHTOOL_STAT_COUNT ARRAY_SIZE(nes_ethtool_stringset)
1095 1095
1096/**
1097 * nes_netdev_get_rx_csum
1098 */
1099static u32 nes_netdev_get_rx_csum (struct net_device *netdev)
1100{
1101 struct nes_vnic *nesvnic = netdev_priv(netdev);
1102
1103 if (nesvnic->rx_checksum_disabled)
1104 return 0;
1105 else
1106 return 1;
1107}
1108
1109
1110/**
1111 * nes_netdev_set_rc_csum
1112 */
1113static int nes_netdev_set_rx_csum(struct net_device *netdev, u32 enable)
1114{
1115 struct nes_vnic *nesvnic = netdev_priv(netdev);
1116
1117 if (enable)
1118 nesvnic->rx_checksum_disabled = 0;
1119 else
1120 nesvnic->rx_checksum_disabled = 1;
1121 return 0;
1122}
1123
1124 1096
1125/** 1097/**
1126 * nes_netdev_get_sset_count 1098 * nes_netdev_get_sset_count
@@ -1521,7 +1493,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
1521 et_cmd->maxrxpkt = 511; 1493 et_cmd->maxrxpkt = 511;
1522 1494
1523 if (nesadapter->OneG_Mode) { 1495 if (nesadapter->OneG_Mode) {
1524 et_cmd->speed = SPEED_1000; 1496 ethtool_cmd_speed_set(et_cmd, SPEED_1000);
1525 if (phy_type == NES_PHY_TYPE_PUMA_1G) { 1497 if (phy_type == NES_PHY_TYPE_PUMA_1G) {
1526 et_cmd->supported = SUPPORTED_1000baseT_Full; 1498 et_cmd->supported = SUPPORTED_1000baseT_Full;
1527 et_cmd->advertising = ADVERTISED_1000baseT_Full; 1499 et_cmd->advertising = ADVERTISED_1000baseT_Full;
@@ -1560,7 +1532,7 @@ static int nes_netdev_get_settings(struct net_device *netdev, struct ethtool_cmd
1560 et_cmd->advertising = ADVERTISED_10000baseT_Full; 1532 et_cmd->advertising = ADVERTISED_10000baseT_Full;
1561 et_cmd->phy_address = mac_index; 1533 et_cmd->phy_address = mac_index;
1562 } 1534 }
1563 et_cmd->speed = SPEED_10000; 1535 ethtool_cmd_speed_set(et_cmd, SPEED_10000);
1564 et_cmd->autoneg = AUTONEG_DISABLE; 1536 et_cmd->autoneg = AUTONEG_DISABLE;
1565 return 0; 1537 return 0;
1566} 1538}
@@ -1598,19 +1570,10 @@ static int nes_netdev_set_settings(struct net_device *netdev, struct ethtool_cmd
1598} 1570}
1599 1571
1600 1572
1601static int nes_netdev_set_flags(struct net_device *netdev, u32 flags)
1602{
1603 return ethtool_op_set_flags(netdev, flags, ETH_FLAG_LRO);
1604}
1605
1606
1607static const struct ethtool_ops nes_ethtool_ops = { 1573static const struct ethtool_ops nes_ethtool_ops = {
1608 .get_link = ethtool_op_get_link, 1574 .get_link = ethtool_op_get_link,
1609 .get_settings = nes_netdev_get_settings, 1575 .get_settings = nes_netdev_get_settings,
1610 .set_settings = nes_netdev_set_settings, 1576 .set_settings = nes_netdev_set_settings,
1611 .get_tx_csum = ethtool_op_get_tx_csum,
1612 .get_rx_csum = nes_netdev_get_rx_csum,
1613 .get_sg = ethtool_op_get_sg,
1614 .get_strings = nes_netdev_get_strings, 1577 .get_strings = nes_netdev_get_strings,
1615 .get_sset_count = nes_netdev_get_sset_count, 1578 .get_sset_count = nes_netdev_get_sset_count,
1616 .get_ethtool_stats = nes_netdev_get_ethtool_stats, 1579 .get_ethtool_stats = nes_netdev_get_ethtool_stats,
@@ -1619,13 +1582,6 @@ static const struct ethtool_ops nes_ethtool_ops = {
1619 .set_coalesce = nes_netdev_set_coalesce, 1582 .set_coalesce = nes_netdev_set_coalesce,
1620 .get_pauseparam = nes_netdev_get_pauseparam, 1583 .get_pauseparam = nes_netdev_get_pauseparam,
1621 .set_pauseparam = nes_netdev_set_pauseparam, 1584 .set_pauseparam = nes_netdev_set_pauseparam,
1622 .set_tx_csum = ethtool_op_set_tx_csum,
1623 .set_rx_csum = nes_netdev_set_rx_csum,
1624 .set_sg = ethtool_op_set_sg,
1625 .get_tso = ethtool_op_get_tso,
1626 .set_tso = ethtool_op_set_tso,
1627 .get_flags = ethtool_op_get_flags,
1628 .set_flags = nes_netdev_set_flags,
1629}; 1585};
1630 1586
1631 1587
@@ -1727,12 +1683,11 @@ struct net_device *nes_netdev_init(struct nes_device *nesdev,
1727 netdev->dev_addr[5] = (u8)u64temp; 1683 netdev->dev_addr[5] = (u8)u64temp;
1728 memcpy(netdev->perm_addr, netdev->dev_addr, 6); 1684 memcpy(netdev->perm_addr, netdev->dev_addr, 6);
1729 1685
1730 if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV)) { 1686 netdev->hw_features = NETIF_F_RXCSUM | NETIF_F_SG | NETIF_F_IP_CSUM;
1731 netdev->features |= NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; 1687 if ((nesvnic->logical_port < 2) || (nesdev->nesadapter->hw_rev != NE020_REV))
1732 netdev->features |= NETIF_F_GSO | NETIF_F_TSO | NETIF_F_SG | NETIF_F_IP_CSUM; 1688 netdev->hw_features |= NETIF_F_TSO;
1733 } else { 1689 netdev->features |= netdev->hw_features;
1734 netdev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; 1690 netdev->hw_features |= NETIF_F_LRO;
1735 }
1736 1691
1737 nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d," 1692 nes_debug(NES_DBG_INIT, "nesvnic = %p, reported features = 0x%lX, QPid = %d,"
1738 " nic_index = %d, logical_port = %d, mac_index = %d.\n", 1693 " nic_index = %d, logical_port = %d, mac_index = %d.\n",
diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h
index ab97f92fc257..7b6985a2e652 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib.h
+++ b/drivers/infiniband/ulp/ipoib/ipoib.h
@@ -91,7 +91,6 @@ enum {
91 IPOIB_STOP_REAPER = 7, 91 IPOIB_STOP_REAPER = 7,
92 IPOIB_FLAG_ADMIN_CM = 9, 92 IPOIB_FLAG_ADMIN_CM = 9,
93 IPOIB_FLAG_UMCAST = 10, 93 IPOIB_FLAG_UMCAST = 10,
94 IPOIB_FLAG_CSUM = 11,
95 94
96 IPOIB_MAX_BACKOFF_SECONDS = 16, 95 IPOIB_MAX_BACKOFF_SECONDS = 16,
97 96
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_cm.c b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
index 93d55806b967..39913a065f99 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_cm.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_cm.c
@@ -1463,8 +1463,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
1463 set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 1463 set_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
1464 ipoib_warn(priv, "enabling connected mode " 1464 ipoib_warn(priv, "enabling connected mode "
1465 "will cause multicast packet drops\n"); 1465 "will cause multicast packet drops\n");
1466 1466 netdev_update_features(dev);
1467 dev->features &= ~(NETIF_F_IP_CSUM | NETIF_F_SG | NETIF_F_TSO);
1468 rtnl_unlock(); 1467 rtnl_unlock();
1469 priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM; 1468 priv->tx_wr.send_flags &= ~IB_SEND_IP_CSUM;
1470 1469
@@ -1474,13 +1473,7 @@ static ssize_t set_mode(struct device *d, struct device_attribute *attr,
1474 1473
1475 if (!strcmp(buf, "datagram\n")) { 1474 if (!strcmp(buf, "datagram\n")) {
1476 clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags); 1475 clear_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
1477 1476 netdev_update_features(dev);
1478 if (test_bit(IPOIB_FLAG_CSUM, &priv->flags)) {
1479 dev->features |= NETIF_F_IP_CSUM | NETIF_F_SG;
1480 priv->dev->features |= NETIF_F_GRO;
1481 if (priv->hca_caps & IB_DEVICE_UD_TSO)
1482 dev->features |= NETIF_F_TSO;
1483 }
1484 dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu)); 1477 dev_set_mtu(dev, min(priv->mcast_mtu, dev->mtu));
1485 rtnl_unlock(); 1478 rtnl_unlock();
1486 ipoib_flush_paths(dev); 1479 ipoib_flush_paths(dev);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
index 19f7f5206f78..29bc7b5724ac 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ethtool.c
@@ -42,32 +42,6 @@ static void ipoib_get_drvinfo(struct net_device *netdev,
42 strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1); 42 strncpy(drvinfo->driver, "ipoib", sizeof(drvinfo->driver) - 1);
43} 43}
44 44
45static u32 ipoib_get_rx_csum(struct net_device *dev)
46{
47 struct ipoib_dev_priv *priv = netdev_priv(dev);
48 return test_bit(IPOIB_FLAG_CSUM, &priv->flags) &&
49 !test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags);
50}
51
52static int ipoib_set_tso(struct net_device *dev, u32 data)
53{
54 struct ipoib_dev_priv *priv = netdev_priv(dev);
55
56 if (data) {
57 if (!test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags) &&
58 (dev->features & NETIF_F_SG) &&
59 (priv->hca_caps & IB_DEVICE_UD_TSO)) {
60 dev->features |= NETIF_F_TSO;
61 } else {
62 ipoib_warn(priv, "can't set TSO on\n");
63 return -EOPNOTSUPP;
64 }
65 } else
66 dev->features &= ~NETIF_F_TSO;
67
68 return 0;
69}
70
71static int ipoib_get_coalesce(struct net_device *dev, 45static int ipoib_get_coalesce(struct net_device *dev,
72 struct ethtool_coalesce *coal) 46 struct ethtool_coalesce *coal)
73{ 47{
@@ -108,8 +82,6 @@ static int ipoib_set_coalesce(struct net_device *dev,
108 82
109static const struct ethtool_ops ipoib_ethtool_ops = { 83static const struct ethtool_ops ipoib_ethtool_ops = {
110 .get_drvinfo = ipoib_get_drvinfo, 84 .get_drvinfo = ipoib_get_drvinfo,
111 .get_rx_csum = ipoib_get_rx_csum,
112 .set_tso = ipoib_set_tso,
113 .get_coalesce = ipoib_get_coalesce, 85 .get_coalesce = ipoib_get_coalesce,
114 .set_coalesce = ipoib_set_coalesce, 86 .set_coalesce = ipoib_set_coalesce,
115}; 87};
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_ib.c b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
index 806d0292dc39..81ae61d68a22 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_ib.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_ib.c
@@ -292,7 +292,7 @@ static void ipoib_ib_handle_rx_wc(struct net_device *dev, struct ib_wc *wc)
292 dev->stats.rx_bytes += skb->len; 292 dev->stats.rx_bytes += skb->len;
293 293
294 skb->dev = dev; 294 skb->dev = dev;
295 if (test_bit(IPOIB_FLAG_CSUM, &priv->flags) && likely(wc->csum_ok)) 295 if ((dev->features & NETIF_F_RXCSUM) && likely(wc->csum_ok))
296 skb->ip_summed = CHECKSUM_UNNECESSARY; 296 skb->ip_summed = CHECKSUM_UNNECESSARY;
297 297
298 napi_gro_receive(&priv->napi, skb); 298 napi_gro_receive(&priv->napi, skb);
diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c
index aca3b44f7aed..86addca9ddf6 100644
--- a/drivers/infiniband/ulp/ipoib/ipoib_main.c
+++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c
@@ -171,6 +171,16 @@ static int ipoib_stop(struct net_device *dev)
171 return 0; 171 return 0;
172} 172}
173 173
174static u32 ipoib_fix_features(struct net_device *dev, u32 features)
175{
176 struct ipoib_dev_priv *priv = netdev_priv(dev);
177
178 if (test_bit(IPOIB_FLAG_ADMIN_CM, &priv->flags))
179 features &= ~(NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO);
180
181 return features;
182}
183
174static int ipoib_change_mtu(struct net_device *dev, int new_mtu) 184static int ipoib_change_mtu(struct net_device *dev, int new_mtu)
175{ 185{
176 struct ipoib_dev_priv *priv = netdev_priv(dev); 186 struct ipoib_dev_priv *priv = netdev_priv(dev);
@@ -970,6 +980,7 @@ static const struct net_device_ops ipoib_netdev_ops = {
970 .ndo_open = ipoib_open, 980 .ndo_open = ipoib_open,
971 .ndo_stop = ipoib_stop, 981 .ndo_stop = ipoib_stop,
972 .ndo_change_mtu = ipoib_change_mtu, 982 .ndo_change_mtu = ipoib_change_mtu,
983 .ndo_fix_features = ipoib_fix_features,
973 .ndo_start_xmit = ipoib_start_xmit, 984 .ndo_start_xmit = ipoib_start_xmit,
974 .ndo_tx_timeout = ipoib_timeout, 985 .ndo_tx_timeout = ipoib_timeout,
975 .ndo_set_multicast_list = ipoib_set_mcast_list, 986 .ndo_set_multicast_list = ipoib_set_mcast_list,
@@ -1154,19 +1165,18 @@ int ipoib_set_dev_features(struct ipoib_dev_priv *priv, struct ib_device *hca)
1154 kfree(device_attr); 1165 kfree(device_attr);
1155 1166
1156 if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) { 1167 if (priv->hca_caps & IB_DEVICE_UD_IP_CSUM) {
1157 set_bit(IPOIB_FLAG_CSUM, &priv->flags); 1168 priv->dev->hw_features = NETIF_F_SG |
1158 priv->dev->features |= NETIF_F_SG | NETIF_F_IP_CSUM; 1169 NETIF_F_IP_CSUM | NETIF_F_RXCSUM;
1159 }
1160 1170
1161 priv->dev->features |= NETIF_F_GRO; 1171 if (priv->hca_caps & IB_DEVICE_UD_TSO)
1172 priv->dev->hw_features |= NETIF_F_TSO;
1162 1173
1163 if (priv->dev->features & NETIF_F_SG && priv->hca_caps & IB_DEVICE_UD_TSO) 1174 priv->dev->features |= priv->dev->hw_features;
1164 priv->dev->features |= NETIF_F_TSO; 1175 }
1165 1176
1166 return 0; 1177 return 0;
1167} 1178}
1168 1179
1169
1170static struct net_device *ipoib_add_port(const char *format, 1180static struct net_device *ipoib_add_port(const char *format,
1171 struct ib_device *hca, u8 port) 1181 struct ib_device *hca, u8 port)
1172{ 1182{