]> git.baikalelectronics.ru Git - kernel.git/commitdiff
octeontx2-pf: offload DMAC filters to CGX/RPM block
authorHariprasad Kelam <hkelam@marvell.com>
Wed, 30 Jun 2021 10:10:59 +0000 (15:40 +0530)
committerDavid S. Miller <davem@davemloft.net>
Thu, 1 Jul 2021 20:02:38 +0000 (13:02 -0700)
DMAC filtering can be achieved by either NPC MCAM rules or
CGX/RPM MAC filters. Currently we are achieving this by NPC
MCAM rules. This patch offloads DMAC filters to CGX/RPM MAC
filters instead of NPC MCAM rules. Offloading DMAC filter to
CGX/RPM block helps in reducing traffic to NPC block and
save MCAM rules

Signed-off-by: Hariprasad Kelam <hkelam@marvell.com>
Signed-off-by: Sunil Kovvuri Goutham <sgoutham@marvell.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/marvell/octeontx2/nic/Makefile
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_dmac_flt.c [new file with mode: 0644]
drivers/net/ethernet/marvell/octeontx2/nic/otx2_flows.c
drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c

index 457c94793e63b99e56bd72b7d1155cd1848d97d0..3254b02205ca598edd2b01183b3559c1204de840 100644 (file)
@@ -7,7 +7,7 @@ obj-$(CONFIG_OCTEONTX2_PF) += rvu_nicpf.o
 obj-$(CONFIG_OCTEONTX2_VF) += rvu_nicvf.o
 
 rvu_nicpf-y := otx2_pf.o otx2_common.o otx2_txrx.o otx2_ethtool.o \
-                    otx2_ptp.o otx2_flows.o otx2_tc.o cn10k.o
+               otx2_ptp.o otx2_flows.o otx2_tc.o cn10k.o otx2_dmac_flt.o
 rvu_nicvf-y := otx2_vf.o
 
 ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
index cf7875d51d879325cd79f7a785de58caf1b343a0..7cccd802c4ed0ecf14ea87ce9ea8812e69cc31e3 100644 (file)
@@ -210,6 +210,9 @@ int otx2_set_mac_address(struct net_device *netdev, void *p)
                /* update dmac field in vlan offload rule */
                if (pfvf->flags & OTX2_FLAG_RX_VLAN_SUPPORT)
                        otx2_install_rxvlan_offload_flow(pfvf);
+               /* update dmac address in ntuple and DMAC filter list */
+               if (pfvf->flags & OTX2_FLAG_DMACFLTR_SUPPORT)
+                       otx2_dmacflt_update_pfmac_flow(pfvf);
        } else {
                return -EPERM;
        }
index 20a9c69f020fc4423d52a28e1061f5ea6763a770..8fd58cd07f50b8ce9f690d24d30d616b2175a3fa 100644 (file)
@@ -288,6 +288,9 @@ struct otx2_flow_config {
        u16                     tc_flower_offset;
        u16                     ntuple_max_flows;
        u16                     tc_max_flows;
+       u8                      dmacflt_max_flows;
+       u8                      *bmap_to_dmacindex;
+       unsigned long           dmacflt_bmap;
        struct list_head        flow_list;
 };
 
@@ -329,6 +332,7 @@ struct otx2_nic {
 #define OTX2_FLAG_TC_FLOWER_SUPPORT            BIT_ULL(11)
 #define OTX2_FLAG_TC_MATCHALL_EGRESS_ENABLED   BIT_ULL(12)
 #define OTX2_FLAG_TC_MATCHALL_INGRESS_ENABLED  BIT_ULL(13)
+#define OTX2_FLAG_DMACFLTR_SUPPORT             BIT_ULL(14)
        u64                     flags;
 
        struct otx2_qset        qset;
@@ -834,4 +838,11 @@ int otx2_init_tc(struct otx2_nic *nic);
 void otx2_shutdown_tc(struct otx2_nic *nic);
 int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
                  void *type_data);
+/* CGX/RPM DMAC filters support */
+int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf);
+int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos);
+int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac, u8 bit_pos);
+int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos);
+void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf);
+void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf);
 #endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dmac_flt.c
new file mode 100644 (file)
index 0000000..ffe3e94
--- /dev/null
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell OcteonTx2 RVU Physcial Function ethernet driver
+ *
+ * Copyright (C) 2021 Marvell.
+ */
+
+#include "otx2_common.h"
+
+static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
+                              u8 *dmac_index)
+{
+       struct cgx_mac_addr_add_req *req;
+       struct cgx_mac_addr_add_rsp *rsp;
+       int err;
+
+       mutex_lock(&pf->mbox.lock);
+
+       req = otx2_mbox_alloc_msg_cgx_mac_addr_add(&pf->mbox);
+       if (!req) {
+               mutex_unlock(&pf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       ether_addr_copy(req->mac_addr, mac);
+       err = otx2_sync_mbox_msg(&pf->mbox);
+
+       if (!err) {
+               rsp = (struct cgx_mac_addr_add_rsp *)
+                        otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
+               *dmac_index = rsp->index;
+       }
+
+       mutex_unlock(&pf->mbox.lock);
+       return err;
+}
+
+static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf)
+{
+       struct cgx_mac_addr_set_or_get *req;
+       int err;
+
+       mutex_lock(&pf->mbox.lock);
+
+       req = otx2_mbox_alloc_msg_cgx_mac_addr_set(&pf->mbox);
+       if (!req) {
+               mutex_unlock(&pf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       ether_addr_copy(req->mac_addr, pf->netdev->dev_addr);
+       err = otx2_sync_mbox_msg(&pf->mbox);
+
+       mutex_unlock(&pf->mbox.lock);
+       return err;
+}
+
+int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos)
+{
+       u8 *dmacindex;
+
+       /* Store dmacindex returned by CGX/RPM driver which will
+        * be used for macaddr update/remove
+        */
+       dmacindex = &pf->flow_cfg->bmap_to_dmacindex[bit_pos];
+
+       if (ether_addr_equal(mac, pf->netdev->dev_addr))
+               return otx2_dmacflt_add_pfmac(pf);
+       else
+               return otx2_dmacflt_do_add(pf, mac, dmacindex);
+}
+
+static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac,
+                                 u8 dmac_index)
+{
+       struct cgx_mac_addr_del_req *req;
+       int err;
+
+       mutex_lock(&pfvf->mbox.lock);
+       req = otx2_mbox_alloc_msg_cgx_mac_addr_del(&pfvf->mbox);
+       if (!req) {
+               mutex_unlock(&pfvf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       req->index = dmac_index;
+
+       err = otx2_sync_mbox_msg(&pfvf->mbox);
+       mutex_unlock(&pfvf->mbox.lock);
+
+       return err;
+}
+
+static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf)
+{
+       struct msg_req *req;
+       int err;
+
+       mutex_lock(&pf->mbox.lock);
+       req = otx2_mbox_alloc_msg_cgx_mac_addr_reset(&pf->mbox);
+       if (!req) {
+               mutex_unlock(&pf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       err = otx2_sync_mbox_msg(&pf->mbox);
+
+       mutex_unlock(&pf->mbox.lock);
+       return err;
+}
+
+int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac,
+                       u8 bit_pos)
+{
+       u8 dmacindex = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
+
+       if (ether_addr_equal(mac, pf->netdev->dev_addr))
+               return otx2_dmacflt_remove_pfmac(pf);
+       else
+               return otx2_dmacflt_do_remove(pf, mac, dmacindex);
+}
+
+/* CGX/RPM blocks support max unicast entries of 32.
+ * on typical configuration MAC block associated
+ * with 4 lmacs, each lmac will have 8 dmac entries
+ */
+int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf)
+{
+       struct cgx_max_dmac_entries_get_rsp *rsp;
+       struct msg_req *msg;
+       int err;
+
+       mutex_lock(&pf->mbox.lock);
+       msg = otx2_mbox_alloc_msg_cgx_mac_max_entries_get(&pf->mbox);
+
+       if (!msg) {
+               mutex_unlock(&pf->mbox.lock);
+               return -ENOMEM;
+       }
+
+       err = otx2_sync_mbox_msg(&pf->mbox);
+       if (err)
+               goto out;
+
+       rsp = (struct cgx_max_dmac_entries_get_rsp *)
+                    otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &msg->hdr);
+       pf->flow_cfg->dmacflt_max_flows = rsp->max_dmac_filters;
+
+out:
+       mutex_unlock(&pf->mbox.lock);
+       return err;
+}
+
+int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos)
+{
+       struct cgx_mac_addr_update_req *req;
+       int rc;
+
+       mutex_lock(&pf->mbox.lock);
+
+       req = otx2_mbox_alloc_msg_cgx_mac_addr_update(&pf->mbox);
+
+       if (!req) {
+               mutex_unlock(&pf->mbox.lock);
+               rc = -ENOMEM;
+       }
+
+       ether_addr_copy(req->mac_addr, mac);
+       req->index = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
+       rc = otx2_sync_mbox_msg(&pf->mbox);
+
+       mutex_unlock(&pf->mbox.lock);
+       return rc;
+}
index 8c97106bdd1cf89f6477c9658acea512205c7fb4..4d9de525802d0060b1b5b5f7f57ea1b219123bc6 100644 (file)
@@ -18,6 +18,12 @@ struct otx2_flow {
        bool is_vf;
        u8 rss_ctx_id;
        int vf;
+       bool dmac_filter;
+};
+
+enum dmac_req {
+       DMAC_ADDR_UPDATE,
+       DMAC_ADDR_DEL
 };
 
 static void otx2_clear_ntuple_flow_info(struct otx2_nic *pfvf, struct otx2_flow_config *flow_cfg)
@@ -219,6 +225,22 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
        if (!pf->mac_table)
                return -ENOMEM;
 
+       otx2_dmacflt_get_max_cnt(pf);
+
+       /* DMAC filters are not allocated */
+       if (!pf->flow_cfg->dmacflt_max_flows)
+               return 0;
+
+       pf->flow_cfg->bmap_to_dmacindex =
+                       devm_kzalloc(pf->dev, sizeof(u8) *
+                                    pf->flow_cfg->dmacflt_max_flows,
+                                    GFP_KERNEL);
+
+       if (!pf->flow_cfg->bmap_to_dmacindex)
+               return -ENOMEM;
+
+       pf->flags |= OTX2_FLAG_DMACFLTR_SUPPORT;
+
        return 0;
 }
 
@@ -280,6 +302,12 @@ int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
 {
        struct otx2_nic *pf = netdev_priv(netdev);
 
+       if (bitmap_weight(&pf->flow_cfg->dmacflt_bmap,
+                         pf->flow_cfg->dmacflt_max_flows))
+               netdev_warn(netdev,
+                           "Add %pM to CGX/RPM DMAC filters list as well\n",
+                           mac);
+
        return otx2_do_add_macfilter(pf, mac);
 }
 
@@ -351,12 +379,22 @@ static void otx2_add_flow_to_list(struct otx2_nic *pfvf, struct otx2_flow *flow)
        list_add(&flow->list, head);
 }
 
+static int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
+{
+       if (flow_cfg->nr_flows == flow_cfg->ntuple_max_flows ||
+           bitmap_weight(&flow_cfg->dmacflt_bmap,
+                         flow_cfg->dmacflt_max_flows))
+               return flow_cfg->ntuple_max_flows + flow_cfg->dmacflt_max_flows;
+       else
+               return flow_cfg->ntuple_max_flows;
+}
+
 int otx2_get_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
                  u32 location)
 {
        struct otx2_flow *iter;
 
-       if (location >= pfvf->flow_cfg->ntuple_max_flows)
+       if (location >= otx2_get_maxflows(pfvf->flow_cfg))
                return -EINVAL;
 
        list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
@@ -378,7 +416,7 @@ int otx2_get_all_flows(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc,
        int idx = 0;
        int err = 0;
 
-       nfc->data = pfvf->flow_cfg->ntuple_max_flows;
+       nfc->data = otx2_get_maxflows(pfvf->flow_cfg);
        while ((!err || err == -ENOENT) && idx < rule_cnt) {
                err = otx2_get_flow(pfvf, nfc, location);
                if (!err)
@@ -760,6 +798,32 @@ int otx2_prepare_flow_request(struct ethtool_rx_flow_spec *fsp,
        return 0;
 }
 
+static int otx2_is_flow_rule_dmacfilter(struct otx2_nic *pfvf,
+                                       struct ethtool_rx_flow_spec *fsp)
+{
+       struct ethhdr *eth_mask = &fsp->m_u.ether_spec;
+       struct ethhdr *eth_hdr = &fsp->h_u.ether_spec;
+       u64 ring_cookie = fsp->ring_cookie;
+       u32 flow_type;
+
+       if (!(pfvf->flags & OTX2_FLAG_DMACFLTR_SUPPORT))
+               return false;
+
+       flow_type = fsp->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS);
+
+       /* CGX/RPM block dmac filtering configured for white listing
+        * check for action other than DROP
+        */
+       if (flow_type == ETHER_FLOW && ring_cookie != RX_CLS_FLOW_DISC &&
+           !ethtool_get_flow_spec_ring_vf(ring_cookie)) {
+               if (is_zero_ether_addr(eth_mask->h_dest) &&
+                   is_valid_ether_addr(eth_hdr->h_dest))
+                       return true;
+       }
+
+       return false;
+}
+
 static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
 {
        u64 ring_cookie = flow->flow_spec.ring_cookie;
@@ -818,14 +882,46 @@ static int otx2_add_flow_msg(struct otx2_nic *pfvf, struct otx2_flow *flow)
        return err;
 }
 
+static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf,
+                                   struct otx2_flow *flow)
+{
+       struct otx2_flow *pf_mac;
+       struct ethhdr *eth_hdr;
+
+       pf_mac = kzalloc(sizeof(*pf_mac), GFP_KERNEL);
+       if (!pf_mac)
+               return -ENOMEM;
+
+       pf_mac->entry = 0;
+       pf_mac->dmac_filter = true;
+       pf_mac->location = pfvf->flow_cfg->ntuple_max_flows;
+       memcpy(&pf_mac->flow_spec, &flow->flow_spec,
+              sizeof(struct ethtool_rx_flow_spec));
+       pf_mac->flow_spec.location = pf_mac->location;
+
+       /* Copy PF mac address */
+       eth_hdr = &pf_mac->flow_spec.h_u.ether_spec;
+       ether_addr_copy(eth_hdr->h_dest, pfvf->netdev->dev_addr);
+
+       /* Install DMAC filter with PF mac address */
+       otx2_dmacflt_add(pfvf, eth_hdr->h_dest, 0);
+
+       otx2_add_flow_to_list(pfvf, pf_mac);
+       pfvf->flow_cfg->nr_flows++;
+       set_bit(0, &pfvf->flow_cfg->dmacflt_bmap);
+
+       return 0;
+}
+
 int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
 {
        struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
        struct ethtool_rx_flow_spec *fsp = &nfc->fs;
        struct otx2_flow *flow;
+       struct ethhdr *eth_hdr;
        bool new = false;
+       int err = 0;
        u32 ring;
-       int err;
 
        ring = ethtool_get_flow_spec_ring(fsp->ring_cookie);
        if (!(pfvf->flags & OTX2_FLAG_NTUPLE_SUPPORT))
@@ -834,16 +930,15 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
        if (ring >= pfvf->hw.rx_queues && fsp->ring_cookie != RX_CLS_FLOW_DISC)
                return -EINVAL;
 
-       if (fsp->location >= flow_cfg->ntuple_max_flows)
+       if (fsp->location >= otx2_get_maxflows(flow_cfg))
                return -EINVAL;
 
        flow = otx2_find_flow(pfvf, fsp->location);
        if (!flow) {
-               flow = kzalloc(sizeof(*flow), GFP_ATOMIC);
+               flow = kzalloc(sizeof(*flow), GFP_KERNEL);
                if (!flow)
                        return -ENOMEM;
                flow->location = fsp->location;
-               flow->entry = flow_cfg->flow_ent[flow->location];
                new = true;
        }
        /* struct copy */
@@ -852,7 +947,54 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
        if (fsp->flow_type & FLOW_RSS)
                flow->rss_ctx_id = nfc->rss_context;
 
-       err = otx2_add_flow_msg(pfvf, flow);
+       if (otx2_is_flow_rule_dmacfilter(pfvf, &flow->flow_spec)) {
+               eth_hdr = &flow->flow_spec.h_u.ether_spec;
+
+               /* Sync dmac filter table with updated fields */
+               if (flow->dmac_filter)
+                       return otx2_dmacflt_update(pfvf, eth_hdr->h_dest,
+                                                  flow->entry);
+
+               if (bitmap_full(&flow_cfg->dmacflt_bmap,
+                               flow_cfg->dmacflt_max_flows)) {
+                       netdev_warn(pfvf->netdev,
+                                   "Can't insert the rule %d as max allowed dmac filters are %d\n",
+                                   flow->location +
+                                   flow_cfg->dmacflt_max_flows,
+                                   flow_cfg->dmacflt_max_flows);
+                       err = -EINVAL;
+                       if (new)
+                               kfree(flow);
+                       return err;
+               }
+
+               /* Install PF mac address to DMAC filter list */
+               if (!test_bit(0, &flow_cfg->dmacflt_bmap))
+                       otx2_add_flow_with_pfmac(pfvf, flow);
+
+               flow->dmac_filter = true;
+               flow->entry = find_first_zero_bit(&flow_cfg->dmacflt_bmap,
+                                                 flow_cfg->dmacflt_max_flows);
+               fsp->location = flow_cfg->ntuple_max_flows + flow->entry;
+               flow->flow_spec.location = fsp->location;
+               flow->location = fsp->location;
+
+               set_bit(flow->entry, &flow_cfg->dmacflt_bmap);
+               otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry);
+
+       } else {
+               if (flow->location >= pfvf->flow_cfg->ntuple_max_flows) {
+                       netdev_warn(pfvf->netdev,
+                                   "Can't insert non dmac ntuple rule at %d, allowed range %d-0\n",
+                                   flow->location,
+                                   flow_cfg->ntuple_max_flows - 1);
+                       err = -EINVAL;
+               } else {
+                       flow->entry = flow_cfg->flow_ent[flow->location];
+                       err = otx2_add_flow_msg(pfvf, flow);
+               }
+       }
+
        if (err) {
                if (new)
                        kfree(flow);
@@ -890,20 +1032,70 @@ static int otx2_remove_flow_msg(struct otx2_nic *pfvf, u16 entry, bool all)
        return err;
 }
 
+static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req)
+{
+       struct otx2_flow *iter;
+       struct ethhdr *eth_hdr;
+       bool found = false;
+
+       list_for_each_entry(iter, &pfvf->flow_cfg->flow_list, list) {
+               if (iter->dmac_filter && iter->entry == 0) {
+                       eth_hdr = &iter->flow_spec.h_u.ether_spec;
+                       if (req == DMAC_ADDR_DEL) {
+                               otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
+                                                   0);
+                               clear_bit(0, &pfvf->flow_cfg->dmacflt_bmap);
+                               found = true;
+                       } else {
+                               ether_addr_copy(eth_hdr->h_dest,
+                                               pfvf->netdev->dev_addr);
+                               otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0);
+                       }
+                       break;
+               }
+       }
+
+       if (found) {
+               list_del(&iter->list);
+               kfree(iter);
+               pfvf->flow_cfg->nr_flows--;
+       }
+}
+
 int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
 {
        struct otx2_flow_config *flow_cfg = pfvf->flow_cfg;
        struct otx2_flow *flow;
        int err;
 
-       if (location >= flow_cfg->ntuple_max_flows)
+       if (location >= otx2_get_maxflows(flow_cfg))
                return -EINVAL;
 
        flow = otx2_find_flow(pfvf, location);
        if (!flow)
                return -ENOENT;
 
-       err = otx2_remove_flow_msg(pfvf, flow->entry, false);
+       if (flow->dmac_filter) {
+               struct ethhdr *eth_hdr = &flow->flow_spec.h_u.ether_spec;
+
+               /* user not allowed to remove dmac filter with interface mac */
+               if (ether_addr_equal(pfvf->netdev->dev_addr, eth_hdr->h_dest))
+                       return -EPERM;
+
+               err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
+                                         flow->entry);
+               clear_bit(flow->entry, &flow_cfg->dmacflt_bmap);
+               /* If all dmac filters are removed delete macfilter with
+                * interface mac address and configure CGX/RPM block in
+                * promiscuous mode
+                */
+               if (bitmap_weight(&flow_cfg->dmacflt_bmap,
+                                 flow_cfg->dmacflt_max_flows) == 1)
+                       otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL);
+       } else {
+               err = otx2_remove_flow_msg(pfvf, flow->entry, false);
+       }
+
        if (err)
                return err;
 
@@ -1100,3 +1292,22 @@ int otx2_enable_rxvlan(struct otx2_nic *pf, bool enable)
        mutex_unlock(&pf->mbox.lock);
        return rsp_hdr->rc;
 }
+
+void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf)
+{
+       struct otx2_flow *iter;
+       struct ethhdr *eth_hdr;
+
+       list_for_each_entry(iter, &pf->flow_cfg->flow_list, list) {
+               if (iter->dmac_filter) {
+                       eth_hdr = &iter->flow_spec.h_u.ether_spec;
+                       otx2_dmacflt_add(pf, eth_hdr->h_dest,
+                                        iter->entry);
+               }
+       }
+}
+
+void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf)
+{
+       otx2_update_rem_pfmac(pfvf, DMAC_ADDR_UPDATE);
+}
index 088c28df849d090b4ddf51baebf4b2ac1805cb35..f300b807a85bf739743703358a0b468471f8f16d 100644 (file)
@@ -1110,6 +1110,11 @@ static int otx2_cgx_config_loopback(struct otx2_nic *pf, bool enable)
        struct msg_req *msg;
        int err;
 
+       if (enable && bitmap_weight(&pf->flow_cfg->dmacflt_bmap,
+                                   pf->flow_cfg->dmacflt_max_flows))
+               netdev_warn(pf->netdev,
+                           "CGX/RPM internal loopback might not work as DMAC filters are active\n");
+
        mutex_lock(&pf->mbox.lock);
        if (enable)
                msg = otx2_mbox_alloc_msg_cgx_intlbk_enable(&pf->mbox);
@@ -1644,6 +1649,10 @@ int otx2_open(struct net_device *netdev)
        /* Restore pause frame settings */
        otx2_config_pause_frm(pf);
 
+       /* Install DMAC Filters */
+       if (pf->flags & OTX2_FLAG_DMACFLTR_SUPPORT)
+               otx2_dmacflt_reinstall_flows(pf);
+
        err = otx2_rxtx_enable(pf, true);
        if (err)
                goto err_tx_stop_queues;