diff options
Diffstat (limited to 'drivers/net/ethernet/emulex')
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_ethtool.c | 12 | ||||
-rw-r--r-- | drivers/net/ethernet/emulex/benet/be_main.c | 64 |
3 files changed, 55 insertions, 22 deletions
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h index 9a2d752..712e7f8 100644 --- a/drivers/net/ethernet/emulex/benet/be.h +++ b/drivers/net/ethernet/emulex/benet/be.h @@ -522,6 +522,7 @@ struct be_adapter { u8 hba_port_num; u16 pvid; __be16 vxlan_port; + int vxlan_port_count; struct phy_info phy; u8 wol_cap; bool wol_en; diff --git a/drivers/net/ethernet/emulex/benet/be_ethtool.c b/drivers/net/ethernet/emulex/benet/be_ethtool.c index e42a791..73a500c 100644 --- a/drivers/net/ethernet/emulex/benet/be_ethtool.c +++ b/drivers/net/ethernet/emulex/benet/be_ethtool.c @@ -1171,7 +1171,8 @@ static u32 be_get_rxfh_key_size(struct net_device *netdev) return RSS_HASH_KEY_LEN; } -static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey) +static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey, + u8 *hfunc) { struct be_adapter *adapter = netdev_priv(netdev); int i; @@ -1185,16 +1186,23 @@ static int be_get_rxfh(struct net_device *netdev, u32 *indir, u8 *hkey) if (hkey) memcpy(hkey, rss->rss_hkey, RSS_HASH_KEY_LEN); + if (hfunc) + *hfunc = ETH_RSS_HASH_TOP; + return 0; } static int be_set_rxfh(struct net_device *netdev, const u32 *indir, - const u8 *hkey) + const u8 *hkey, const u8 hfunc) { int rc = 0, i, j; struct be_adapter *adapter = netdev_priv(netdev); u8 rsstable[RSS_INDIR_TABLE_LEN]; + /* We do not allow change in unsupported parameters */ + if (hfunc != ETH_RSS_HASH_NO_CHANGE && hfunc != ETH_RSS_HASH_TOP) + return -EOPNOTSUPP; + if (indir) { struct be_rx_obj *rxo; diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c index 597c463..2aacd47 100644 --- a/drivers/net/ethernet/emulex/benet/be_main.c +++ b/drivers/net/ethernet/emulex/benet/be_main.c @@ -887,7 +887,8 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, } if (vlan_tag) { - skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); + skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q), + vlan_tag); if (unlikely(!skb)) return skb; skb->vlan_tci = 0; @@ -896,7 +897,8 @@ static struct sk_buff *be_insert_vlan_in_pkt(struct be_adapter *adapter, /* Insert the outer VLAN, if any */ if (adapter->qnq_vid) { vlan_tag = adapter->qnq_vid; - skb = __vlan_put_tag(skb, htons(ETH_P_8021Q), vlan_tag); + skb = vlan_insert_tag_set_proto(skb, htons(ETH_P_8021Q), + vlan_tag); if (unlikely(!skb)) return skb; if (skip_hw_vlan) @@ -1015,9 +1017,8 @@ static struct sk_buff *be_xmit_workarounds(struct be_adapter *adapter, * to pad short packets (<= 32 bytes) to a 36-byte length. */ if (unlikely(!BEx_chip(adapter) && skb->len <= 32)) { - if (skb_padto(skb, 36)) + if (skb_put_padto(skb, 36)) return NULL; - skb->len = 36; } if (BEx_chip(adapter) || lancer_chip(adapter)) { @@ -2853,10 +2854,10 @@ static int be_close(struct net_device *netdev) static int be_rx_qs_create(struct be_adapter *adapter) { + struct rss_info *rss = &adapter->rss_info; + u8 rss_key[RSS_HASH_KEY_LEN]; struct be_rx_obj *rxo; int rc, i, j; - u8 rss_hkey[RSS_HASH_KEY_LEN]; - struct rss_info *rss = &adapter->rss_info; for_all_rx_queues(adapter, rxo, i) { rc = be_queue_alloc(adapter, &rxo->q, RX_Q_LEN, @@ -2901,15 +2902,15 @@ static int be_rx_qs_create(struct be_adapter *adapter) rss->rss_flags = RSS_ENABLE_NONE; } - get_random_bytes(rss_hkey, RSS_HASH_KEY_LEN); + netdev_rss_key_fill(rss_key, RSS_HASH_KEY_LEN); rc = be_cmd_rss_config(adapter, rss->rsstable, rss->rss_flags, - 128, rss_hkey); + 128, rss_key); if (rc) { rss->rss_flags = RSS_ENABLE_NONE; return rc; } - memcpy(rss->rss_hkey, rss_hkey, RSS_HASH_KEY_LEN); + memcpy(rss->rss_hkey, rss_key, RSS_HASH_KEY_LEN); /* First time posting */ for_all_rx_queues(adapter, rxo, i) @@ -3123,6 +3124,8 @@ static void be_mac_clear(struct be_adapter *adapter) #ifdef CONFIG_BE2NET_VXLAN static void be_disable_vxlan_offloads(struct be_adapter *adapter) { + struct net_device *netdev = adapter->netdev; + if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) be_cmd_manage_iface(adapter, adapter->if_handle, OP_CONVERT_TUNNEL_TO_NORMAL); @@ -3132,6 +3135,9 @@ static void be_disable_vxlan_offloads(struct be_adapter *adapter) adapter->flags &= ~BE_FLAGS_VXLAN_OFFLOADS; adapter->vxlan_port = 0; + + netdev->hw_enc_features = 0; + netdev->hw_features &= ~(NETIF_F_GSO_UDP_TUNNEL); } #endif @@ -4365,10 +4371,24 @@ static int be_ndo_bridge_getlink(struct sk_buff *skb, u32 pid, u32 seq, return ndo_dflt_bridge_getlink(skb, pid, seq, dev, hsw_mode == PORT_FWD_TYPE_VEPA ? - BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB); + BRIDGE_MODE_VEPA : BRIDGE_MODE_VEB, + 0, 0); } #ifdef CONFIG_BE2NET_VXLAN +/* VxLAN offload Notes: + * + * The stack defines tunnel offload flags (hw_enc_features) for IP and doesn't + * distinguish various types of transports (VxLAN, GRE, NVGRE ..). So, offload + * is expected to work across all types of IP tunnels once exported. Skyhawk + * supports offloads for either VxLAN or NVGRE, exclusively. So we export VxLAN + * offloads in hw_enc_features only when a VxLAN port is added. Note this only + * ensures that other tunnels work fine while VxLAN offloads are not enabled. + * + * Skyhawk supports VxLAN offloads only for one UDP dport. So, if the stack + * adds more than one port, disable offloads and don't re-enable them again + * until after all the tunnels are removed. + */ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family, __be16 port) { @@ -4380,13 +4400,16 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family, return; if (adapter->flags & BE_FLAGS_VXLAN_OFFLOADS) { - dev_warn(dev, "Cannot add UDP port %d for VxLAN offloads\n", - be16_to_cpu(port)); dev_info(dev, "Only one UDP port supported for VxLAN offloads\n"); - return; + dev_info(dev, "Disabling VxLAN offloads\n"); + adapter->vxlan_port_count++; + goto err; } + if (adapter->vxlan_port_count++ >= 1) + return; + status = be_cmd_manage_iface(adapter, adapter->if_handle, OP_CONVERT_NORMAL_TO_TUNNEL); if (status) { @@ -4402,6 +4425,11 @@ static void be_add_vxlan_port(struct net_device *netdev, sa_family_t sa_family, adapter->flags |= BE_FLAGS_VXLAN_OFFLOADS; adapter->vxlan_port = port; + netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | + NETIF_F_TSO | NETIF_F_TSO6 | + NETIF_F_GSO_UDP_TUNNEL; + netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; + dev_info(dev, "Enabled VxLAN offloads for UDP port %d\n", be16_to_cpu(port)); return; @@ -4418,13 +4446,15 @@ static void be_del_vxlan_port(struct net_device *netdev, sa_family_t sa_family, return; if (adapter->vxlan_port != port) - return; + goto done; be_disable_vxlan_offloads(adapter); dev_info(&adapter->pdev->dev, "Disabled VxLAN offloads for UDP port %d\n", be16_to_cpu(port)); +done: + adapter->vxlan_port_count--; } static bool be_gso_check(struct sk_buff *skb, struct net_device *dev) @@ -4468,12 +4498,6 @@ static void be_netdev_init(struct net_device *netdev) { struct be_adapter *adapter = netdev_priv(netdev); - if (skyhawk_chip(adapter)) { - netdev->hw_enc_features |= NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | - NETIF_F_TSO | NETIF_F_TSO6 | - NETIF_F_GSO_UDP_TUNNEL; - netdev->hw_features |= NETIF_F_GSO_UDP_TUNNEL; - } netdev->hw_features |= NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_TX; |