Skip to content

Commit 1f6e77c

Browse files
Michael Chandavem330
authored andcommitted
bnxt_en: Add bnxt_l2_filter hash table.
The current driver only has an array of 4 additional L2 unicast addresses to support the netdev uc address list. Generalize and expand this infrastructure with an L2 address hash table so we can support an expanded list of unicast addresses (for bridges, macvlans, OVS, etc). The L2 hash table infrastructure will also allow more generalized n-tuple filter support. This patch creates the bnxt_l2_filter structure and the hash table. This L2 filter structure has the same bnxt_filter_base structure as used in the bnxt_ntuple_filter structure. All currently supported L2 filters will now have an entry in this new table. Note that L2 filters may be created for the VF. VF filters should not be freed when the PF goes down. Add some logic in bnxt_free_l2_filters() to allow keeping the VF filters or to free everything during rmmod. Reviewed-by: Vasundhara Volam <[email protected]> Reviewed-by: Andy Gospodarek <[email protected]> Reviewed-by: Pavan Chebbi <[email protected]> Signed-off-by: Michael Chan <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 992d38d commit 1f6e77c

File tree

2 files changed

+191
-14
lines changed

2 files changed

+191
-14
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 162 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -4789,7 +4789,7 @@ static void bnxt_clear_ring_indices(struct bnxt *bp)
47894789
}
47904790
}
47914791

4792-
static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool irq_reinit)
4792+
static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool all)
47934793
{
47944794
#ifdef CONFIG_RFS_ACCEL
47954795
int i;
@@ -4804,14 +4804,19 @@ static void bnxt_free_ntp_fltrs(struct bnxt *bp, bool irq_reinit)
48044804

48054805
head = &bp->ntp_fltr_hash_tbl[i];
48064806
hlist_for_each_entry_safe(fltr, tmp, head, base.hash) {
4807+
if (!all && (fltr->base.flags & BNXT_ACT_FUNC_DST))
4808+
continue;
48074809
hlist_del(&fltr->base.hash);
4810+
clear_bit(fltr->base.sw_id, bp->ntp_fltr_bmap);
4811+
bp->ntp_fltr_count--;
48084812
kfree(fltr);
48094813
}
48104814
}
4811-
if (irq_reinit) {
4812-
bitmap_free(bp->ntp_fltr_bmap);
4813-
bp->ntp_fltr_bmap = NULL;
4814-
}
4815+
if (!all)
4816+
return;
4817+
4818+
bitmap_free(bp->ntp_fltr_bmap);
4819+
bp->ntp_fltr_bmap = NULL;
48154820
bp->ntp_fltr_count = 0;
48164821
#endif
48174822
}
@@ -4821,7 +4826,7 @@ static int bnxt_alloc_ntp_fltrs(struct bnxt *bp)
48214826
#ifdef CONFIG_RFS_ACCEL
48224827
int i, rc = 0;
48234828

4824-
if (!(bp->flags & BNXT_FLAG_RFS))
4829+
if (!(bp->flags & BNXT_FLAG_RFS) || bp->ntp_fltr_bmap)
48254830
return 0;
48264831

48274832
for (i = 0; i < BNXT_NTP_FLTR_HASH_SIZE; i++)
@@ -4839,14 +4844,47 @@ static int bnxt_alloc_ntp_fltrs(struct bnxt *bp)
48394844
#endif
48404845
}
48414846

4847+
static void bnxt_free_l2_filters(struct bnxt *bp, bool all)
4848+
{
4849+
int i;
4850+
4851+
for (i = 0; i < BNXT_L2_FLTR_HASH_SIZE; i++) {
4852+
struct hlist_head *head;
4853+
struct hlist_node *tmp;
4854+
struct bnxt_l2_filter *fltr;
4855+
4856+
head = &bp->l2_fltr_hash_tbl[i];
4857+
hlist_for_each_entry_safe(fltr, tmp, head, base.hash) {
4858+
if (!all && (fltr->base.flags & BNXT_ACT_FUNC_DST))
4859+
continue;
4860+
hlist_del(&fltr->base.hash);
4861+
if (fltr->base.flags) {
4862+
clear_bit(fltr->base.sw_id, bp->ntp_fltr_bmap);
4863+
bp->ntp_fltr_count--;
4864+
}
4865+
kfree(fltr);
4866+
}
4867+
}
4868+
}
4869+
4870+
static void bnxt_init_l2_fltr_tbl(struct bnxt *bp)
4871+
{
4872+
int i;
4873+
4874+
for (i = 0; i < BNXT_L2_FLTR_HASH_SIZE; i++)
4875+
INIT_HLIST_HEAD(&bp->l2_fltr_hash_tbl[i]);
4876+
get_random_bytes(&bp->hash_seed, sizeof(bp->hash_seed));
4877+
}
4878+
48424879
static void bnxt_free_mem(struct bnxt *bp, bool irq_re_init)
48434880
{
48444881
bnxt_free_vnic_attributes(bp);
48454882
bnxt_free_tx_rings(bp);
48464883
bnxt_free_rx_rings(bp);
48474884
bnxt_free_cp_rings(bp);
48484885
bnxt_free_all_cp_arrays(bp);
4849-
bnxt_free_ntp_fltrs(bp, irq_re_init);
4886+
bnxt_free_ntp_fltrs(bp, false);
4887+
bnxt_free_l2_filters(bp, false);
48504888
if (irq_re_init) {
48514889
bnxt_free_ring_stats(bp);
48524890
if (!(bp->phy_flags & BNXT_PHY_FL_PORT_STATS_NO_RESET) ||
@@ -5290,6 +5328,92 @@ static int bnxt_hwrm_cfa_l2_set_rx_mask(struct bnxt *bp, u16 vnic_id)
52905328
return hwrm_req_send_silent(bp, req);
52915329
}
52925330

5331+
void bnxt_del_l2_filter(struct bnxt *bp, struct bnxt_l2_filter *fltr)
5332+
{
5333+
if (!atomic_dec_and_test(&fltr->refcnt))
5334+
return;
5335+
spin_lock_bh(&bp->ntp_fltr_lock);
5336+
hlist_del_rcu(&fltr->base.hash);
5337+
if (fltr->base.flags) {
5338+
clear_bit(fltr->base.sw_id, bp->ntp_fltr_bmap);
5339+
bp->ntp_fltr_count--;
5340+
}
5341+
spin_unlock_bh(&bp->ntp_fltr_lock);
5342+
kfree_rcu(fltr, base.rcu);
5343+
}
5344+
5345+
static struct bnxt_l2_filter *__bnxt_lookup_l2_filter(struct bnxt *bp,
5346+
struct bnxt_l2_key *key,
5347+
u32 idx)
5348+
{
5349+
struct hlist_head *head = &bp->l2_fltr_hash_tbl[idx];
5350+
struct bnxt_l2_filter *fltr;
5351+
5352+
hlist_for_each_entry_rcu(fltr, head, base.hash) {
5353+
struct bnxt_l2_key *l2_key = &fltr->l2_key;
5354+
5355+
if (ether_addr_equal(l2_key->dst_mac_addr, key->dst_mac_addr) &&
5356+
l2_key->vlan == key->vlan)
5357+
return fltr;
5358+
}
5359+
return NULL;
5360+
}
5361+
5362+
static struct bnxt_l2_filter *bnxt_lookup_l2_filter(struct bnxt *bp,
5363+
struct bnxt_l2_key *key,
5364+
u32 idx)
5365+
{
5366+
struct bnxt_l2_filter *fltr = NULL;
5367+
5368+
rcu_read_lock();
5369+
fltr = __bnxt_lookup_l2_filter(bp, key, idx);
5370+
if (fltr)
5371+
atomic_inc(&fltr->refcnt);
5372+
rcu_read_unlock();
5373+
return fltr;
5374+
}
5375+
5376+
static int bnxt_init_l2_filter(struct bnxt *bp, struct bnxt_l2_filter *fltr,
5377+
struct bnxt_l2_key *key, u32 idx)
5378+
{
5379+
struct hlist_head *head;
5380+
5381+
ether_addr_copy(fltr->l2_key.dst_mac_addr, key->dst_mac_addr);
5382+
fltr->l2_key.vlan = key->vlan;
5383+
fltr->base.type = BNXT_FLTR_TYPE_L2;
5384+
head = &bp->l2_fltr_hash_tbl[idx];
5385+
hlist_add_head_rcu(&fltr->base.hash, head);
5386+
atomic_set(&fltr->refcnt, 1);
5387+
return 0;
5388+
}
5389+
5390+
static struct bnxt_l2_filter *bnxt_alloc_l2_filter(struct bnxt *bp,
5391+
struct bnxt_l2_key *key,
5392+
gfp_t gfp)
5393+
{
5394+
struct bnxt_l2_filter *fltr;
5395+
u32 idx;
5396+
int rc;
5397+
5398+
idx = jhash2(&key->filter_key, BNXT_L2_KEY_SIZE, bp->hash_seed) &
5399+
BNXT_L2_FLTR_HASH_MASK;
5400+
fltr = bnxt_lookup_l2_filter(bp, key, idx);
5401+
if (fltr)
5402+
return fltr;
5403+
5404+
fltr = kzalloc(sizeof(*fltr), gfp);
5405+
if (!fltr)
5406+
return ERR_PTR(-ENOMEM);
5407+
spin_lock_bh(&bp->ntp_fltr_lock);
5408+
rc = bnxt_init_l2_filter(bp, fltr, key, idx);
5409+
spin_unlock_bh(&bp->ntp_fltr_lock);
5410+
if (rc) {
5411+
bnxt_del_l2_filter(bp, fltr);
5412+
fltr = ERR_PTR(rc);
5413+
}
5414+
return fltr;
5415+
}
5416+
52935417
#ifdef CONFIG_RFS_ACCEL
52945418
static int bnxt_hwrm_cfa_ntuple_filter_free(struct bnxt *bp,
52955419
struct bnxt_ntuple_filter *fltr)
@@ -5330,6 +5454,7 @@ static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
53305454
struct hwrm_cfa_ntuple_filter_alloc_output *resp;
53315455
struct hwrm_cfa_ntuple_filter_alloc_input *req;
53325456
struct flow_keys *keys = &fltr->fkeys;
5457+
struct bnxt_l2_filter *l2_fltr;
53335458
struct bnxt_vnic_info *vnic;
53345459
u32 flags = 0;
53355460
int rc;
@@ -5338,7 +5463,9 @@ static int bnxt_hwrm_cfa_ntuple_filter_alloc(struct bnxt *bp,
53385463
if (rc)
53395464
return rc;
53405465

5341-
req->l2_filter_id = bp->vnic_info[0].fw_l2_filter_id[fltr->l2_fltr_idx];
5466+
l2_fltr = bp->vnic_info[0].l2_filters[fltr->l2_fltr_idx];
5467+
req->l2_filter_id = l2_fltr->base.filter_id;
5468+
53425469

53435470
if (bp->fw_cap & BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2) {
53445471
flags = CFA_NTUPLE_FILTER_ALLOC_REQ_FLAGS_DEST_RFS_RING_IDX;
@@ -5400,8 +5527,16 @@ static int bnxt_hwrm_set_vnic_filter(struct bnxt *bp, u16 vnic_id, u16 idx,
54005527
{
54015528
struct hwrm_cfa_l2_filter_alloc_output *resp;
54025529
struct hwrm_cfa_l2_filter_alloc_input *req;
5530+
struct bnxt_l2_filter *fltr;
5531+
struct bnxt_l2_key key;
54035532
int rc;
54045533

5534+
ether_addr_copy(key.dst_mac_addr, mac_addr);
5535+
key.vlan = 0;
5536+
fltr = bnxt_alloc_l2_filter(bp, &key, GFP_KERNEL);
5537+
if (IS_ERR(fltr))
5538+
return PTR_ERR(fltr);
5539+
54055540
rc = hwrm_req_init(bp, req, HWRM_CFA_L2_FILTER_ALLOC);
54065541
if (rc)
54075542
return rc;
@@ -5425,9 +5560,13 @@ static int bnxt_hwrm_set_vnic_filter(struct bnxt *bp, u16 vnic_id, u16 idx,
54255560

54265561
resp = hwrm_req_hold(bp, req);
54275562
rc = hwrm_req_send(bp, req);
5428-
if (!rc)
5429-
bp->vnic_info[vnic_id].fw_l2_filter_id[idx] =
5430-
resp->l2_filter_id;
5563+
if (rc) {
5564+
bnxt_del_l2_filter(bp, fltr);
5565+
} else {
5566+
fltr->base.filter_id = resp->l2_filter_id;
5567+
set_bit(BNXT_FLTR_VALID, &fltr->base.state);
5568+
bp->vnic_info[vnic_id].l2_filters[idx] = fltr;
5569+
}
54315570
hwrm_req_drop(bp, req);
54325571
return rc;
54335572
}
@@ -5447,9 +5586,13 @@ static int bnxt_hwrm_clear_vnic_filter(struct bnxt *bp)
54475586
struct bnxt_vnic_info *vnic = &bp->vnic_info[i];
54485587

54495588
for (j = 0; j < vnic->uc_filter_count; j++) {
5450-
req->l2_filter_id = vnic->fw_l2_filter_id[j];
5589+
struct bnxt_l2_filter *fltr;
5590+
5591+
fltr = vnic->l2_filters[j];
5592+
req->l2_filter_id = fltr->base.filter_id;
54515593

54525594
rc = hwrm_req_send(bp, req);
5595+
bnxt_del_l2_filter(bp, fltr);
54535596
}
54545597
vnic->uc_filter_count = 0;
54555598
}
@@ -11759,9 +11902,12 @@ static int bnxt_cfg_rx_mode(struct bnxt *bp)
1175911902
return rc;
1176011903
hwrm_req_hold(bp, req);
1176111904
for (i = 1; i < vnic->uc_filter_count; i++) {
11762-
req->l2_filter_id = vnic->fw_l2_filter_id[i];
11905+
struct bnxt_l2_filter *fltr = vnic->l2_filters[i];
11906+
11907+
req->l2_filter_id = fltr->base.filter_id;
1176311908

1176411909
rc = hwrm_req_send(bp, req);
11910+
bnxt_del_l2_filter(bp, fltr);
1176511911
}
1176611912
hwrm_req_drop(bp, req);
1176711913

@@ -13901,6 +14047,8 @@ static void bnxt_remove_one(struct pci_dev *pdev)
1390114047

1390214048
bnxt_ptp_clear(bp);
1390314049
unregister_netdev(dev);
14050+
bnxt_free_l2_filters(bp, true);
14051+
bnxt_free_ntp_fltrs(bp, true);
1390414052
clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
1390514053
/* Flush any pending tasks */
1390614054
cancel_work_sync(&bp->sp_task);
@@ -14450,6 +14598,7 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1445014598
if (rc)
1445114599
goto init_err_pci_clean;
1445214600

14601+
bnxt_init_l2_fltr_tbl(bp);
1445314602
bnxt_set_rx_skb_mode(bp, false);
1445414603
bnxt_set_tpa_flags(bp);
1445514604
bnxt_set_ring_params(bp);

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1219,7 +1219,7 @@ struct bnxt_vnic_info {
12191219
u16 fw_rss_cos_lb_ctx[BNXT_MAX_CTX_PER_VNIC];
12201220
u16 fw_l2_ctx_id;
12211221
#define BNXT_MAX_UC_ADDRS 4
1222-
__le64 fw_l2_filter_id[BNXT_MAX_UC_ADDRS];
1222+
struct bnxt_l2_filter *l2_filters[BNXT_MAX_UC_ADDRS];
12231223
/* index 0 always dev_addr */
12241224
u16 uc_filter_count;
12251225
u8 *uc_list;
@@ -1349,6 +1349,8 @@ struct bnxt_filter_base {
13491349
unsigned long state;
13501350
#define BNXT_FLTR_VALID 0
13511351
#define BNXT_FLTR_UPDATE 1
1352+
1353+
struct rcu_head rcu;
13521354
};
13531355

13541356
struct bnxt_ntuple_filter {
@@ -1360,6 +1362,24 @@ struct bnxt_ntuple_filter {
13601362
u32 flow_id;
13611363
};
13621364

1365+
struct bnxt_l2_key {
1366+
union {
1367+
struct {
1368+
u8 dst_mac_addr[ETH_ALEN];
1369+
u16 vlan;
1370+
};
1371+
u32 filter_key;
1372+
};
1373+
};
1374+
1375+
#define BNXT_L2_KEY_SIZE (sizeof(struct bnxt_l2_key) / 4)
1376+
1377+
struct bnxt_l2_filter {
1378+
struct bnxt_filter_base base;
1379+
struct bnxt_l2_key l2_key;
1380+
atomic_t refcnt;
1381+
};
1382+
13631383
struct bnxt_link_info {
13641384
u8 phy_type;
13651385
u8 media_type;
@@ -2388,6 +2408,13 @@ struct bnxt {
23882408
unsigned long *ntp_fltr_bmap;
23892409
int ntp_fltr_count;
23902410

2411+
#define BNXT_L2_FLTR_MAX_FLTR 1024
2412+
#define BNXT_L2_FLTR_HASH_SIZE 32
2413+
#define BNXT_L2_FLTR_HASH_MASK (BNXT_L2_FLTR_HASH_SIZE - 1)
2414+
struct hlist_head l2_fltr_hash_tbl[BNXT_L2_FLTR_HASH_SIZE];
2415+
2416+
u32 hash_seed;
2417+
23912418
/* To protect link related settings during link changes and
23922419
* ethtool settings changes.
23932420
*/
@@ -2595,6 +2622,7 @@ int bnxt_set_rx_skb_mode(struct bnxt *bp, bool page_mode);
25952622
int bnxt_hwrm_func_drv_rgtr(struct bnxt *bp, unsigned long *bmap,
25962623
int bmap_size, bool async_only);
25972624
int bnxt_hwrm_func_drv_unrgtr(struct bnxt *bp);
2625+
void bnxt_del_l2_filter(struct bnxt *bp, struct bnxt_l2_filter *fltr);
25982626
int bnxt_get_nr_rss_ctxs(struct bnxt *bp, int rx_rings);
25992627
int bnxt_hwrm_vnic_cfg(struct bnxt *bp, u16 vnic_id);
26002628
int __bnxt_hwrm_get_tx_rings(struct bnxt *bp, u16 fid, int *tx_rings);

0 commit comments

Comments
 (0)