cxgb4: add geneve offload support for T6
authorGanesh Goudar <ganeshgr@chelsio.com>
Mon, 22 Jan 2018 13:18:26 +0000 (18:48 +0530)
committerDavid S. Miller <davem@davemloft.net>
Mon, 22 Jan 2018 15:18:09 +0000 (10:18 -0500)
Add geneve segmentation offload support of T6 cards.

Original work by: Santosh Rastapur <santosh@chelsio.com>
Signed-off-by: Ganesh Goudar <ganeshgr@chelsio.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
drivers/net/ethernet/chelsio/cxgb4/sge.c
drivers/net/ethernet/chelsio/cxgb4/t4_regs.h

index f05b58f74c7aabc4a838fb086bc909dc6b5391c2..3e0218735b2b4c0cec3a7f34276b39ff48f9e360 100644 (file)
@@ -846,6 +846,8 @@ struct adapter {
        int msg_enable;
        __be16 vxlan_port;
        u8 vxlan_port_cnt;
+       __be16 geneve_port;
+       u8 geneve_port_cnt;
 
        struct adapter_params params;
        struct cxgb4_virt_res vres;
index 11fe5961040a925ce330f4dce8c05c7f555dcc59..4716387830eff0b09899f0afa7f860d1e2ddca88 100644 (file)
@@ -3020,6 +3020,17 @@ static void cxgb_del_udp_tunnel(struct net_device *netdev,
                adapter->vxlan_port = 0;
                t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A, 0);
                break;
+       case UDP_TUNNEL_TYPE_GENEVE:
+               if (!adapter->geneve_port_cnt ||
+                   adapter->geneve_port != ti->port)
+                       return; /* Invalid GENEVE destination port */
+
+               adapter->geneve_port_cnt--;
+               if (adapter->geneve_port_cnt)
+                       return;
+
+               adapter->geneve_port = 0;
+               t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A, 0);
        default:
                return;
        }
@@ -3055,17 +3066,11 @@ static void cxgb_add_udp_tunnel(struct net_device *netdev,
        u8 match_all_mac[] = { 0, 0, 0, 0, 0, 0 };
        int i, ret;
 
-       if (chip_ver < CHELSIO_T6)
+       if (chip_ver < CHELSIO_T6 || !adapter->rawf_cnt)
                return;
 
        switch (ti->type) {
        case UDP_TUNNEL_TYPE_VXLAN:
-               /* For T6 fw reserves last 2 entries for
-                * storing match all mac filter (config file entry).
-                */
-               if (!adapter->rawf_cnt)
-                       return;
-
                /* Callback for adding vxlan port can be called with the same
                 * port for both IPv4 and IPv6. We should not disable the
                 * offloading when the same port for both protocols is added
@@ -3091,6 +3096,26 @@ static void cxgb_add_udp_tunnel(struct net_device *netdev,
                t4_write_reg(adapter, MPS_RX_VXLAN_TYPE_A,
                             VXLAN_V(be16_to_cpu(ti->port)) | VXLAN_EN_F);
                break;
+       case UDP_TUNNEL_TYPE_GENEVE:
+               if (adapter->geneve_port_cnt &&
+                   adapter->geneve_port == ti->port) {
+                       adapter->geneve_port_cnt++;
+                       return;
+               }
+
+               /* We will support only one GENEVE port */
+               if (adapter->geneve_port_cnt) {
+                       netdev_info(netdev, "UDP port %d already offloaded, not adding port %d\n",
+                                   be16_to_cpu(adapter->geneve_port),
+                                   be16_to_cpu(ti->port));
+                       return;
+               }
+
+               adapter->geneve_port = ti->port;
+               adapter->geneve_port_cnt = 1;
+
+               t4_write_reg(adapter, MPS_RX_GENEVE_TYPE_A,
+                            GENEVE_V(be16_to_cpu(ti->port)) | GENEVE_EN_F);
        default:
                return;
        }
@@ -3101,24 +3126,22 @@ static void cxgb_add_udp_tunnel(struct net_device *netdev,
         * we will remove this 'match all' entry and fallback to adding
         * exact match filters.
         */
-       if (adapter->rawf_cnt) {
-               for_each_port(adapter, i) {
-                       pi = adap2pinfo(adapter, i);
-
-                       ret = t4_alloc_raw_mac_filt(adapter, pi->viid,
-                                                   match_all_mac,
-                                                   match_all_mac,
-                                                   adapter->rawf_start +
-                                                   pi->port_id,
-                                                   1, pi->port_id, true);
-                       if (ret < 0) {
-                               netdev_info(netdev, "Failed to allocate a mac filter entry, not adding port %d\n",
-                                           be16_to_cpu(ti->port));
-                               cxgb_del_udp_tunnel(netdev, ti);
-                               return;
-                       }
-                       atomic_inc(&adapter->mps_encap[ret].refcnt);
+       for_each_port(adapter, i) {
+               pi = adap2pinfo(adapter, i);
+
+               ret = t4_alloc_raw_mac_filt(adapter, pi->viid,
+                                           match_all_mac,
+                                           match_all_mac,
+                                           adapter->rawf_start +
+                                           pi->port_id,
+                                           1, pi->port_id, true);
+               if (ret < 0) {
+                       netdev_info(netdev, "Failed to allocate a mac filter entry, not adding port %d\n",
+                                   be16_to_cpu(ti->port));
+                       cxgb_del_udp_tunnel(netdev, ti);
+                       return;
                }
+               atomic_inc(&adapter->mps_encap[ret].refcnt);
        }
 }
 
index eab781fab2a89d1ac1ea93c508f298486007f554..a7af71bf14fbb6a345d6c0192232e14eed77f835 100644 (file)
@@ -1199,6 +1199,8 @@ enum cpl_tx_tnl_lso_type cxgb_encap_offload_supported(struct sk_buff *skb)
        case IPPROTO_UDP:
                if (adapter->vxlan_port == udp_hdr(skb)->dest)
                        tnl_type = TX_TNL_TYPE_VXLAN;
+               else if (adapter->geneve_port == udp_hdr(skb)->dest)
+                       tnl_type = TX_TNL_TYPE_GENEVE;
                break;
        default:
                return tnl_type;
@@ -1238,6 +1240,7 @@ static inline void t6_fill_tnl_lso(struct sk_buff *skb,
 
        switch (tnl_type) {
        case TX_TNL_TYPE_VXLAN:
+       case TX_TNL_TYPE_GENEVE:
                tnl_lso->UdpLenSetOut_to_TnlHdrLen =
                        htons(CPL_TX_TNL_LSO_UDPCHKCLROUT_F |
                        CPL_TX_TNL_LSO_UDPLENSETOUT_F);
index d9c06d6dc7b2b0dfc55d3e22eb708a1e1a6df9ca..a6df73398d17f830090255360dce916ec9448af9 100644 (file)
 #define VXLAN_V(x) ((x) << VXLAN_S)
 #define VXLAN_G(x) (((x) >> VXLAN_S) & VXLAN_M)
 
+#define MPS_RX_GENEVE_TYPE_A 0x11238
+
+#define GENEVE_EN_S    16
+#define GENEVE_EN_V(x) ((x) << GENEVE_EN_S)
+#define GENEVE_EN_F    GENEVE_EN_V(1U)
+
+#define GENEVE_S    0
+#define GENEVE_M    0xffffU
+#define GENEVE_V(x) ((x) << GENEVE_S)
+#define GENEVE_G(x) (((x) >> GENEVE_S) & GENEVE_M)
+
 #define MPS_CLS_TCAM_Y_L_A 0xf000
 #define MPS_CLS_TCAM_DATA0_A 0xf000
 #define MPS_CLS_TCAM_DATA1_A 0xf004