diff options
author | Don Skidmore <donald.c.skidmore@intel.com> | 2014-12-23 02:40:34 -0500 |
---|---|---|
committer | Jeff Kirsher <jeffrey.t.kirsher@intel.com> | 2015-02-05 22:57:49 -0500 |
commit | 3f207800a998fb1b0b36df251e826ee7682294f7 (patch) | |
tree | a943a6de0631fe8232511f76b9313af7f1a16e27 | |
parent | 4dedadcbae35c84366c2543bce37e045b1665196 (diff) |
ixgbe: add VXLAN offload support for X550 devices
Add support VXLAN receive checksum offload in X550 hardware.
Signed-off-by: Don Skidmore <donald.c.skidmore@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r-- | drivers/net/ethernet/intel/Kconfig | 11 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe.h | 1 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 98 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 5 |
4 files changed, 113 insertions, 2 deletions
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig index 4d61ef50b465..f4ff465584a0 100644 --- a/drivers/net/ethernet/intel/Kconfig +++ b/drivers/net/ethernet/intel/Kconfig | |||
@@ -192,6 +192,17 @@ config IXGBE | |||
192 | To compile this driver as a module, choose M here. The module | 192 | To compile this driver as a module, choose M here. The module |
193 | will be called ixgbe. | 193 | will be called ixgbe. |
194 | 194 | ||
195 | config IXGBE_VXLAN | ||
196 | bool "Virtual eXtensible Local Area Network Support" | ||
197 | default n | ||
198 | depends on IXGBE && VXLAN && !(IXGBE=y && VXLAN=m) | ||
199 | ---help--- | ||
200 | This allows one to create VXLAN virtual interfaces that provide | ||
201 | Layer 2 Networks over Layer 3 Networks. VXLAN is often used | ||
202 | to tunnel virtual network infrastructure in virtualized environments. | ||
203 | Say Y here if you want to use Virtual eXtensible Local Area Network | ||
204 | (VXLAN) in the driver. | ||
205 | |||
195 | config IXGBE_HWMON | 206 | config IXGBE_HWMON |
196 | bool "Intel(R) 10GbE PCI Express adapters HWMON support" | 207 | bool "Intel(R) 10GbE PCI Express adapters HWMON support" |
197 | default y | 208 | default y |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h index 38fc64cf5dca..699117aff5fe 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h | |||
@@ -753,6 +753,7 @@ struct ixgbe_adapter { | |||
753 | u32 timer_event_accumulator; | 753 | u32 timer_event_accumulator; |
754 | u32 vferr_refcount; | 754 | u32 vferr_refcount; |
755 | struct ixgbe_mac_addr *mac_table; | 755 | struct ixgbe_mac_addr *mac_table; |
756 | u16 vxlan_port; | ||
756 | struct kobject *info_kobj; | 757 | struct kobject *info_kobj; |
757 | #ifdef CONFIG_IXGBE_HWMON | 758 | #ifdef CONFIG_IXGBE_HWMON |
758 | struct hwmon_buff *ixgbe_hwmon_buff; | 759 | struct hwmon_buff *ixgbe_hwmon_buff; |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index e9e3a1eb9a97..6aa9b96b2e10 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/if_bridge.h> | 50 | #include <linux/if_bridge.h> |
51 | #include <linux/prefetch.h> | 51 | #include <linux/prefetch.h> |
52 | #include <scsi/fc/fc_fcoe.h> | 52 | #include <scsi/fc/fc_fcoe.h> |
53 | #include <net/vxlan.h> | ||
53 | 54 | ||
54 | #ifdef CONFIG_OF | 55 | #ifdef CONFIG_OF |
55 | #include <linux/of_net.h> | 56 | #include <linux/of_net.h> |
@@ -1396,12 +1397,23 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring, | |||
1396 | union ixgbe_adv_rx_desc *rx_desc, | 1397 | union ixgbe_adv_rx_desc *rx_desc, |
1397 | struct sk_buff *skb) | 1398 | struct sk_buff *skb) |
1398 | { | 1399 | { |
1400 | __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; | ||
1401 | __le16 hdr_info = rx_desc->wb.lower.lo_dword.hs_rss.hdr_info; | ||
1402 | bool encap_pkt = false; | ||
1403 | |||
1399 | skb_checksum_none_assert(skb); | 1404 | skb_checksum_none_assert(skb); |
1400 | 1405 | ||
1401 | /* Rx csum disabled */ | 1406 | /* Rx csum disabled */ |
1402 | if (!(ring->netdev->features & NETIF_F_RXCSUM)) | 1407 | if (!(ring->netdev->features & NETIF_F_RXCSUM)) |
1403 | return; | 1408 | return; |
1404 | 1409 | ||
1410 | if ((pkt_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_VXLAN)) && | ||
1411 | (hdr_info & cpu_to_le16(IXGBE_RXDADV_PKTTYPE_TUNNEL >> 16))) { | ||
1412 | encap_pkt = true; | ||
1413 | skb->encapsulation = 1; | ||
1414 | skb->ip_summed = CHECKSUM_NONE; | ||
1415 | } | ||
1416 | |||
1405 | /* if IP and error */ | 1417 | /* if IP and error */ |
1406 | if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_IPCS) && | 1418 | if (ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_IPCS) && |
1407 | ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_IPE)) { | 1419 | ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_IPE)) { |
@@ -1413,8 +1425,6 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring, | |||
1413 | return; | 1425 | return; |
1414 | 1426 | ||
1415 | if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_TCPE)) { | 1427 | if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_TCPE)) { |
1416 | __le16 pkt_info = rx_desc->wb.lower.lo_dword.hs_rss.pkt_info; | ||
1417 | |||
1418 | /* | 1428 | /* |
1419 | * 82599 errata, UDP frames with a 0 checksum can be marked as | 1429 | * 82599 errata, UDP frames with a 0 checksum can be marked as |
1420 | * checksum errors. | 1430 | * checksum errors. |
@@ -1429,6 +1439,17 @@ static inline void ixgbe_rx_checksum(struct ixgbe_ring *ring, | |||
1429 | 1439 | ||
1430 | /* It must be a TCP or UDP packet with a valid checksum */ | 1440 | /* It must be a TCP or UDP packet with a valid checksum */ |
1431 | skb->ip_summed = CHECKSUM_UNNECESSARY; | 1441 | skb->ip_summed = CHECKSUM_UNNECESSARY; |
1442 | if (encap_pkt) { | ||
1443 | if (!ixgbe_test_staterr(rx_desc, IXGBE_RXD_STAT_OUTERIPCS)) | ||
1444 | return; | ||
1445 | |||
1446 | if (ixgbe_test_staterr(rx_desc, IXGBE_RXDADV_ERR_OUTERIPER)) { | ||
1447 | ring->rx_stats.csum_err++; | ||
1448 | return; | ||
1449 | } | ||
1450 | /* If we checked the outer header let the stack know */ | ||
1451 | skb->csum_level = 1; | ||
1452 | } | ||
1432 | } | 1453 | } |
1433 | 1454 | ||
1434 | static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring, | 1455 | static bool ixgbe_alloc_mapped_page(struct ixgbe_ring *rx_ring, |
@@ -5627,6 +5648,10 @@ static int ixgbe_open(struct net_device *netdev) | |||
5627 | 5648 | ||
5628 | ixgbe_up_complete(adapter); | 5649 | ixgbe_up_complete(adapter); |
5629 | 5650 | ||
5651 | #if IS_ENABLED(CONFIG_IXGBE_VXLAN) | ||
5652 | vxlan_get_rx_port(netdev); | ||
5653 | |||
5654 | #endif | ||
5630 | return 0; | 5655 | return 0; |
5631 | 5656 | ||
5632 | err_set_queues: | 5657 | err_set_queues: |
@@ -7771,6 +7796,64 @@ static int ixgbe_set_features(struct net_device *netdev, | |||
7771 | return 0; | 7796 | return 0; |
7772 | } | 7797 | } |
7773 | 7798 | ||
7799 | /** | ||
7800 | * ixgbe_add_vxlan_port - Get notifications about VXLAN ports that come up | ||
7801 | * @dev: The port's netdev | ||
7802 | * @sa_family: Socket Family that VXLAN is notifiying us about | ||
7803 | * @port: New UDP port number that VXLAN started listening to | ||
7804 | **/ | ||
7805 | static void ixgbe_add_vxlan_port(struct net_device *dev, sa_family_t sa_family, | ||
7806 | __be16 port) | ||
7807 | { | ||
7808 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
7809 | struct ixgbe_hw *hw = &adapter->hw; | ||
7810 | u16 new_port = ntohs(port); | ||
7811 | |||
7812 | if (sa_family == AF_INET6) | ||
7813 | return; | ||
7814 | |||
7815 | if (adapter->vxlan_port == new_port) { | ||
7816 | netdev_info(dev, "Port %d already offloaded\n", new_port); | ||
7817 | return; | ||
7818 | } | ||
7819 | |||
7820 | if (adapter->vxlan_port) { | ||
7821 | netdev_info(dev, | ||
7822 | "Hit Max num of UDP ports, not adding port %d\n", | ||
7823 | new_port); | ||
7824 | return; | ||
7825 | } | ||
7826 | |||
7827 | adapter->vxlan_port = new_port; | ||
7828 | IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, new_port); | ||
7829 | } | ||
7830 | |||
7831 | /** | ||
7832 | * ixgbe_del_vxlan_port - Get notifications about VXLAN ports that go away | ||
7833 | * @dev: The port's netdev | ||
7834 | * @sa_family: Socket Family that VXLAN is notifying us about | ||
7835 | * @port: UDP port number that VXLAN stopped listening to | ||
7836 | **/ | ||
7837 | static void ixgbe_del_vxlan_port(struct net_device *dev, sa_family_t sa_family, | ||
7838 | __be16 port) | ||
7839 | { | ||
7840 | struct ixgbe_adapter *adapter = netdev_priv(dev); | ||
7841 | struct ixgbe_hw *hw = &adapter->hw; | ||
7842 | u16 new_port = ntohs(port); | ||
7843 | |||
7844 | if (sa_family == AF_INET6) | ||
7845 | return; | ||
7846 | |||
7847 | if (adapter->vxlan_port != new_port) { | ||
7848 | netdev_info(dev, "Port %d was not found, not deleting\n", | ||
7849 | new_port); | ||
7850 | return; | ||
7851 | } | ||
7852 | |||
7853 | adapter->vxlan_port = 0; | ||
7854 | IXGBE_WRITE_REG(hw, IXGBE_VXLANCTRL, 0); | ||
7855 | } | ||
7856 | |||
7774 | static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], | 7857 | static int ixgbe_ndo_fdb_add(struct ndmsg *ndm, struct nlattr *tb[], |
7775 | struct net_device *dev, | 7858 | struct net_device *dev, |
7776 | const unsigned char *addr, u16 vid, | 7859 | const unsigned char *addr, u16 vid, |
@@ -7982,6 +8065,8 @@ static const struct net_device_ops ixgbe_netdev_ops = { | |||
7982 | .ndo_bridge_getlink = ixgbe_ndo_bridge_getlink, | 8065 | .ndo_bridge_getlink = ixgbe_ndo_bridge_getlink, |
7983 | .ndo_dfwd_add_station = ixgbe_fwd_add, | 8066 | .ndo_dfwd_add_station = ixgbe_fwd_add, |
7984 | .ndo_dfwd_del_station = ixgbe_fwd_del, | 8067 | .ndo_dfwd_del_station = ixgbe_fwd_del, |
8068 | .ndo_add_vxlan_port = ixgbe_add_vxlan_port, | ||
8069 | .ndo_del_vxlan_port = ixgbe_del_vxlan_port, | ||
7985 | }; | 8070 | }; |
7986 | 8071 | ||
7987 | /** | 8072 | /** |
@@ -8339,6 +8424,15 @@ skip_sriov: | |||
8339 | netdev->priv_flags |= IFF_UNICAST_FLT; | 8424 | netdev->priv_flags |= IFF_UNICAST_FLT; |
8340 | netdev->priv_flags |= IFF_SUPP_NOFCS; | 8425 | netdev->priv_flags |= IFF_SUPP_NOFCS; |
8341 | 8426 | ||
8427 | switch (adapter->hw.mac.type) { | ||
8428 | case ixgbe_mac_X550: | ||
8429 | case ixgbe_mac_X550EM_x: | ||
8430 | netdev->hw_enc_features |= NETIF_F_RXCSUM; | ||
8431 | break; | ||
8432 | default: | ||
8433 | break; | ||
8434 | } | ||
8435 | |||
8342 | #ifdef CONFIG_IXGBE_DCB | 8436 | #ifdef CONFIG_IXGBE_DCB |
8343 | netdev->dcbnl_ops = &dcbnl_ops; | 8437 | netdev->dcbnl_ops = &dcbnl_ops; |
8344 | #endif | 8438 | #endif |
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index d101b25dc4b6..02b57bfe72b0 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | |||
@@ -399,6 +399,7 @@ struct ixgbe_thermal_sensor_data { | |||
399 | 399 | ||
400 | #define IXGBE_WUPL 0x05900 | 400 | #define IXGBE_WUPL 0x05900 |
401 | #define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */ | 401 | #define IXGBE_WUPM 0x05A00 /* wake up pkt memory 0x5A00-0x5A7C */ |
402 | #define IXGBE_VXLANCTRL 0x0000507C /* Rx filter VXLAN UDPPORT Register */ | ||
402 | #define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */ | 403 | #define IXGBE_FHFT(_n) (0x09000 + ((_n) * 0x100)) /* Flex host filter table */ |
403 | #define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100)) /* Ext Flexible Host | 404 | #define IXGBE_FHFT_EXT(_n) (0x09800 + ((_n) * 0x100)) /* Ext Flexible Host |
404 | * Filter Table */ | 405 | * Filter Table */ |
@@ -2122,6 +2123,7 @@ enum { | |||
2122 | #define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ | 2123 | #define IXGBE_RXD_STAT_IPCS 0x40 /* IP xsum calculated */ |
2123 | #define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */ | 2124 | #define IXGBE_RXD_STAT_PIF 0x80 /* passed in-exact filter */ |
2124 | #define IXGBE_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ | 2125 | #define IXGBE_RXD_STAT_CRCV 0x100 /* Speculative CRC Valid */ |
2126 | #define IXGBE_RXD_STAT_OUTERIPCS 0x100 /* Cloud IP xsum calculated */ | ||
2125 | #define IXGBE_RXD_STAT_VEXT 0x200 /* 1st VLAN found */ | 2127 | #define IXGBE_RXD_STAT_VEXT 0x200 /* 1st VLAN found */ |
2126 | #define IXGBE_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ | 2128 | #define IXGBE_RXD_STAT_UDPV 0x400 /* Valid UDP checksum */ |
2127 | #define IXGBE_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ | 2129 | #define IXGBE_RXD_STAT_DYNINT 0x800 /* Pkt caused INT via DYNINT */ |
@@ -2139,6 +2141,7 @@ enum { | |||
2139 | #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ | 2141 | #define IXGBE_RXD_ERR_IPE 0x80 /* IP Checksum Error */ |
2140 | #define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */ | 2142 | #define IXGBE_RXDADV_ERR_MASK 0xfff00000 /* RDESC.ERRORS mask */ |
2141 | #define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ | 2143 | #define IXGBE_RXDADV_ERR_SHIFT 20 /* RDESC.ERRORS shift */ |
2144 | #define IXGBE_RXDADV_ERR_OUTERIPER 0x04000000 /* CRC IP Header error */ | ||
2142 | #define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCoEFe/IPE */ | 2145 | #define IXGBE_RXDADV_ERR_FCEOFE 0x80000000 /* FCoEFe/IPE */ |
2143 | #define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */ | 2146 | #define IXGBE_RXDADV_ERR_FCERR 0x00700000 /* FCERR/FDIRERR */ |
2144 | #define IXGBE_RXDADV_ERR_FDIR_LEN 0x00100000 /* FDIR Length error */ | 2147 | #define IXGBE_RXDADV_ERR_FDIR_LEN 0x00100000 /* FDIR Length error */ |
@@ -2227,6 +2230,8 @@ enum { | |||
2227 | #define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ | 2230 | #define IXGBE_RXDADV_PKTTYPE_UDP 0x00000200 /* UDP hdr present */ |
2228 | #define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ | 2231 | #define IXGBE_RXDADV_PKTTYPE_SCTP 0x00000400 /* SCTP hdr present */ |
2229 | #define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ | 2232 | #define IXGBE_RXDADV_PKTTYPE_NFS 0x00000800 /* NFS hdr present */ |
2233 | #define IXGBE_RXDADV_PKTTYPE_VXLAN 0x00000800 /* VXLAN hdr present */ | ||
2234 | #define IXGBE_RXDADV_PKTTYPE_TUNNEL 0x00010000 /* Tunnel type */ | ||
2230 | #define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ | 2235 | #define IXGBE_RXDADV_PKTTYPE_IPSEC_ESP 0x00001000 /* IPSec ESP */ |
2231 | #define IXGBE_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ | 2236 | #define IXGBE_RXDADV_PKTTYPE_IPSEC_AH 0x00002000 /* IPSec AH */ |
2232 | #define IXGBE_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ | 2237 | #define IXGBE_RXDADV_PKTTYPE_LINKSEC 0x00004000 /* LinkSec Encap */ |