Commit fa5e0ccb authored by Ratheesh Kannoth's avatar Ratheesh Kannoth Committed by Jakub Kicinski

octeontx2-pf: Add support for exact match table.

NPC exact match table can support more entries than RPM
dmac filters. This requires field size of DMAC filter count
and index to be increased.
Signed-off-by: default avatarRatheesh Kannoth <rkannoth@marvell.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent d6c9784b
...@@ -314,8 +314,8 @@ struct otx2_flow_config { ...@@ -314,8 +314,8 @@ struct otx2_flow_config {
#define OTX2_VF_VLAN_TX_INDEX 1 #define OTX2_VF_VLAN_TX_INDEX 1
u16 max_flows; u16 max_flows;
u8 dmacflt_max_flows; u8 dmacflt_max_flows;
u8 *bmap_to_dmacindex; u32 *bmap_to_dmacindex;
unsigned long dmacflt_bmap; unsigned long *dmacflt_bmap;
struct list_head flow_list; struct list_head flow_list;
}; };
...@@ -895,9 +895,9 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type, ...@@ -895,9 +895,9 @@ int otx2_setup_tc(struct net_device *netdev, enum tc_setup_type type,
int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic); int otx2_tc_alloc_ent_bitmap(struct otx2_nic *nic);
/* CGX/RPM DMAC filters support */ /* CGX/RPM DMAC filters support */
int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf); 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_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos);
int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac, u8 bit_pos); int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac, u32 bit_pos);
int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos); int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos);
void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf); void otx2_dmacflt_reinstall_flows(struct otx2_nic *pf);
void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf); void otx2_dmacflt_update_pfmac_flow(struct otx2_nic *pfvf);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
#include "otx2_common.h" #include "otx2_common.h"
static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac, static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
u8 *dmac_index) u32 *dmac_index)
{ {
struct cgx_mac_addr_add_req *req; struct cgx_mac_addr_add_req *req;
struct cgx_mac_addr_add_rsp *rsp; struct cgx_mac_addr_add_rsp *rsp;
...@@ -35,9 +35,10 @@ static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac, ...@@ -35,9 +35,10 @@ static int otx2_dmacflt_do_add(struct otx2_nic *pf, const u8 *mac,
return err; return err;
} }
static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf) static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf, u32 *dmac_index)
{ {
struct cgx_mac_addr_set_or_get *req; struct cgx_mac_addr_set_or_get *req;
struct cgx_mac_addr_set_or_get *rsp;
int err; int err;
mutex_lock(&pf->mbox.lock); mutex_lock(&pf->mbox.lock);
...@@ -48,16 +49,24 @@ static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf) ...@@ -48,16 +49,24 @@ static int otx2_dmacflt_add_pfmac(struct otx2_nic *pf)
return -ENOMEM; return -ENOMEM;
} }
req->index = *dmac_index;
ether_addr_copy(req->mac_addr, pf->netdev->dev_addr); ether_addr_copy(req->mac_addr, pf->netdev->dev_addr);
err = otx2_sync_mbox_msg(&pf->mbox); err = otx2_sync_mbox_msg(&pf->mbox);
if (!err) {
rsp = (struct cgx_mac_addr_set_or_get *)
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
*dmac_index = rsp->index;
}
mutex_unlock(&pf->mbox.lock); mutex_unlock(&pf->mbox.lock);
return err; return err;
} }
int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos) int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u32 bit_pos)
{ {
u8 *dmacindex; u32 *dmacindex;
/* Store dmacindex returned by CGX/RPM driver which will /* Store dmacindex returned by CGX/RPM driver which will
* be used for macaddr update/remove * be used for macaddr update/remove
...@@ -65,13 +74,13 @@ int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos) ...@@ -65,13 +74,13 @@ int otx2_dmacflt_add(struct otx2_nic *pf, const u8 *mac, u8 bit_pos)
dmacindex = &pf->flow_cfg->bmap_to_dmacindex[bit_pos]; dmacindex = &pf->flow_cfg->bmap_to_dmacindex[bit_pos];
if (ether_addr_equal(mac, pf->netdev->dev_addr)) if (ether_addr_equal(mac, pf->netdev->dev_addr))
return otx2_dmacflt_add_pfmac(pf); return otx2_dmacflt_add_pfmac(pf, dmacindex);
else else
return otx2_dmacflt_do_add(pf, mac, dmacindex); return otx2_dmacflt_do_add(pf, mac, dmacindex);
} }
static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac, static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac,
u8 dmac_index) u32 dmac_index)
{ {
struct cgx_mac_addr_del_req *req; struct cgx_mac_addr_del_req *req;
int err; int err;
...@@ -91,7 +100,7 @@ static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac, ...@@ -91,7 +100,7 @@ static int otx2_dmacflt_do_remove(struct otx2_nic *pfvf, const u8 *mac,
return err; return err;
} }
static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf) static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf, u32 dmac_index)
{ {
struct cgx_mac_addr_reset_req *req; struct cgx_mac_addr_reset_req *req;
int err; int err;
...@@ -102,6 +111,7 @@ static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf) ...@@ -102,6 +111,7 @@ static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf)
mutex_unlock(&pf->mbox.lock); mutex_unlock(&pf->mbox.lock);
return -ENOMEM; return -ENOMEM;
} }
req->index = dmac_index;
err = otx2_sync_mbox_msg(&pf->mbox); err = otx2_sync_mbox_msg(&pf->mbox);
...@@ -110,12 +120,12 @@ static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf) ...@@ -110,12 +120,12 @@ static int otx2_dmacflt_remove_pfmac(struct otx2_nic *pf)
} }
int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac, int otx2_dmacflt_remove(struct otx2_nic *pf, const u8 *mac,
u8 bit_pos) u32 bit_pos)
{ {
u8 dmacindex = pf->flow_cfg->bmap_to_dmacindex[bit_pos]; u32 dmacindex = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
if (ether_addr_equal(mac, pf->netdev->dev_addr)) if (ether_addr_equal(mac, pf->netdev->dev_addr))
return otx2_dmacflt_remove_pfmac(pf); return otx2_dmacflt_remove_pfmac(pf, dmacindex);
else else
return otx2_dmacflt_do_remove(pf, mac, dmacindex); return otx2_dmacflt_do_remove(pf, mac, dmacindex);
} }
...@@ -151,9 +161,10 @@ int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf) ...@@ -151,9 +161,10 @@ int otx2_dmacflt_get_max_cnt(struct otx2_nic *pf)
return err; return err;
} }
int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos) int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u32 bit_pos)
{ {
struct cgx_mac_addr_update_req *req; struct cgx_mac_addr_update_req *req;
struct cgx_mac_addr_update_rsp *rsp;
int rc; int rc;
mutex_lock(&pf->mbox.lock); mutex_lock(&pf->mbox.lock);
...@@ -167,8 +178,19 @@ int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos) ...@@ -167,8 +178,19 @@ int otx2_dmacflt_update(struct otx2_nic *pf, u8 *mac, u8 bit_pos)
ether_addr_copy(req->mac_addr, mac); ether_addr_copy(req->mac_addr, mac);
req->index = pf->flow_cfg->bmap_to_dmacindex[bit_pos]; req->index = pf->flow_cfg->bmap_to_dmacindex[bit_pos];
/* check the response and change index */
rc = otx2_sync_mbox_msg(&pf->mbox); rc = otx2_sync_mbox_msg(&pf->mbox);
if (rc)
goto out;
rsp = (struct cgx_mac_addr_update_rsp *)
otx2_mbox_get_rsp(&pf->mbox.mbox, 0, &req->hdr);
pf->flow_cfg->bmap_to_dmacindex[bit_pos] = rsp->index;
out:
mutex_unlock(&pf->mbox.lock); mutex_unlock(&pf->mbox.lock);
return rc; return rc;
} }
...@@ -18,7 +18,7 @@ struct otx2_flow { ...@@ -18,7 +18,7 @@ struct otx2_flow {
struct ethtool_rx_flow_spec flow_spec; struct ethtool_rx_flow_spec flow_spec;
struct list_head list; struct list_head list;
u32 location; u32 location;
u16 entry; u32 entry;
bool is_vf; bool is_vf;
u8 rss_ctx_id; u8 rss_ctx_id;
#define DMAC_FILTER_RULE BIT(0) #define DMAC_FILTER_RULE BIT(0)
...@@ -232,6 +232,9 @@ static int otx2_mcam_entry_init(struct otx2_nic *pfvf) ...@@ -232,6 +232,9 @@ static int otx2_mcam_entry_init(struct otx2_nic *pfvf)
return 0; return 0;
} }
/* TODO : revisit on size */
#define OTX2_DMAC_FLTR_BITMAP_SZ (4 * 2048 + 32)
int otx2vf_mcam_flow_init(struct otx2_nic *pfvf) int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
{ {
struct otx2_flow_config *flow_cfg; struct otx2_flow_config *flow_cfg;
...@@ -242,6 +245,12 @@ int otx2vf_mcam_flow_init(struct otx2_nic *pfvf) ...@@ -242,6 +245,12 @@ int otx2vf_mcam_flow_init(struct otx2_nic *pfvf)
if (!pfvf->flow_cfg) if (!pfvf->flow_cfg)
return -ENOMEM; return -ENOMEM;
pfvf->flow_cfg->dmacflt_bmap = devm_kcalloc(pfvf->dev,
BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
sizeof(long), GFP_KERNEL);
if (!pfvf->flow_cfg->dmacflt_bmap)
return -ENOMEM;
flow_cfg = pfvf->flow_cfg; flow_cfg = pfvf->flow_cfg;
INIT_LIST_HEAD(&flow_cfg->flow_list); INIT_LIST_HEAD(&flow_cfg->flow_list);
flow_cfg->max_flows = 0; flow_cfg->max_flows = 0;
...@@ -259,6 +268,12 @@ int otx2_mcam_flow_init(struct otx2_nic *pf) ...@@ -259,6 +268,12 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
if (!pf->flow_cfg) if (!pf->flow_cfg)
return -ENOMEM; return -ENOMEM;
pf->flow_cfg->dmacflt_bmap = devm_kcalloc(pf->dev,
BITS_TO_LONGS(OTX2_DMAC_FLTR_BITMAP_SZ),
sizeof(long), GFP_KERNEL);
if (!pf->flow_cfg->dmacflt_bmap)
return -ENOMEM;
INIT_LIST_HEAD(&pf->flow_cfg->flow_list); INIT_LIST_HEAD(&pf->flow_cfg->flow_list);
/* Allocate bare minimum number of MCAM entries needed for /* Allocate bare minimum number of MCAM entries needed for
...@@ -284,7 +299,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf) ...@@ -284,7 +299,7 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
return 0; return 0;
pf->flow_cfg->bmap_to_dmacindex = pf->flow_cfg->bmap_to_dmacindex =
devm_kzalloc(pf->dev, sizeof(u8) * devm_kzalloc(pf->dev, sizeof(u32) *
pf->flow_cfg->dmacflt_max_flows, pf->flow_cfg->dmacflt_max_flows,
GFP_KERNEL); GFP_KERNEL);
...@@ -355,7 +370,7 @@ int otx2_add_macfilter(struct net_device *netdev, const u8 *mac) ...@@ -355,7 +370,7 @@ int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
{ {
struct otx2_nic *pf = netdev_priv(netdev); struct otx2_nic *pf = netdev_priv(netdev);
if (!bitmap_empty(&pf->flow_cfg->dmacflt_bmap, if (!bitmap_empty(pf->flow_cfg->dmacflt_bmap,
pf->flow_cfg->dmacflt_max_flows)) pf->flow_cfg->dmacflt_max_flows))
netdev_warn(netdev, netdev_warn(netdev,
"Add %pM to CGX/RPM DMAC filters list as well\n", "Add %pM to CGX/RPM DMAC filters list as well\n",
...@@ -438,7 +453,7 @@ int otx2_get_maxflows(struct otx2_flow_config *flow_cfg) ...@@ -438,7 +453,7 @@ int otx2_get_maxflows(struct otx2_flow_config *flow_cfg)
return 0; return 0;
if (flow_cfg->nr_flows == flow_cfg->max_flows || if (flow_cfg->nr_flows == flow_cfg->max_flows ||
!bitmap_empty(&flow_cfg->dmacflt_bmap, !bitmap_empty(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows)) flow_cfg->dmacflt_max_flows))
return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows; return flow_cfg->max_flows + flow_cfg->dmacflt_max_flows;
else else
...@@ -1010,7 +1025,7 @@ static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf, ...@@ -1010,7 +1025,7 @@ static int otx2_add_flow_with_pfmac(struct otx2_nic *pfvf,
otx2_add_flow_to_list(pfvf, pf_mac); otx2_add_flow_to_list(pfvf, pf_mac);
pfvf->flow_cfg->nr_flows++; pfvf->flow_cfg->nr_flows++;
set_bit(0, &pfvf->flow_cfg->dmacflt_bmap); set_bit(0, pfvf->flow_cfg->dmacflt_bmap);
return 0; return 0;
} }
...@@ -1064,7 +1079,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc) ...@@ -1064,7 +1079,7 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
return otx2_dmacflt_update(pfvf, eth_hdr->h_dest, return otx2_dmacflt_update(pfvf, eth_hdr->h_dest,
flow->entry); flow->entry);
if (bitmap_full(&flow_cfg->dmacflt_bmap, if (bitmap_full(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows)) { flow_cfg->dmacflt_max_flows)) {
netdev_warn(pfvf->netdev, netdev_warn(pfvf->netdev,
"Can't insert the rule %d as max allowed dmac filters are %d\n", "Can't insert the rule %d as max allowed dmac filters are %d\n",
...@@ -1078,17 +1093,17 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc) ...@@ -1078,17 +1093,17 @@ int otx2_add_flow(struct otx2_nic *pfvf, struct ethtool_rxnfc *nfc)
} }
/* Install PF mac address to DMAC filter list */ /* Install PF mac address to DMAC filter list */
if (!test_bit(0, &flow_cfg->dmacflt_bmap)) if (!test_bit(0, flow_cfg->dmacflt_bmap))
otx2_add_flow_with_pfmac(pfvf, flow); otx2_add_flow_with_pfmac(pfvf, flow);
flow->rule_type |= DMAC_FILTER_RULE; flow->rule_type |= DMAC_FILTER_RULE;
flow->entry = find_first_zero_bit(&flow_cfg->dmacflt_bmap, flow->entry = find_first_zero_bit(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows); flow_cfg->dmacflt_max_flows);
fsp->location = flow_cfg->max_flows + flow->entry; fsp->location = flow_cfg->max_flows + flow->entry;
flow->flow_spec.location = fsp->location; flow->flow_spec.location = fsp->location;
flow->location = fsp->location; flow->location = fsp->location;
set_bit(flow->entry, &flow_cfg->dmacflt_bmap); set_bit(flow->entry, flow_cfg->dmacflt_bmap);
otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry); otx2_dmacflt_add(pfvf, eth_hdr->h_dest, flow->entry);
} else { } else {
...@@ -1154,11 +1169,12 @@ static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req) ...@@ -1154,11 +1169,12 @@ static void otx2_update_rem_pfmac(struct otx2_nic *pfvf, int req)
if (req == DMAC_ADDR_DEL) { if (req == DMAC_ADDR_DEL) {
otx2_dmacflt_remove(pfvf, eth_hdr->h_dest, otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
0); 0);
clear_bit(0, &pfvf->flow_cfg->dmacflt_bmap); clear_bit(0, pfvf->flow_cfg->dmacflt_bmap);
found = true; found = true;
} else { } else {
ether_addr_copy(eth_hdr->h_dest, ether_addr_copy(eth_hdr->h_dest,
pfvf->netdev->dev_addr); pfvf->netdev->dev_addr);
otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0); otx2_dmacflt_update(pfvf, eth_hdr->h_dest, 0);
} }
break; break;
...@@ -1194,12 +1210,12 @@ int otx2_remove_flow(struct otx2_nic *pfvf, u32 location) ...@@ -1194,12 +1210,12 @@ int otx2_remove_flow(struct otx2_nic *pfvf, u32 location)
err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest, err = otx2_dmacflt_remove(pfvf, eth_hdr->h_dest,
flow->entry); flow->entry);
clear_bit(flow->entry, &flow_cfg->dmacflt_bmap); clear_bit(flow->entry, flow_cfg->dmacflt_bmap);
/* If all dmac filters are removed delete macfilter with /* If all dmac filters are removed delete macfilter with
* interface mac address and configure CGX/RPM block in * interface mac address and configure CGX/RPM block in
* promiscuous mode * promiscuous mode
*/ */
if (bitmap_weight(&flow_cfg->dmacflt_bmap, if (bitmap_weight(flow_cfg->dmacflt_bmap,
flow_cfg->dmacflt_max_flows) == 1) flow_cfg->dmacflt_max_flows) == 1)
otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL); otx2_update_rem_pfmac(pfvf, DMAC_ADDR_DEL);
} else { } else {
......
...@@ -1120,7 +1120,7 @@ static int otx2_cgx_config_loopback(struct otx2_nic *pf, bool enable) ...@@ -1120,7 +1120,7 @@ static int otx2_cgx_config_loopback(struct otx2_nic *pf, bool enable)
struct msg_req *msg; struct msg_req *msg;
int err; int err;
if (enable && !bitmap_empty(&pf->flow_cfg->dmacflt_bmap, if (enable && !bitmap_empty(pf->flow_cfg->dmacflt_bmap,
pf->flow_cfg->dmacflt_max_flows)) pf->flow_cfg->dmacflt_max_flows))
netdev_warn(pf->netdev, netdev_warn(pf->netdev,
"CGX/RPM internal loopback might not work as DMAC filters are active\n"); "CGX/RPM internal loopback might not work as DMAC filters are active\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment