diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/dummy.c | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/nic.h | 29 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/nic_main.c | 45 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/nicvf_main.c | 110 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/thunder_bgx.c | 201 | ||||
-rw-r--r-- | drivers/net/ethernet/cavium/thunder/thunder_bgx.h | 19 | ||||
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/hisilicon/hns3/hns3_enet.c | 4 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 5 | ||||
-rw-r--r-- | drivers/net/hyperv/rndis_filter.c | 16 | ||||
-rw-r--r-- | drivers/net/ifb.c | 2 | ||||
-rw-r--r-- | drivers/net/netdevsim/devlink.c | 12 | ||||
-rw-r--r-- | drivers/net/netdevsim/netdev.c | 6 | ||||
-rw-r--r-- | drivers/net/netdevsim/netdevsim.h | 5 |
14 files changed, 407 insertions, 55 deletions
diff --git a/drivers/net/dummy.c b/drivers/net/dummy.c index 30b1c8512049..0d15a12a4560 100644 --- a/drivers/net/dummy.c +++ b/drivers/net/dummy.c @@ -219,6 +219,7 @@ static int __init dummy_init_module(void) { int i, err = 0; + down_write(&pernet_ops_rwsem); rtnl_lock(); err = __rtnl_link_register(&dummy_link_ops); if (err < 0) @@ -233,6 +234,7 @@ static int __init dummy_init_module(void) out: rtnl_unlock(); + up_write(&pernet_ops_rwsem); return err; } diff --git a/drivers/net/ethernet/cavium/thunder/nic.h b/drivers/net/ethernet/cavium/thunder/nic.h index 4cacce5d2b16..5fc46c5a4f36 100644 --- a/drivers/net/ethernet/cavium/thunder/nic.h +++ b/drivers/net/ethernet/cavium/thunder/nic.h @@ -265,6 +265,22 @@ struct nicvf_drv_stats { struct cavium_ptp; +struct xcast_addr { + struct list_head list; + u64 addr; +}; + +struct xcast_addr_list { + struct list_head list; + int count; +}; + +struct nicvf_work { + struct delayed_work work; + u8 mode; + struct xcast_addr_list *mc; +}; + struct nicvf { struct nicvf *pnicvf; struct net_device *netdev; @@ -313,6 +329,7 @@ struct nicvf { struct nicvf_pfc pfc; struct tasklet_struct qs_err_task; struct work_struct reset_task; + struct nicvf_work rx_mode_work; /* PTP timestamp */ struct cavium_ptp *ptp_clock; @@ -403,6 +420,9 @@ struct nicvf { #define NIC_MBOX_MSG_PTP_CFG 0x19 /* HW packet timestamp */ #define NIC_MBOX_MSG_CFG_DONE 0xF0 /* VF configuration done */ #define NIC_MBOX_MSG_SHUTDOWN 0xF1 /* VF is being shutdown */ +#define NIC_MBOX_MSG_RESET_XCAST 0xF2 /* Reset DCAM filtering mode */ +#define NIC_MBOX_MSG_ADD_MCAST 0xF3 /* Add MAC to DCAM filters */ +#define NIC_MBOX_MSG_SET_XCAST 0xF4 /* Set MCAST/BCAST RX mode */ struct nic_cfg_msg { u8 msg; @@ -556,6 +576,14 @@ struct set_ptp { bool enable; }; +struct xcast { + u8 msg; + union { + u8 mode; + u64 mac; + } data; +}; + /* 128 bit shared memory between PF and each VF */ union nic_mbx { struct { u8 msg; } msg; @@ -576,6 +604,7 @@ union nic_mbx { struct reset_stat_cfg reset_stat; struct pfc pfc; struct set_ptp ptp; + struct xcast xcast; }; #define NIC_NODE_ID_MASK 0x03 diff --git a/drivers/net/ethernet/cavium/thunder/nic_main.c b/drivers/net/ethernet/cavium/thunder/nic_main.c index 7ff66a8194e2..55af04fa03a7 100644 --- a/drivers/net/ethernet/cavium/thunder/nic_main.c +++ b/drivers/net/ethernet/cavium/thunder/nic_main.c @@ -21,6 +21,8 @@ #define DRV_NAME "nicpf" #define DRV_VERSION "1.0" +#define NIC_VF_PER_MBX_REG 64 + struct hw_info { u8 bgx_cnt; u8 chans_per_lmac; @@ -1072,6 +1074,40 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf) case NIC_MBOX_MSG_PTP_CFG: nic_config_timestamp(nic, vf, &mbx.ptp); break; + case NIC_MBOX_MSG_RESET_XCAST: + if (vf >= nic->num_vf_en) { + ret = -1; /* NACK */ + break; + } + bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + bgx_reset_xcast_mode(nic->node, bgx, lmac, + vf < NIC_VF_PER_MBX_REG ? vf : + vf - NIC_VF_PER_MBX_REG); + break; + + case NIC_MBOX_MSG_ADD_MCAST: + if (vf >= nic->num_vf_en) { + ret = -1; /* NACK */ + break; + } + bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + bgx_set_dmac_cam_filter(nic->node, bgx, lmac, + mbx.xcast.data.mac, + vf < NIC_VF_PER_MBX_REG ? vf : + vf - NIC_VF_PER_MBX_REG); + break; + + case NIC_MBOX_MSG_SET_XCAST: + if (vf >= nic->num_vf_en) { + ret = -1; /* NACK */ + break; + } + bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]); + bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.data.mode); + break; default: dev_err(&nic->pdev->dev, "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) struct nicpf *nic = (struct nicpf *)nic_irq; int mbx; u64 intr; - u8 vf, vf_per_mbx_reg = 64; + u8 vf; if (irq == pci_irq_vector(nic->pdev, NIC_PF_INTR_ID_MBOX0)) mbx = 0; @@ -1103,12 +1139,13 @@ static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq) intr = nic_reg_read(nic, NIC_PF_MAILBOX_INT + (mbx << 3)); dev_dbg(&nic->pdev->dev, "PF interrupt Mbox%d 0x%llx\n", mbx, intr); - for (vf = 0; vf < vf_per_mbx_reg; vf++) { + for (vf = 0; vf < NIC_VF_PER_MBX_REG; vf++) { if (intr & (1ULL << vf)) { dev_dbg(&nic->pdev->dev, "Intr from VF %d\n", - vf + (mbx * vf_per_mbx_reg)); + vf + (mbx * NIC_VF_PER_MBX_REG)); - nic_handle_mbx_intr(nic, vf + (mbx * vf_per_mbx_reg)); + nic_handle_mbx_intr(nic, vf + + (mbx * NIC_VF_PER_MBX_REG)); nic_clear_mbx_intr(nic, vf, mbx); } } diff --git a/drivers/net/ethernet/cavium/thunder/nicvf_main.c b/drivers/net/ethernet/cavium/thunder/nicvf_main.c index 73fe3881414b..1e9a31fef729 100644 --- a/drivers/net/ethernet/cavium/thunder/nicvf_main.c +++ b/drivers/net/ethernet/cavium/thunder/nicvf_main.c @@ -21,6 +21,7 @@ #include <linux/bpf_trace.h> #include <linux/filter.h> #include <linux/net_tstamp.h> +#include <linux/workqueue.h> #include "nic_reg.h" #include "nic.h" @@ -67,6 +68,9 @@ module_param(cpi_alg, int, 0444); MODULE_PARM_DESC(cpi_alg, "PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)"); +/* workqueue for handling kernel ndo_set_rx_mode() calls */ +static struct workqueue_struct *nicvf_rx_mode_wq; + static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx) { if (nic->sqs_mode) @@ -1919,6 +1923,100 @@ static int nicvf_ioctl(struct net_device *netdev, struct ifreq *req, int cmd) } } +static void nicvf_set_rx_mode_task(struct work_struct *work_arg) +{ + struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work, + work.work); + struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work); + union nic_mbx mbx = {}; + struct xcast_addr *xaddr, *next; + + if (!vf_work) + return; + + /* From the inside of VM code flow we have only 128 bits memory + * available to send message to host's PF, so send all mc addrs + * one by one, starting from flush command in case if kernel + * requests to configure specific MAC filtering + */ + + /* flush DMAC filters and reset RX mode */ + mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST; + nicvf_send_msg_to_pf(nic, &mbx); + + if (vf_work->mode & BGX_XCAST_MCAST_FILTER) { + /* once enabling filtering, we need to signal to PF to add + * its' own LMAC to the filter to accept packets for it. + */ + mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST; + mbx.xcast.data.mac = 0; + nicvf_send_msg_to_pf(nic, &mbx); + } + + /* check if we have any specific MACs to be added to PF DMAC filter */ + if (vf_work->mc) { + /* now go through kernel list of MACs and add them one by one */ + list_for_each_entry_safe(xaddr, next, + &vf_work->mc->list, list) { + mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST; + mbx.xcast.data.mac = xaddr->addr; + nicvf_send_msg_to_pf(nic, &mbx); + + /* after receiving ACK from PF release memory */ + list_del(&xaddr->list); + kfree(xaddr); + vf_work->mc->count--; + } + kfree(vf_work->mc); + } + + /* and finally set rx mode for PF accordingly */ + mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST; + mbx.xcast.data.mode = vf_work->mode; + + nicvf_send_msg_to_pf(nic, &mbx); +} + +static void nicvf_set_rx_mode(struct net_device *netdev) +{ + struct nicvf *nic = netdev_priv(netdev); + struct netdev_hw_addr *ha; + struct xcast_addr_list *mc_list = NULL; + u8 mode = 0; + + if (netdev->flags & IFF_PROMISC) { + mode = BGX_XCAST_BCAST_ACCEPT | BGX_XCAST_MCAST_ACCEPT; + } else { + if (netdev->flags & IFF_BROADCAST) + mode |= BGX_XCAST_BCAST_ACCEPT; + + if (netdev->flags & IFF_ALLMULTI) { + mode |= BGX_XCAST_MCAST_ACCEPT; + } else if (netdev->flags & IFF_MULTICAST) { + mode |= BGX_XCAST_MCAST_FILTER; + /* here we need to copy mc addrs */ + if (netdev_mc_count(netdev)) { + struct xcast_addr *xaddr; + + mc_list = kmalloc(sizeof(*mc_list), GFP_ATOMIC); + INIT_LIST_HEAD(&mc_list->list); + netdev_hw_addr_list_for_each(ha, &netdev->mc) { + xaddr = kmalloc(sizeof(*xaddr), + GFP_ATOMIC); + xaddr->addr = + ether_addr_to_u64(ha->addr); + list_add_tail(&xaddr->list, + &mc_list->list); + mc_list->count++; + } + } + } + } + nic->rx_mode_work.mc = mc_list; + nic->rx_mode_work.mode = mode; + queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 2 * HZ); +} + static const struct net_device_ops nicvf_netdev_ops = { .ndo_open = nicvf_open, .ndo_stop = nicvf_stop, @@ -1931,6 +2029,7 @@ static const struct net_device_ops nicvf_netdev_ops = { .ndo_set_features = nicvf_set_features, .ndo_bpf = nicvf_xdp, .ndo_do_ioctl = nicvf_ioctl, + .ndo_set_rx_mode = nicvf_set_rx_mode, }; 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) INIT_WORK(&nic->reset_task, nicvf_reset_task); + INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task); + err = register_netdev(netdev); if (err) { dev_err(dev, "Failed to register netdevice\n"); @@ -2109,6 +2210,8 @@ static void nicvf_remove(struct pci_dev *pdev) nic = netdev_priv(netdev); pnetdev = nic->pnicvf->netdev; + cancel_delayed_work_sync(&nic->rx_mode_work.work); + /* Check if this Qset is assigned to different VF. * If yes, clean primary and all secondary Qsets. */ @@ -2140,12 +2243,17 @@ static struct pci_driver nicvf_driver = { static int __init nicvf_init_module(void) { pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION); - + nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_generic", + WQ_MEM_RECLAIM); return pci_register_driver(&nicvf_driver); } static void __exit nicvf_cleanup_module(void) { + if (nicvf_rx_mode_wq) { + destroy_workqueue(nicvf_rx_mode_wq); + nicvf_rx_mode_wq = NULL; + } pci_unregister_driver(&nicvf_driver); } diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c index 91d34ea40e2c..5d08d2aeb172 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c @@ -24,9 +24,31 @@ #define DRV_NAME "thunder_bgx" #define DRV_VERSION "1.0" +/* RX_DMAC_CTL configuration */ +enum MCAST_MODE { + MCAST_MODE_REJECT = 0x0, + MCAST_MODE_ACCEPT = 0x1, + MCAST_MODE_CAM_FILTER = 0x2, + RSVD = 0x3 +}; + +#define BCAST_ACCEPT BIT(0) +#define CAM_ACCEPT BIT(3) +#define MCAST_MODE_MASK 0x3 +#define BGX_MCAST_MODE(x) (x << 1) + +struct dmac_map { + u64 vf_map; + u64 dmac; +}; + struct lmac { struct bgx *bgx; - int dmac; + /* actual number of DMACs configured */ + u8 dmacs_cfg; + /* overal number of possible DMACs could be configured per LMAC */ + u8 dmacs_count; + struct dmac_map *dmacs; /* DMAC:VFs tracking filter array */ u8 mac[ETH_ALEN]; u8 lmac_type; u8 lane_to_sds; @@ -223,6 +245,163 @@ void bgx_set_lmac_mac(int node, int bgx_idx, int lmacid, const u8 *mac) } EXPORT_SYMBOL(bgx_set_lmac_mac); +static void bgx_flush_dmac_cam_filter(struct bgx *bgx, int lmacid) +{ + struct lmac *lmac = NULL; + u8 idx = 0; + + lmac = &bgx->lmac[lmacid]; + /* reset CAM filters */ + for (idx = 0; idx < lmac->dmacs_count; idx++) + bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + + ((lmacid * lmac->dmacs_count) + idx) * + sizeof(u64), 0); +} + +static void bgx_lmac_remove_filters(struct lmac *lmac, u8 vf_id) +{ + int i = 0; + + if (!lmac) + return; + + /* We've got reset filters request from some of attached VF, while the + * others might want to keep their configuration. So in this case lets + * iterate over all of configured filters and decrease number of + * referencies. if some addresses get zero refs remove them from list + */ + for (i = lmac->dmacs_cfg - 1; i >= 0; i--) { + lmac->dmacs[i].vf_map &= ~BIT_ULL(vf_id); + if (!lmac->dmacs[i].vf_map) { + lmac->dmacs_cfg--; + lmac->dmacs[i].dmac = 0; + lmac->dmacs[i].vf_map = 0; + } + } +} + +static int bgx_lmac_save_filter(struct lmac *lmac, u64 dmac, u8 vf_id) +{ + u8 i = 0; + + if (!lmac) + return -1; + + /* At the same time we could have several VFs 'attached' to some + * particular LMAC, and each VF is represented as network interface + * for kernel. So from user perspective it should be possible to + * manipulate with its' (VF) receive modes. However from PF + * driver perspective we need to keep track of filter configurations + * for different VFs to prevent filter values dupes + */ + for (i = 0; i < lmac->dmacs_cfg; i++) { + if (lmac->dmacs[i].dmac == dmac) { + lmac->dmacs[i].vf_map |= BIT_ULL(vf_id); + return -1; + } + } + + if (!(lmac->dmacs_cfg < lmac->dmacs_count)) + return -1; + + /* keep it for further tracking */ + lmac->dmacs[lmac->dmacs_cfg].dmac = dmac; + lmac->dmacs[lmac->dmacs_cfg].vf_map = BIT_ULL(vf_id); + lmac->dmacs_cfg++; + return 0; +} + +static int bgx_set_dmac_cam_filter_mac(struct bgx *bgx, int lmacid, + u64 cam_dmac, u8 idx) +{ + struct lmac *lmac = NULL; + u64 cfg = 0; + + /* skip zero addresses as meaningless */ + if (!cam_dmac || !bgx) + return -1; + + lmac = &bgx->lmac[lmacid]; + + /* configure DCAM filtering for designated LMAC */ + cfg = RX_DMACX_CAM_LMACID(lmacid & LMAC_ID_MASK) | + RX_DMACX_CAM_EN | cam_dmac; + bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + + ((lmacid * lmac->dmacs_count) + idx) * sizeof(u64), cfg); + return 0; +} + +void bgx_set_dmac_cam_filter(int node, int bgx_idx, int lmacid, + u64 cam_dmac, u8 vf_id) +{ + struct bgx *bgx = get_bgx(node, bgx_idx); + struct lmac *lmac = NULL; + + if (!bgx) + return; + + lmac = &bgx->lmac[lmacid]; + + if (!cam_dmac) + cam_dmac = ether_addr_to_u64(lmac->mac); + + /* since we might have several VFs attached to particular LMAC + * and kernel could call mcast config for each of them with the + * same MAC, check if requested MAC is already in filtering list and + * updare/prepare list of MACs to be applied later to HW filters + */ + bgx_lmac_save_filter(lmac, cam_dmac, vf_id); +} +EXPORT_SYMBOL(bgx_set_dmac_cam_filter); + +void bgx_set_xcast_mode(int node, int bgx_idx, int lmacid, u8 mode) +{ + struct bgx *bgx = get_bgx(node, bgx_idx); + struct lmac *lmac = NULL; + u64 cfg = 0; + u8 i = 0; + + if (!bgx) + return; + + lmac = &bgx->lmac[lmacid]; + + cfg = bgx_reg_read(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL); + if (mode & BGX_XCAST_BCAST_ACCEPT) + cfg |= BCAST_ACCEPT; + else + cfg &= ~BCAST_ACCEPT; + + /* disable all MCASTs and DMAC filtering */ + cfg &= ~(CAM_ACCEPT | BGX_MCAST_MODE(MCAST_MODE_MASK)); + + /* check requested bits and set filtergin mode appropriately */ + if (mode & (BGX_XCAST_MCAST_ACCEPT)) { + cfg |= (BGX_MCAST_MODE(MCAST_MODE_ACCEPT)); + } else if (mode & BGX_XCAST_MCAST_FILTER) { + cfg |= (BGX_MCAST_MODE(MCAST_MODE_CAM_FILTER) | CAM_ACCEPT); + for (i = 0; i < lmac->dmacs_cfg; i++) + bgx_set_dmac_cam_filter_mac(bgx, lmacid, + lmac->dmacs[i].dmac, i); + } + bgx_reg_write(bgx, lmacid, BGX_CMRX_RX_DMAC_CTL, cfg); +} +EXPORT_SYMBOL(bgx_set_xcast_mode); + +void bgx_reset_xcast_mode(int node, int bgx_idx, int lmacid, u8 vf_id) +{ + struct bgx *bgx = get_bgx(node, bgx_idx); + + if (!bgx) + return; + + bgx_lmac_remove_filters(&bgx->lmac[lmacid], vf_id); + bgx_flush_dmac_cam_filter(bgx, lmacid); + bgx_set_xcast_mode(node, bgx_idx, lmacid, + (BGX_XCAST_BCAST_ACCEPT | BGX_XCAST_MCAST_ACCEPT)); +} +EXPORT_SYMBOL(bgx_reset_xcast_mode); + void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable) { struct bgx *bgx = get_bgx(node, bgx_idx); @@ -468,18 +647,6 @@ u64 bgx_get_tx_stats(int node, int bgx_idx, int lmac, int idx) } EXPORT_SYMBOL(bgx_get_tx_stats); -static void bgx_flush_dmac_addrs(struct bgx *bgx, int lmac) -{ - u64 offset; - - while (bgx->lmac[lmac].dmac > 0) { - offset = ((bgx->lmac[lmac].dmac - 1) * sizeof(u64)) + - (lmac * MAX_DMAC_PER_LMAC * sizeof(u64)); - bgx_reg_write(bgx, 0, BGX_CMR_RX_DMACX_CAM + offset, 0); - bgx->lmac[lmac].dmac--; - } -} - /* Configure BGX LMAC in internal loopback mode */ void bgx_lmac_internal_loopback(int node, int bgx_idx, int lmac_idx, bool enable) @@ -912,6 +1079,11 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid) bgx_reg_write(bgx, lmacid, BGX_SMUX_TX_MIN_PKT, 60 + 4); } + /* actual number of filters available to exact LMAC */ + lmac->dmacs_count = (RX_DMAC_COUNT / bgx->lmac_count); + lmac->dmacs = kcalloc(lmac->dmacs_count, sizeof(*lmac->dmacs), + GFP_KERNEL); + /* Enable lmac */ bgx_reg_modify(bgx, lmacid, BGX_CMRX_CFG, CMR_EN); @@ -998,7 +1170,8 @@ static void bgx_lmac_disable(struct bgx *bgx, u8 lmacid) cfg &= ~CMR_EN; bgx_reg_write(bgx, lmacid, BGX_CMRX_CFG, cfg); - bgx_flush_dmac_addrs(bgx, lmacid); + bgx_flush_dmac_cam_filter(bgx, lmacid); + kfree(lmac->dmacs); if ((lmac->lmac_type != BGX_MODE_XFI) && (lmac->lmac_type != BGX_MODE_XLAUI) && diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h index 5a7567d31138..cbdd20b9ee6f 100644 --- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.h +++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.h @@ -30,6 +30,7 @@ #define DEFAULT_PAUSE_TIME 0xFFFF #define BGX_ID_MASK 0x3 +#define LMAC_ID_MASK 0x3 #define MAX_DMAC_PER_LMAC_TNS_BYPASS_MODE 2 @@ -57,7 +58,7 @@ #define BGX_CMRX_RX_FIFO_LEN 0x108 #define BGX_CMR_RX_DMACX_CAM 0x200 #define RX_DMACX_CAM_EN BIT_ULL(48) -#define RX_DMACX_CAM_LMACID(x) (x << 49) +#define RX_DMACX_CAM_LMACID(x) (((u64)x) << 49) #define RX_DMAC_COUNT 32 #define BGX_CMR_RX_STREERING 0x300 #define RX_TRAFFIC_STEER_RULE_COUNT 8 @@ -205,17 +206,13 @@ #define LMAC_INTR_LINK_UP BIT(0) #define LMAC_INTR_LINK_DOWN BIT(1) -/* RX_DMAC_CTL configuration*/ -enum MCAST_MODE { - MCAST_MODE_REJECT, - MCAST_MODE_ACCEPT, - MCAST_MODE_CAM_FILTER, - RSVD -}; - -#define BCAST_ACCEPT 1 -#define CAM_ACCEPT 1 +#define BGX_XCAST_BCAST_ACCEPT BIT(0) +#define BGX_XCAST_MCAST_ACCEPT BIT(1) +#define BGX_XCAST_MCAST_FILTER BIT(2) +void bgx_set_dmac_cam_filter(int node, int bgx_idx, int lmacid, u64 mac, u8 vf); +void bgx_reset_xcast_mode(int node, int bgx_idx, int lmacid, u8 vf); +void bgx_set_xcast_mode(int node, int bgx_idx, int lmacid, u8 mode); void octeon_mdiobus_force_mod_depencency(void); void bgx_lmac_rx_tx_enable(int node, int bgx_idx, int lmacid, bool enable); void bgx_add_dmac_addr(u64 dmac, int node, int bgx_idx, int lmac); diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c index cac86e9ae0dd..9dcc5765f11f 100644 --- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c @@ -369,7 +369,6 @@ static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb, { int ret; struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; - u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct dsaf_drv_mac_single_dest_entry mac_entry; /* directy return ok in debug network mode */ @@ -377,7 +376,7 @@ static int hns_mac_port_config_bc_en(struct hns_mac_cb *mac_cb, return 0; if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { - memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + eth_broadcast_addr(mac_entry.addr); mac_entry.in_vlan_id = vlan_id; mac_entry.in_port_num = mac_cb->mac_id; mac_entry.port_num = port_num; @@ -404,7 +403,6 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable) int ret; struct dsaf_device *dsaf_dev = mac_cb->dsaf_dev; u8 port_num; - u8 addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; struct mac_entry_idx *uc_mac_entry; struct dsaf_drv_mac_single_dest_entry mac_entry; @@ -414,7 +412,7 @@ int hns_mac_vm_config_bc_en(struct hns_mac_cb *mac_cb, u32 vmid, bool enable) uc_mac_entry = &mac_cb->addr_entry_idx[vmid]; if (!HNS_DSAF_IS_DEBUG(dsaf_dev)) { - memcpy(mac_entry.addr, addr, sizeof(mac_entry.addr)); + eth_broadcast_addr(mac_entry.addr); mac_entry.in_vlan_id = uc_mac_entry->vlan_id; mac_entry.in_port_num = mac_cb->mac_id; ret = hns_mac_get_inner_port_num(mac_cb, vmid, &port_num); diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index a31b4adf6e6a..8c55965a66ac 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1614,10 +1614,6 @@ static void hns3_remove(struct pci_dev *pdev) struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev); hnae3_unregister_ae_dev(ae_dev); - - devm_kfree(&pdev->dev, ae_dev); - - pci_set_drvdata(pdev, NULL); } static struct pci_driver hns3_driver = { diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c index 2d5d4aea3bcb..7cb794094a70 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c @@ -1,5 +1,5 @@ /* - * Amlogic Meson8b and GXBB DWMAC glue layer + * Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer * * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com> * @@ -318,6 +318,7 @@ err_remove_config_dt: static const struct of_device_id meson8b_dwmac_match[] = { { .compatible = "amlogic,meson8b-dwmac" }, + { .compatible = "amlogic,meson8m2-dwmac" }, { .compatible = "amlogic,meson-gxbb-dwmac" }, { } }; @@ -335,5 +336,5 @@ static struct platform_driver meson8b_dwmac_driver = { module_platform_driver(meson8b_dwmac_driver); MODULE_AUTHOR("Martin Blumenstingl <martin.blumenstingl@googlemail.com>"); -MODULE_DESCRIPTION("Amlogic Meson8b and GXBB DWMAC glue layer"); +MODULE_DESCRIPTION("Amlogic Meson8b, Meson8m2 and GXBB DWMAC glue layer"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/hyperv/rndis_filter.c b/drivers/net/hyperv/rndis_filter.c index 4a4952363e8a..e2b68d9328a7 100644 --- a/drivers/net/hyperv/rndis_filter.c +++ b/drivers/net/hyperv/rndis_filter.c @@ -365,14 +365,15 @@ static inline void *rndis_get_ppi(struct rndis_packet *rpkt, u32 type) static int rndis_filter_receive_data(struct net_device *ndev, struct netvsc_device *nvdev, - struct rndis_message *msg, struct vmbus_channel *channel, - void *data, u32 data_buflen) + struct rndis_message *msg, + u32 data_buflen) { struct rndis_packet *rndis_pkt = &msg->msg.pkt; const struct ndis_tcp_ip_checksum_info *csum_info; const struct ndis_pkt_8021q_info *vlan; u32 data_offset; + void *data; /* Remove the rndis header and pass it back up the stack */ data_offset = RNDIS_HEADER_SIZE + rndis_pkt->data_offset; @@ -393,14 +394,15 @@ static int rndis_filter_receive_data(struct net_device *ndev, vlan = rndis_get_ppi(rndis_pkt, IEEE_8021Q_INFO); + csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); + + data = (void *)msg + data_offset; + /* * Remove the rndis trailer padding from rndis packet message * rndis_pkt->data_len tell us the real data length, we only copy * the data packet to the stack, without the rndis trailer padding */ - data = (void *)((unsigned long)data + data_offset); - csum_info = rndis_get_ppi(rndis_pkt, TCPIP_CHKSUM_PKTINFO); - return netvsc_recv_callback(ndev, nvdev, channel, data, rndis_pkt->data_len, csum_info, vlan); @@ -419,8 +421,8 @@ int rndis_filter_receive(struct net_device *ndev, switch (rndis_msg->ndis_msg_type) { case RNDIS_MSG_PACKET: - return rndis_filter_receive_data(ndev, net_dev, rndis_msg, - channel, data, buflen); + return rndis_filter_receive_data(ndev, net_dev, channel, + rndis_msg, buflen); case RNDIS_MSG_INIT_C: case RNDIS_MSG_QUERY_C: case RNDIS_MSG_SET_C: diff --git a/drivers/net/ifb.c b/drivers/net/ifb.c index 0008da7e9d4c..5f2897ec0edc 100644 --- a/drivers/net/ifb.c +++ b/drivers/net/ifb.c @@ -330,6 +330,7 @@ static int __init ifb_init_module(void) { int i, err; + down_write(&pernet_ops_rwsem); rtnl_lock(); err = __rtnl_link_register(&ifb_link_ops); if (err < 0) @@ -344,6 +345,7 @@ static int __init ifb_init_module(void) out: rtnl_unlock(); + up_write(&pernet_ops_rwsem); return err; } diff --git a/drivers/net/netdevsim/devlink.c b/drivers/net/netdevsim/devlink.c index bbdcf064ba10..27ae05c5fdaf 100644 --- a/drivers/net/netdevsim/devlink.c +++ b/drivers/net/netdevsim/devlink.c @@ -218,22 +218,22 @@ void nsim_devlink_teardown(struct netdevsim *ns) } } -void nsim_devlink_setup(struct netdevsim *ns) +int nsim_devlink_setup(struct netdevsim *ns) { struct net *net = nsim_to_net(ns); bool *reg_devlink = net_generic(net, nsim_devlink_id); struct devlink *devlink; - int err = -ENOMEM; + int err; /* only one device per namespace controls devlink */ if (!*reg_devlink) { ns->devlink = NULL; - return; + return 0; } devlink = devlink_alloc(&nsim_devlink_ops, 0); if (!devlink) - return; + return -ENOMEM; err = devlink_register(devlink, &ns->dev); if (err) @@ -247,12 +247,14 @@ void nsim_devlink_setup(struct netdevsim *ns) *reg_devlink = false; - return; + return 0; err_dl_unregister: devlink_unregister(devlink); err_devlink_free: devlink_free(devlink); + + return err; } /* Initialize per network namespace state */ diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 8b30ab3ea2c2..ec68f38213d9 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -167,10 +167,14 @@ static int nsim_init(struct net_device *dev) SET_NETDEV_DEV(dev, &ns->dev); - nsim_devlink_setup(ns); + err = nsim_devlink_setup(ns); + if (err) + goto err_unreg_dev; return 0; +err_unreg_dev: + device_unregister(&ns->dev); err_bpf_uninit: nsim_bpf_uninit(ns); err_debugfs_destroy: diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h index afb8cf90c0fd..3a8581af3b85 100644 --- a/drivers/net/netdevsim/netdevsim.h +++ b/drivers/net/netdevsim/netdevsim.h @@ -117,7 +117,7 @@ enum nsim_resource_id { NSIM_RESOURCE_IPV6_FIB_RULES, }; -void nsim_devlink_setup(struct netdevsim *ns); +int nsim_devlink_setup(struct netdevsim *ns); void nsim_devlink_teardown(struct netdevsim *ns); int nsim_devlink_init(void); @@ -128,8 +128,9 @@ void nsim_fib_exit(void); u64 nsim_fib_get_val(struct net *net, enum nsim_resource_id res_id, bool max); int nsim_fib_set_max(struct net *net, enum nsim_resource_id res_id, u64 val); #else -static inline void nsim_devlink_setup(struct netdevsim *ns) +static inline int nsim_devlink_setup(struct netdevsim *ns) { + return 0; } static inline void nsim_devlink_teardown(struct netdevsim *ns) |