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 */ |
