Skip to content

Commit c1e329e

Browse files
emuslndavem330
authored andcommitted
ionic: Add management of rx filters
Set up the infrastructure for managing Rx filters. We can't ask the hardware for what filters it has, so we keep a local list of filters that we've pushed into the HW. Signed-off-by: Shannon Nelson <snelson@pensando.io> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent beead69 commit c1e329e

File tree

5 files changed

+194
-1
lines changed

5 files changed

+194
-1
lines changed

drivers/net/ethernet/pensando/ionic/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
obj-$(CONFIG_IONIC) := ionic.o
55

66
ionic-y := ionic_main.o ionic_bus_pci.o ionic_devlink.o ionic_dev.o \
7-
ionic_debugfs.o ionic_lif.o
7+
ionic_debugfs.o ionic_lif.o ionic_rx_filter.o

drivers/net/ethernet/pensando/ionic/ionic_lif.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,8 @@ static void ionic_lif_deinit(struct ionic_lif *lif)
830830

831831
clear_bit(IONIC_LIF_INITED, lif->state);
832832

833+
ionic_rx_filters_deinit(lif);
834+
833835
napi_disable(&lif->adminqcq->napi);
834836
ionic_lif_qcq_deinit(lif, lif->notifyqcq);
835837
ionic_lif_qcq_deinit(lif, lif->adminqcq);
@@ -1009,6 +1011,10 @@ static int ionic_lif_init(struct ionic_lif *lif)
10091011
if (err)
10101012
goto err_out_notifyq_deinit;
10111013

1014+
err = ionic_rx_filters_init(lif);
1015+
if (err)
1016+
goto err_out_notifyq_deinit;
1017+
10121018
set_bit(IONIC_LIF_INITED, lif->state);
10131019

10141020
return 0;

drivers/net/ethernet/pensando/ionic/ionic_lif.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#define _IONIC_LIF_H_
66

77
#include <linux/pci.h>
8+
#include "ionic_rx_filter.h"
89

910
#define IONIC_ADMINQ_LENGTH 16 /* must be a power of two */
1011
#define IONIC_NOTIFYQ_LENGTH 64 /* must be a power of two */
@@ -90,6 +91,7 @@ struct ionic_lif {
9091
dma_addr_t info_pa;
9192
u32 info_sz;
9293

94+
struct ionic_rx_filters rx_filters;
9395
unsigned long *dbid_inuse;
9496
unsigned int dbid_count;
9597
struct dentry *dentry;
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
3+
4+
#include <linux/netdevice.h>
5+
#include <linux/etherdevice.h>
6+
7+
#include "ionic.h"
8+
#include "ionic_lif.h"
9+
#include "ionic_rx_filter.h"
10+
11+
void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f)
12+
{
13+
struct device *dev = lif->ionic->dev;
14+
15+
hlist_del(&f->by_id);
16+
hlist_del(&f->by_hash);
17+
devm_kfree(dev, f);
18+
}
19+
20+
int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f)
21+
{
22+
struct ionic_admin_ctx ctx = {
23+
.work = COMPLETION_INITIALIZER_ONSTACK(ctx.work),
24+
.cmd.rx_filter_del = {
25+
.opcode = IONIC_CMD_RX_FILTER_DEL,
26+
.filter_id = cpu_to_le32(f->filter_id),
27+
},
28+
};
29+
30+
return ionic_adminq_post_wait(lif, &ctx);
31+
}
32+
33+
int ionic_rx_filters_init(struct ionic_lif *lif)
34+
{
35+
unsigned int i;
36+
37+
spin_lock_init(&lif->rx_filters.lock);
38+
39+
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
40+
INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]);
41+
INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]);
42+
}
43+
44+
return 0;
45+
}
46+
47+
void ionic_rx_filters_deinit(struct ionic_lif *lif)
48+
{
49+
struct ionic_rx_filter *f;
50+
struct hlist_head *head;
51+
struct hlist_node *tmp;
52+
unsigned int i;
53+
54+
for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) {
55+
head = &lif->rx_filters.by_id[i];
56+
hlist_for_each_entry_safe(f, tmp, head, by_id)
57+
ionic_rx_filter_free(lif, f);
58+
}
59+
}
60+
61+
int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
62+
u32 hash, struct ionic_admin_ctx *ctx)
63+
{
64+
struct device *dev = lif->ionic->dev;
65+
struct ionic_rx_filter_add_cmd *ac;
66+
struct ionic_rx_filter *f;
67+
struct hlist_head *head;
68+
unsigned int key;
69+
70+
ac = &ctx->cmd.rx_filter_add;
71+
72+
switch (le16_to_cpu(ac->match)) {
73+
case IONIC_RX_FILTER_MATCH_VLAN:
74+
key = le16_to_cpu(ac->vlan.vlan);
75+
break;
76+
case IONIC_RX_FILTER_MATCH_MAC:
77+
key = *(u32 *)ac->mac.addr;
78+
break;
79+
case IONIC_RX_FILTER_MATCH_MAC_VLAN:
80+
key = le16_to_cpu(ac->mac_vlan.vlan);
81+
break;
82+
default:
83+
return -EINVAL;
84+
}
85+
86+
f = devm_kzalloc(dev, sizeof(*f), GFP_KERNEL);
87+
if (!f)
88+
return -ENOMEM;
89+
90+
f->flow_id = flow_id;
91+
f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id);
92+
f->rxq_index = rxq_index;
93+
memcpy(&f->cmd, ac, sizeof(f->cmd));
94+
95+
INIT_HLIST_NODE(&f->by_hash);
96+
INIT_HLIST_NODE(&f->by_id);
97+
98+
spin_lock_bh(&lif->rx_filters.lock);
99+
100+
key = hash_32(key, IONIC_RX_FILTER_HASH_BITS);
101+
head = &lif->rx_filters.by_hash[key];
102+
hlist_add_head(&f->by_hash, head);
103+
104+
key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK;
105+
head = &lif->rx_filters.by_id[key];
106+
hlist_add_head(&f->by_id, head);
107+
108+
spin_unlock_bh(&lif->rx_filters.lock);
109+
110+
return 0;
111+
}
112+
113+
struct ionic_rx_filter *ionic_rx_filter_by_vlan(struct ionic_lif *lif, u16 vid)
114+
{
115+
struct ionic_rx_filter *f;
116+
struct hlist_head *head;
117+
unsigned int key;
118+
119+
key = hash_32(vid, IONIC_RX_FILTER_HASH_BITS);
120+
head = &lif->rx_filters.by_hash[key];
121+
122+
hlist_for_each_entry(f, head, by_hash) {
123+
if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_VLAN)
124+
continue;
125+
if (le16_to_cpu(f->cmd.vlan.vlan) == vid)
126+
return f;
127+
}
128+
129+
return NULL;
130+
}
131+
132+
struct ionic_rx_filter *ionic_rx_filter_by_addr(struct ionic_lif *lif,
133+
const u8 *addr)
134+
{
135+
struct ionic_rx_filter *f;
136+
struct hlist_head *head;
137+
unsigned int key;
138+
139+
key = hash_32(*(u32 *)addr, IONIC_RX_FILTER_HASH_BITS);
140+
head = &lif->rx_filters.by_hash[key];
141+
142+
hlist_for_each_entry(f, head, by_hash) {
143+
if (le16_to_cpu(f->cmd.match) != IONIC_RX_FILTER_MATCH_MAC)
144+
continue;
145+
if (memcmp(addr, f->cmd.mac.addr, ETH_ALEN) == 0)
146+
return f;
147+
}
148+
149+
return NULL;
150+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* SPDX-License-Identifier: GPL-2.0 */
2+
/* Copyright(c) 2017 - 2019 Pensando Systems, Inc */
3+
4+
#ifndef _IONIC_RX_FILTER_H_
5+
#define _IONIC_RX_FILTER_H_
6+
7+
#define IONIC_RXQ_INDEX_ANY (0xFFFF)
8+
struct ionic_rx_filter {
9+
u32 flow_id;
10+
u32 filter_id;
11+
u16 rxq_index;
12+
struct ionic_rx_filter_add_cmd cmd;
13+
struct hlist_node by_hash;
14+
struct hlist_node by_id;
15+
};
16+
17+
#define IONIC_RX_FILTER_HASH_BITS 10
18+
#define IONIC_RX_FILTER_HLISTS BIT(IONIC_RX_FILTER_HASH_BITS)
19+
#define IONIC_RX_FILTER_HLISTS_MASK (IONIC_RX_FILTER_HLISTS - 1)
20+
struct ionic_rx_filters {
21+
spinlock_t lock; /* filter list lock */
22+
struct hlist_head by_hash[IONIC_RX_FILTER_HLISTS]; /* by skb hash */
23+
struct hlist_head by_id[IONIC_RX_FILTER_HLISTS]; /* by filter_id */
24+
};
25+
26+
void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f);
27+
int ionic_rx_filter_del(struct ionic_lif *lif, struct ionic_rx_filter *f);
28+
int ionic_rx_filters_init(struct ionic_lif *lif);
29+
void ionic_rx_filters_deinit(struct ionic_lif *lif);
30+
int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index,
31+
u32 hash, struct ionic_admin_ctx *ctx);
32+
struct ionic_rx_filter *ionic_rx_filter_by_vlan(struct ionic_lif *lif, u16 vid);
33+
struct ionic_rx_filter *ionic_rx_filter_by_addr(struct ionic_lif *lif, const u8 *addr);
34+
35+
#endif /* _IONIC_RX_FILTER_H_ */

0 commit comments

Comments
 (0)