mirror of
https://github.com/edk2-porting/linux-next.git
synced 2025-01-07 21:24:00 +08:00
octeontx2-pf: Add support for unicast MAC address filtering
Add unicast MAC address filtering support using install flow message. Total of 8 MCAM entries are allocated for adding unicast mac filtering rules. If the MCAM allocation fails, the unicast filtering support will not be advertised. 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>
This commit is contained in:
parent
f0a1913f8a
commit
63ee51575f
@ -229,12 +229,21 @@ struct otx2_ptp {
|
||||
|
||||
#define OTX2_HW_TIMESTAMP_LEN 8
|
||||
|
||||
struct otx2_mac_table {
|
||||
u8 addr[ETH_ALEN];
|
||||
u16 mcam_entry;
|
||||
bool inuse;
|
||||
};
|
||||
|
||||
struct otx2_flow_config {
|
||||
u16 entry[NPC_MAX_NONCONTIG_ENTRIES];
|
||||
u32 nr_flows;
|
||||
#define OTX2_MAX_NTUPLE_FLOWS 32
|
||||
#define OTX2_MCAM_COUNT OTX2_MAX_NTUPLE_FLOWS
|
||||
#define OTX2_MAX_UNICAST_FLOWS 8
|
||||
#define OTX2_MCAM_COUNT (OTX2_MAX_NTUPLE_FLOWS + \
|
||||
OTX2_MAX_UNICAST_FLOWS)
|
||||
u32 ntuple_offset;
|
||||
u32 unicast_offset;
|
||||
u32 ntuple_max_flows;
|
||||
struct list_head flow_list;
|
||||
};
|
||||
@ -251,6 +260,7 @@ struct otx2_nic {
|
||||
#define OTX2_FLAG_INTF_DOWN BIT_ULL(2)
|
||||
#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_PAUSE_ENABLED BIT_ULL(9)
|
||||
#define OTX2_FLAG_TX_PAUSE_ENABLED BIT_ULL(10)
|
||||
u64 flags;
|
||||
@ -279,6 +289,7 @@ struct otx2_nic {
|
||||
struct refill_work *refill_wrk;
|
||||
struct workqueue_struct *otx2_wq;
|
||||
struct work_struct rx_mode_work;
|
||||
struct otx2_mac_table *mac_table;
|
||||
|
||||
/* Ethtool stuff */
|
||||
u32 msg_enable;
|
||||
@ -674,5 +685,7 @@ int otx2_add_flow(struct otx2_nic *pfvf,
|
||||
int otx2_remove_flow(struct otx2_nic *pfvf, u32 location);
|
||||
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);
|
||||
|
||||
#endif /* OTX2_COMMON_H */
|
||||
|
@ -46,14 +46,21 @@ int otx2_alloc_mcam_entries(struct otx2_nic *pfvf)
|
||||
rsp = (struct npc_mcam_alloc_entry_rsp *)otx2_mbox_get_rsp
|
||||
(&pfvf->mbox.mbox, 0, &req->hdr);
|
||||
|
||||
if (rsp->count != req->count)
|
||||
if (rsp->count != req->count) {
|
||||
netdev_info(pfvf->netdev,
|
||||
"Unable to allocate %d MCAM entries, got %d\n",
|
||||
req->count, rsp->count);
|
||||
|
||||
flow_cfg->ntuple_max_flows = rsp->count;
|
||||
flow_cfg->ntuple_offset = 0;
|
||||
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
|
||||
/* support only ntuples here */
|
||||
flow_cfg->ntuple_max_flows = rsp->count;
|
||||
flow_cfg->ntuple_offset = 0;
|
||||
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
|
||||
} else {
|
||||
flow_cfg->ntuple_offset = 0;
|
||||
flow_cfg->unicast_offset = flow_cfg->ntuple_offset +
|
||||
OTX2_MAX_NTUPLE_FLOWS;
|
||||
pfvf->flags |= OTX2_FLAG_NTUPLE_SUPPORT;
|
||||
pfvf->flags |= OTX2_FLAG_UCAST_FLTR_SUPPORT;
|
||||
}
|
||||
|
||||
for (i = 0; i < rsp->count; i++)
|
||||
flow_cfg->entry[i] = rsp->entry_list[i];
|
||||
@ -82,6 +89,11 @@ int otx2_mcam_flow_init(struct otx2_nic *pf)
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
pf->mac_table = devm_kzalloc(pf->dev, sizeof(struct otx2_mac_table)
|
||||
* OTX2_MAX_UNICAST_FLOWS, GFP_KERNEL);
|
||||
if (!pf->mac_table)
|
||||
return -ENOMEM;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -90,6 +102,104 @@ void otx2_mcam_flow_del(struct otx2_nic *pf)
|
||||
otx2_destroy_mcam_flows(pf);
|
||||
}
|
||||
|
||||
/* On success adds mcam entry
|
||||
* On failure enable promisous mode
|
||||
*/
|
||||
static int otx2_do_add_macfilter(struct otx2_nic *pf, const u8 *mac)
|
||||
{
|
||||
struct otx2_flow_config *flow_cfg = pf->flow_cfg;
|
||||
struct npc_install_flow_req *req;
|
||||
int err, i;
|
||||
|
||||
if (!(pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT))
|
||||
return -ENOMEM;
|
||||
|
||||
/* dont have free mcam entries or uc list is greater than alloted */
|
||||
if (netdev_uc_count(pf->netdev) > OTX2_MAX_UNICAST_FLOWS)
|
||||
return -ENOMEM;
|
||||
|
||||
mutex_lock(&pf->mbox.lock);
|
||||
req = otx2_mbox_alloc_msg_npc_install_flow(&pf->mbox);
|
||||
if (!req) {
|
||||
mutex_unlock(&pf->mbox.lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
/* unicast offset starts with 32 0..31 for ntuple */
|
||||
for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) {
|
||||
if (pf->mac_table[i].inuse)
|
||||
continue;
|
||||
ether_addr_copy(pf->mac_table[i].addr, mac);
|
||||
pf->mac_table[i].inuse = true;
|
||||
pf->mac_table[i].mcam_entry =
|
||||
flow_cfg->entry[i + flow_cfg->unicast_offset];
|
||||
req->entry = pf->mac_table[i].mcam_entry;
|
||||
break;
|
||||
}
|
||||
|
||||
ether_addr_copy(req->packet.dmac, mac);
|
||||
eth_broadcast_addr((u8 *)&req->mask.dmac);
|
||||
req->features = BIT_ULL(NPC_DMAC);
|
||||
req->channel = pf->hw.rx_chan_base;
|
||||
req->intf = NIX_INTF_RX;
|
||||
req->op = NIX_RX_ACTION_DEFAULT;
|
||||
req->set_cntr = 1;
|
||||
|
||||
err = otx2_sync_mbox_msg(&pf->mbox);
|
||||
mutex_unlock(&pf->mbox.lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int otx2_add_macfilter(struct net_device *netdev, const u8 *mac)
|
||||
{
|
||||
struct otx2_nic *pf = netdev_priv(netdev);
|
||||
|
||||
return otx2_do_add_macfilter(pf, mac);
|
||||
}
|
||||
|
||||
static bool otx2_get_mcamentry_for_mac(struct otx2_nic *pf, const u8 *mac,
|
||||
int *mcam_entry)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < OTX2_MAX_UNICAST_FLOWS; i++) {
|
||||
if (!pf->mac_table[i].inuse)
|
||||
continue;
|
||||
|
||||
if (ether_addr_equal(pf->mac_table[i].addr, mac)) {
|
||||
*mcam_entry = pf->mac_table[i].mcam_entry;
|
||||
pf->mac_table[i].inuse = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int otx2_del_macfilter(struct net_device *netdev, const u8 *mac)
|
||||
{
|
||||
struct otx2_nic *pf = netdev_priv(netdev);
|
||||
struct npc_delete_flow_req *req;
|
||||
int err, mcam_entry;
|
||||
|
||||
/* check does mcam entry exists for given mac */
|
||||
if (!otx2_get_mcamentry_for_mac(pf, mac, &mcam_entry))
|
||||
return 0;
|
||||
|
||||
mutex_lock(&pf->mbox.lock);
|
||||
req = otx2_mbox_alloc_msg_npc_delete_flow(&pf->mbox);
|
||||
if (!req) {
|
||||
mutex_unlock(&pf->mbox.lock);
|
||||
return -ENOMEM;
|
||||
}
|
||||
req->entry = mcam_entry;
|
||||
/* Send message to AF */
|
||||
err = otx2_sync_mbox_msg(&pf->mbox);
|
||||
mutex_unlock(&pf->mbox.lock);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct otx2_flow *otx2_find_flow(struct otx2_nic *pfvf, u32 location)
|
||||
{
|
||||
struct otx2_flow *iter;
|
||||
|
@ -1720,10 +1720,20 @@ static void otx2_do_set_rx_mode(struct work_struct *work)
|
||||
struct otx2_nic *pf = container_of(work, struct otx2_nic, rx_mode_work);
|
||||
struct net_device *netdev = pf->netdev;
|
||||
struct nix_rx_mode *req;
|
||||
bool promisc = false;
|
||||
|
||||
if (!(netdev->flags & IFF_UP))
|
||||
return;
|
||||
|
||||
if ((netdev->flags & IFF_PROMISC) ||
|
||||
(netdev_uc_count(netdev) > OTX2_MAX_UNICAST_FLOWS)) {
|
||||
promisc = true;
|
||||
}
|
||||
|
||||
/* Write unicast address to mcam entries or del from mcam */
|
||||
if (!promisc && netdev->priv_flags & IFF_UNICAST_FLT)
|
||||
__dev_uc_sync(netdev, otx2_add_macfilter, otx2_del_macfilter);
|
||||
|
||||
mutex_lock(&pf->mbox.lock);
|
||||
req = otx2_mbox_alloc_msg_nix_set_rx_mode(&pf->mbox);
|
||||
if (!req) {
|
||||
@ -1733,7 +1743,7 @@ static void otx2_do_set_rx_mode(struct work_struct *work)
|
||||
|
||||
req->mode = NIX_RX_MODE_UCAST;
|
||||
|
||||
if (netdev->flags & IFF_PROMISC)
|
||||
if (promisc)
|
||||
req->mode |= NIX_RX_MODE_PROMISC;
|
||||
else if (netdev->flags & (IFF_ALLMULTI | IFF_MULTICAST))
|
||||
req->mode |= NIX_RX_MODE_ALLMULTI;
|
||||
@ -2125,6 +2135,9 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||
if (pf->flags & OTX2_FLAG_NTUPLE_SUPPORT)
|
||||
netdev->hw_features |= NETIF_F_NTUPLE;
|
||||
|
||||
if (pf->flags & OTX2_FLAG_UCAST_FLTR_SUPPORT)
|
||||
netdev->priv_flags |= IFF_UNICAST_FLT;
|
||||
|
||||
netdev->gso_max_segs = OTX2_MAX_GSO_SEGS;
|
||||
netdev->watchdog_timeo = OTX2_TX_TIMEOUT;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user