]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
octeontx2-pf: Implement ingress/egress VLAN offload
authorHariprasad Kelam <hkelam@marvell.com>
Sat, 14 Nov 2020 19:52:59 +0000 (01:22 +0530)
committerJakub Kicinski <kuba@kernel.org>
Tue, 17 Nov 2020 21:48:21 +0000 (13:48 -0800)
This patch implements egress VLAN offload by appending NIX_SEND_EXT_S
header to NIX_SEND_HDR_S. The VLAN TCI information is specified
in the NIX_SEND_EXT_S. The VLAN offload in the ingress path is
implemented by configuring the NIX_RX_VTAG_ACTION_S to strip and
capture the outer vlan fields. The NIX PF allocates one MCAM entry
for Rx VLAN offload.

Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: Sunil Goutham <sgoutham@marvell.com>
Signed-off-by: Naveen Mamindlapalli <naveenm@marvell.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/marvell/octeontx2/af/mbox.h
drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c

index 4f230a7272ce40f11d79e03b3bcf660d4d3836b7..ef20078508a5aa792eb4d3ec945fb8ffaa7571a0 100644 (file)
@@ -479,6 +479,19 @@ enum nix_af_status {
        NIX_AF_INVAL_NPA_PF_FUNC    = -419,
        NIX_AF_INVAL_SSO_PF_FUNC    = -420,
        NIX_AF_ERR_TX_VTAG_NOSPC    = -421,
+       NIX_AF_ERR_RX_VTAG_INUSE    = -422,
+};
+
+/* For NIX RX vtag action  */
+enum nix_rx_vtag0_type {
+       NIX_AF_LFX_RX_VTAG_TYPE0, /* reserved for rx vlan offload */
+       NIX_AF_LFX_RX_VTAG_TYPE1,
+       NIX_AF_LFX_RX_VTAG_TYPE2,
+       NIX_AF_LFX_RX_VTAG_TYPE3,
+       NIX_AF_LFX_RX_VTAG_TYPE4,
+       NIX_AF_LFX_RX_VTAG_TYPE5,
+       NIX_AF_LFX_RX_VTAG_TYPE6,
+       NIX_AF_LFX_RX_VTAG_TYPE7,
 };
 
 /* For NIX LF context alloc and init */
index bf844df30464f7b7b1dcd2c782cc423d802f0d39..6665df0ac3598f7d6f59a10fdb58283594085172 100644 (file)
@@ -1984,7 +1984,8 @@ static int nix_rx_vtag_cfg(struct rvu *rvu, int nixlf, int blkaddr,
 {
        u64 regval = req->vtag_size;
 
-       if (req->rx.vtag_type > 7 || req->vtag_size > VTAGSIZE_T8)
+       if (req->rx.vtag_type > NIX_AF_LFX_RX_VTAG_TYPE7 ||
+           req->vtag_size > VTAGSIZE_T8)
                return -EINVAL;
 
        if (req->rx.capture_vtag)
index 9f3d6715748efce19f35e2f40b58fb2c705a5689..68fb4e4757aaa11549f07b0db4c3aa66fd6d7353 100644 (file)
@@ -191,10 +191,14 @@ int otx2_set_mac_address(struct net_device *netdev, void *p)
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
-       if (!otx2_hw_set_mac_addr(pfvf, addr->sa_data))
+       if (!otx2_hw_set_mac_addr(pfvf, addr->sa_data)) {
                memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-       else
+               /* update dmac field in vlan offload rule */
+               if (pfvf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
+                       otx2_install_rxvlan_offload_flow(pfvf);
+       } else {
                return -EPERM;
+       }
 
        return 0;
 }
index f959688e14a3cdd8376d4e64903ea163ca1f55d0..7819f278b99cd4e2989f5017ab6b5ab237539781 100644 (file)
@@ -240,10 +240,13 @@ struct otx2_flow_config {
        u32                     nr_flows;
 #define OTX2_MAX_NTUPLE_FLOWS  32
 #define OTX2_MAX_UNICAST_FLOWS 8
+#define OTX2_MAX_VLAN_FLOWS    1
 #define OTX2_MCAM_COUNT                (OTX2_MAX_NTUPLE_FLOWS + \
-                                OTX2_MAX_UNICAST_FLOWS)
+                                OTX2_MAX_UNICAST_FLOWS + \
+                                OTX2_MAX_VLAN_FLOWS)
        u32                     ntuple_offset;
        u32                     unicast_offset;
+       u32                     rx_vlan_offset;
        u32                     ntuple_max_flows;
        struct list_head        flow_list;
 };
@@ -261,6 +264,7 @@ struct otx2_nic {
 #define OTX2_FLAG_MCAM_ENTRIES_ALLOC           BIT_ULL(3)
 #define OTX2_FLAG_NTUPLE_SUPPORT               BIT_ULL(4)
 #define OTX2_FLAG_UCAST_FLTR_SUPPORT           BIT_ULL(5)
+#define OTX2_FLAG_RX_VLAN_SUPPORT              BIT_ULL(6)
 #define OTX2_FLAG_RX_PAUSE_ENABLED             BIT_ULL(9)
 #define OTX2_FLAG_TX_PAUSE_ENABLED             BIT_ULL(10)
        u64                     flags;
@@ -687,5 +691,7 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
                              struct npc_install_flow_req *req);
 int otx2_del_macfilter(struct net_device *netdev, const u8 *mac);
 int otx2_add_macfilter(struct net_device *netdev, const u8 *mac);
+int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable);
+int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf);
 
 #endif /* OTX2_COMMON_H */
index f297edb2717e2f822ac20a2ab5a26d012c278b02..ba49c5108edc825854f3b7f7832ad9d99257745a 100644 (file)
@@ -58,8 +58,11 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
                flow_cfg->ntuple_offset = 0;
                flow_cfg->unicast_offset = flow_cfg->ntuple_offset +
                                                OTX2_MAX_NTUPLE_FLOWS;
+               flow_cfg->rx_vlan_offset = flow_cfg->unicast_offset +
+                                               OTX2_MAX_UNICAST_FLOWS;
                pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
                pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
+               pfvf->flags |= OTX2_FLAG_RX_VLAN_SUPPORT;
        }
 
        for (i = 0; i < rsp->count; i++)
@@ -711,3 +714,102 @@ int otx2_destroy_mcam_flows(struct otx2_nic *pfvf)
 
        return 0;
 }
+
+int otx2_install_rxvlan_offload_flow(struct otx2_nic *pfvf)
+{
+       struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+       struct npc_install_flow_req *req;
+       int err;
+
+       mutex_lock(&pfvf->mbox.lock);
+       req = otx2_mbox_alloc_msg_npc_install_flow(&pfvf->mbox);
+       if (!req) {
+               mutex_unlock(&pfvf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       req->entry = flow_cfg->entry[flow_cfg->rx_vlan_offset];
+       req->intf = NIX_INTF_RX;
+       ether_addr_copy(req->packet.dmac, pfvf->netdev->dev_addr);
+       eth_broadcast_addr((u8 *)&req->mask.dmac);
+       req->channel = pfvf->hw.rx_chan_base;
+       req->op = NIX_RX_ACTION_DEFAULT;
+       req->features = BIT_ULL(NPC_OUTER_VID) | BIT_ULL(NPC_DMAC);
+       req->vtag0_valid = true;
+       req->vtag0_type = NIX_AF_LFX_RX_VTAG_TYPE0;
+
+       /* Send message to AF */
+       err = otx2_sync_mbox_msg(&pfvf->mbox);
+       mutex_unlock(&pfvf->mbox.lock);
+       return err;
+}
+
+static int otx2_delete_rxvlan_offload_flow(struct otx2_nic *pfvf)
+{
+       struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
+       struct npc_delete_flow_req *req;
+       int err;
+
+       mutex_lock(&pfvf->mbox.lock);
+       req = otx2_mbox_alloc_msg_npc_delete_flow(&pfvf->mbox);
+       if (!req) {
+               mutex_unlock(&pfvf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       req->entry = flow_cfg->entry[flow_cfg->rx_vlan_offset];
+       /* Send message to AF */
+       err = otx2_sync_mbox_msg(&pfvf->mbox);
+       mutex_unlock(&pfvf->mbox.lock);
+       return err;
+}
+
+int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable)
+{
+       struct nix_vtag_config *req;
+       struct mbox_msghdr *rsp_hdr;
+       int err;
+
+       /* Dont have enough mcam entries */
+       if (!(pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT))
+               return -ENOMEM;
+
+       if (enable) {
+               err = otx2_install_rxvlan_offload_flow(pf);
+               if (err)
+                       return err;
+       } else {
+               err = otx2_delete_rxvlan_offload_flow(pf);
+               if (err)
+                       return err;
+       }
+
+       mutex_lock(&pf->mbox.lock);
+       req = otx2_mbox_alloc_msg_nix_vtag_cfg(&pf->mbox);
+       if (!req) {
+               mutex_unlock(&pf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       /* config strip, capture and size */
+       req->vtag_size = VTAGSIZE_T4;
+       req->cfg_type = 1; /* rx vlan cfg */
+       req->rx.vtag_type = NIX_AF_LFX_RX_VTAG_TYPE0;
+       req->rx.strip_vtag = enable;
+       req->rx.capture_vtag = enable;
+
+       err = otx2_sync_mbox_msg(&pf->mbox);
+       if (err) {
+               mutex_unlock(&pf->mbox.lock);
+               return err;
+       }
+
+       rsp_hdr = otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
+       if (IS_ERR(rsp_hdr)) {
+               mutex_unlock(&pf->mbox.lock);
+               return PTR_ERR(rsp_hdr);
+       }
+
+       mutex_unlock(&pf->mbox.lock);
+       return rsp_hdr->rc;
+}
index ac90302b1d813a27d1791efe2290832dd6a4104f..22513e58f7bb3971d5670f6c60d2eca138de6764 100644 (file)
@@ -1566,6 +1566,9 @@ int otx2_open(struct net_device *netdev)
 
        otx2_set_cints_affinity(pf);
 
+       if (pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
+               otx2_enable_rxvlan(pf, true);
+
        /* When reinitializing enable time stamping if it is enabled before */
        if (pf->flags & OTX2_FLAG_TX_TSTAMP_ENABLED) {
                pf->flags &= ~OTX2_FLAG_TX_TSTAMP_ENABLED;
@@ -1763,6 +1766,10 @@ static int otx2_set_features(struct net_device *netdev,
                return otx2_cgx_config_loopback(pf,
                                                features & NETIF_F_LOOPBACK);
 
+       if ((changed & NETIF_F_HW_VLAN_CTAG_RX) && netif_running(netdev))
+               return otx2_enable_rxvlan(pf,
+                                         features & NETIF_F_HW_VLAN_CTAG_RX);
+
        if ((changed & NETIF_F_NTUPLE) && !ntuple)
                otx2_destroy_ntuple_flows(pf);
 
@@ -2138,6 +2145,15 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)
                netdev->priv_flags |= IFF_UNICAST_FLT;
 
+       /* Support TSO on tag interface */
+       netdev->vlan_features |= netdev->features;
+       netdev->hw_features  |= NETIF_F_HW_VLAN_CTAG_TX |
+                               NETIF_F_HW_VLAN_STAG_TX;
+       if (pf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
+               netdev->hw_features |= NETIF_F_HW_VLAN_CTAG_RX |
+                                      NETIF_F_HW_VLAN_STAG_RX;
+       netdev->features |= netdev->hw_features;
+
        netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
        netdev->watchdog_timeo = OTX2_TX_TIMEOUT;
 
index d5d7a2f3749356a4e8d62cdd4b3a4d792e9a9632..d0e25414f1a102447563ee19f573139e92674472 100644 (file)
@@ -556,6 +556,19 @@ static void otx2_sqe_add_ext(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
                ext->tstmp = 1;
        }
 
+#define OTX2_VLAN_PTR_OFFSET     (ETH_HLEN - ETH_TLEN)
+       if (skb_vlan_tag_present(skb)) {
+               if (skb->vlan_proto == htons(ETH_P_8021Q)) {
+                       ext->vlan1_ins_ena = 1;
+                       ext->vlan1_ins_ptr = OTX2_VLAN_PTR_OFFSET;
+                       ext->vlan1_ins_tci = skb_vlan_tag_get(skb);
+               } else if (skb->vlan_proto == htons(ETH_P_8021AD)) {
+                       ext->vlan0_ins_ena = 1;
+                       ext->vlan0_ins_ptr = OTX2_VLAN_PTR_OFFSET;
+                       ext->vlan0_ins_tci = skb_vlan_tag_get(skb);
+               }
+       }
+
        *offset += sizeof(*ext);
 }
 
@@ -871,6 +884,9 @@ bool otx2_sq_append_skb(struct net_device *netdev, struct otx2_snd_queue *sq,
        }
 
        if (skb_shinfo(skb)->gso_size && !is_hw_tso_supported(pfvf, skb)) {
+               /* Insert vlan tag before giving pkt to tso */
+               if (skb_vlan_tag_present(skb))
+                       skb = __vlan_hwaccel_push_inside(skb);
                otx2_sq_append_tso(pfvf, sq, skb, qidx);
                return true;
        }
index 67fabf265fe6f3501fbd6e5c1a130bbafbfd50b0..d3e4cfd244e270c9a924717b83f7af5e340cada4 100644 (file)
@@ -558,6 +558,11 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                              NETIF_F_SG | NETIF_F_TSO | NETIF_F_TSO6 |
                              NETIF_F_GSO_UDP_L4;
        netdev->features = netdev->hw_features;
+       /* Support TSO on tag interface */
+       netdev->vlan_features |= netdev->features;
+       netdev->hw_features  |= NETIF_F_HW_VLAN_CTAG_TX |
+                               NETIF_F_HW_VLAN_STAG_TX;
+       netdev->features |= netdev->hw_features;
 
        netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
        netdev->watchdog_timeo = OTX2_TX_TIMEOUT;