Skip to content

Commit 56c03cb

Browse files
committed
Merge branch 'thunderx-DMAC-filtering'
Vadim Lomovtsev says: ==================== net: thunderx: implement DMAC filtering support By default CN88XX BGX accepts all incoming multicast and broadcast packets and filtering is disabled. The nic driver doesn't provide an ability to change such behaviour. This series is to implement DMAC filtering management for CN88XX nic driver allowing user to enable/disable filtering and configure specific MAC addresses to filter traffic. Changes from v1: build issues: - update code in order to address compiler warnings; checkpatch.pl reported issues: - update code in order to fit 80 symbols length; - update commit descriptions in order to fit 80 symbols length; ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 5e8b270 + 37c3347 commit 56c03cb

File tree

5 files changed

+374
-30
lines changed

5 files changed

+374
-30
lines changed

drivers/net/ethernet/cavium/thunder/nic.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,22 @@ struct nicvf_drv_stats {
265265

266266
struct cavium_ptp;
267267

268+
struct xcast_addr {
269+
struct list_head list;
270+
u64 addr;
271+
};
272+
273+
struct xcast_addr_list {
274+
struct list_head list;
275+
int count;
276+
};
277+
278+
struct nicvf_work {
279+
struct delayed_work work;
280+
u8 mode;
281+
struct xcast_addr_list *mc;
282+
};
283+
268284
struct nicvf {
269285
struct nicvf *pnicvf;
270286
struct net_device *netdev;
@@ -313,6 +329,7 @@ struct nicvf {
313329
struct nicvf_pfc pfc;
314330
struct tasklet_struct qs_err_task;
315331
struct work_struct reset_task;
332+
struct nicvf_work rx_mode_work;
316333

317334
/* PTP timestamp */
318335
struct cavium_ptp *ptp_clock;
@@ -403,6 +420,9 @@ struct nicvf {
403420
#define NIC_MBOX_MSG_PTP_CFG 0x19 /* HW packet timestamp */
404421
#define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */
405422
#define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */
423+
#define NIC_MBOX_MSG_RESET_XCAST 0xF2 /* Reset DCAM filtering mode */
424+
#define NIC_MBOX_MSG_ADD_MCAST 0xF3 /* Add MAC to DCAM filters */
425+
#define NIC_MBOX_MSG_SET_XCAST 0xF4 /* Set MCAST/BCAST RX mode */
406426

407427
struct nic_cfg_msg {
408428
u8 msg;
@@ -556,6 +576,14 @@ struct set_ptp {
556576
bool enable;
557577
};
558578

579+
struct xcast {
580+
u8 msg;
581+
union {
582+
u8 mode;
583+
u64 mac;
584+
} data;
585+
};
586+
559587
/* 128 bit shared memory between PF and each VF */
560588
union nic_mbx {
561589
struct { u8 msg; } msg;
@@ -576,6 +604,7 @@ union nic_mbx {
576604
struct reset_stat_cfg reset_stat;
577605
struct pfc pfc;
578606
struct set_ptp ptp;
607+
struct xcast xcast;
579608
};
580609

581610
#define NIC_NODE_ID_MASK 0x03

drivers/net/ethernet/cavium/thunder/nic_main.c

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
#define DRV_NAME "nicpf"
2222
#define DRV_VERSION "1.0"
2323

24+
#define NIC_VF_PER_MBX_REG 64
25+
2426
struct hw_info {
2527
u8 bgx_cnt;
2628
u8 chans_per_lmac;
@@ -1072,6 +1074,40 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
10721074
case NIC_MBOX_MSG_PTP_CFG:
10731075
nic_config_timestamp(nic, vf, &mbx.ptp);
10741076
break;
1077+
case NIC_MBOX_MSG_RESET_XCAST:
1078+
if (vf >= nic->num_vf_en) {
1079+
ret = -1; /* NACK */
1080+
break;
1081+
}
1082+
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
1083+
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
1084+
bgx_reset_xcast_mode(nic->node, bgx, lmac,
1085+
vf < NIC_VF_PER_MBX_REG ? vf :
1086+
vf - NIC_VF_PER_MBX_REG);
1087+
break;
1088+
1089+
case NIC_MBOX_MSG_ADD_MCAST:
1090+
if (vf >= nic->num_vf_en) {
1091+
ret = -1; /* NACK */
1092+
break;
1093+
}
1094+
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
1095+
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
1096+
bgx_set_dmac_cam_filter(nic->node, bgx, lmac,
1097+
mbx.xcast.data.mac,
1098+
vf < NIC_VF_PER_MBX_REG ? vf :
1099+
vf - NIC_VF_PER_MBX_REG);
1100+
break;
1101+
1102+
case NIC_MBOX_MSG_SET_XCAST:
1103+
if (vf >= nic->num_vf_en) {
1104+
ret = -1; /* NACK */
1105+
break;
1106+
}
1107+
bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
1108+
lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
1109+
bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.data.mode);
1110+
break;
10751111
default:
10761112
dev_err(&nic->pdev->dev,
10771113
"Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
@@ -1094,7 +1130,7 @@ static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq)
10941130
struct nicpf *nic = (struct nicpf *)nic_irq;
10951131
int mbx;
10961132
u64 intr;
1097-
u8 vf, vf_per_mbx_reg = 64;
1133+
u8 vf;
10981134

10991135
if (irq == pci_irq_vector(nic->pdev, NIC_PF_INTR_ID_MBOX0))
11001136
mbx = 0;
@@ -1103,12 +1139,13 @@ static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq)
11031139

11041140
intr = nic_reg_read(nic, NIC_PF_MAILBOX_INT + (mbx << 3));
11051141
dev_dbg(&nic->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr);
1106-
for (vf = 0; vf < vf_per_mbx_reg; vf++) {
1142+
for (vf = 0; vf < NIC_VF_PER_MBX_REG; vf++) {
11071143
if (intr & (1ULL << vf)) {
11081144
dev_dbg(&nic->pdev->dev, "Intr from VF %d\n",
1109-
vf + (mbx * vf_per_mbx_reg));
1145+
vf + (mbx * NIC_VF_PER_MBX_REG));
11101146

1111-
nic_handle_mbx_intr(nic, vf + (mbx * vf_per_mbx_reg));
1147+
nic_handle_mbx_intr(nic, vf +
1148+
(mbx * NIC_VF_PER_MBX_REG));
11121149
nic_clear_mbx_intr(nic, vf, mbx);
11131150
}
11141151
}

drivers/net/ethernet/cavium/thunder/nicvf_main.c

Lines changed: 109 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include <linux/bpf_trace.h>
2222
#include <linux/filter.h>
2323
#include <linux/net_tstamp.h>
24+
#include <linux/workqueue.h>
2425

2526
#include "nic_reg.h"
2627
#include "nic.h"
@@ -67,6 +68,9 @@ module_param(cpi_alg, int, 0444);
6768
MODULE_PARM_DESC(cpi_alg,
6869
"PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)");
6970

71+
/* workqueue for handling kernel ndo_set_rx_mode() calls */
72+
static struct workqueue_struct *nicvf_rx_mode_wq;
73+
7074
static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx)
7175
{
7276
if (nic->sqs_mode)
@@ -1919,6 +1923,100 @@ static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd)
19191923
}
19201924
}
19211925

1926+
static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
1927+
{
1928+
struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
1929+
work.work);
1930+
struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
1931+
union nic_mbx mbx = {};
1932+
struct xcast_addr *xaddr, *next;
1933+
1934+
if (!vf_work)
1935+
return;
1936+
1937+
/* From the inside of VM code flow we have only 128 bits memory
1938+
* available to send message to host's PF, so send all mc addrs
1939+
* one by one, starting from flush command in case if kernel
1940+
* requests to configure specific MAC filtering
1941+
*/
1942+
1943+
/* flush DMAC filters and reset RX mode */
1944+
mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST;
1945+
nicvf_send_msg_to_pf(nic, &mbx);
1946+
1947+
if (vf_work->mode & BGX_XCAST_MCAST_FILTER) {
1948+
/* once enabling filtering, we need to signal to PF to add
1949+
* its' own LMAC to the filter to accept packets for it.
1950+
*/
1951+
mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
1952+
mbx.xcast.data.mac = 0;
1953+
nicvf_send_msg_to_pf(nic, &mbx);
1954+
}
1955+
1956+
/* check if we have any specific MACs to be added to PF DMAC filter */
1957+
if (vf_work->mc) {
1958+
/* now go through kernel list of MACs and add them one by one */
1959+
list_for_each_entry_safe(xaddr, next,
1960+
&vf_work->mc->list, list) {
1961+
mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
1962+
mbx.xcast.data.mac = xaddr->addr;
1963+
nicvf_send_msg_to_pf(nic, &mbx);
1964+
1965+
/* after receiving ACK from PF release memory */
1966+
list_del(&xaddr->list);
1967+
kfree(xaddr);
1968+
vf_work->mc->count--;
1969+
}
1970+
kfree(vf_work->mc);
1971+
}
1972+
1973+
/* and finally set rx mode for PF accordingly */
1974+
mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST;
1975+
mbx.xcast.data.mode = vf_work->mode;
1976+
1977+
nicvf_send_msg_to_pf(nic, &mbx);
1978+
}
1979+
1980+
static void nicvf_set_rx_mode(struct net_device *netdev)
1981+
{
1982+
struct nicvf *nic = netdev_priv(netdev);
1983+
struct netdev_hw_addr *ha;
1984+
struct xcast_addr_list *mc_list = NULL;
1985+
u8 mode = 0;
1986+
1987+
if (netdev->flags & IFF_PROMISC) {
1988+
mode = BGX_XCAST_BCAST_ACCEPT | BGX_XCAST_MCAST_ACCEPT;
1989+
} else {
1990+
if (netdev->flags & IFF_BROADCAST)
1991+
mode |= BGX_XCAST_BCAST_ACCEPT;
1992+
1993+
if (netdev->flags & IFF_ALLMULTI) {
1994+
mode |= BGX_XCAST_MCAST_ACCEPT;
1995+
} else if (netdev->flags & IFF_MULTICAST) {
1996+
mode |= BGX_XCAST_MCAST_FILTER;
1997+
/* here we need to copy mc addrs */
1998+
if (netdev_mc_count(netdev)) {
1999+
struct xcast_addr *xaddr;
2000+
2001+
mc_list = kmalloc(sizeof(*mc_list), GFP_ATOMIC);
2002+
INIT_LIST_HEAD(&mc_list->list);
2003+
netdev_hw_addr_list_for_each(ha, &netdev->mc) {
2004+
xaddr = kmalloc(sizeof(*xaddr),
2005+
GFP_ATOMIC);
2006+
xaddr->addr =
2007+
ether_addr_to_u64(ha->addr);
2008+
list_add_tail(&xaddr->list,
2009+
&mc_list->list);
2010+
mc_list->count++;
2011+
}
2012+
}
2013+
}
2014+
}
2015+
nic->rx_mode_work.mc = mc_list;
2016+
nic->rx_mode_work.mode = mode;
2017+
queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 2 * HZ);
2018+
}
2019+
19222020
static const struct net_device_ops nicvf_netdev_ops = {
19232021
.ndo_open = nicvf_open,
19242022
.ndo_stop = nicvf_stop,
@@ -1931,6 +2029,7 @@ static const struct net_device_ops nicvf_netdev_ops = {
19312029
.ndo_set_features = nicvf_set_features,
19322030
.ndo_bpf = nicvf_xdp,
19332031
.ndo_do_ioctl = nicvf_ioctl,
2032+
.ndo_set_rx_mode = nicvf_set_rx_mode,
19342033
};
19352034

19362035
static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
@@ -2071,6 +2170,8 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
20712170

20722171
INIT_WORK(&nic->reset_task, nicvf_reset_task);
20732172

2173+
INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
2174+
20742175
err = register_netdev(netdev);
20752176
if (err) {
20762177
dev_err(dev, "Failed to register netdevice\n");
@@ -2109,6 +2210,8 @@ static void nicvf_remove(struct pci_dev *pdev)
21092210
nic = netdev_priv(netdev);
21102211
pnetdev = nic->pnicvf->netdev;
21112212

2213+
cancel_delayed_work_sync(&nic->rx_mode_work.work);
2214+
21122215
/* Check if this Qset is assigned to different VF.
21132216
* If yes, clean primary and all secondary Qsets.
21142217
*/
@@ -2140,12 +2243,17 @@ static struct pci_driver nicvf_driver = {
21402243
static int __init nicvf_init_module(void)
21412244
{
21422245
pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION);
2143-
2246+
nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_generic",
2247+
WQ_MEM_RECLAIM);
21442248
return pci_register_driver(&nicvf_driver);
21452249
}
21462250

21472251
static void __exit nicvf_cleanup_module(void)
21482252
{
2253+
if (nicvf_rx_mode_wq) {
2254+
destroy_workqueue(nicvf_rx_mode_wq);
2255+
nicvf_rx_mode_wq = NULL;
2256+
}
21492257
pci_unregister_driver(&nicvf_driver);
21502258
}
21512259

0 commit comments

Comments
 (0)