Skip to content

Commit a1c16b5

Browse files
committed
HSD #15012455743: net: stmmac: Add support for VLAN promiscuous mode
For dwxgmac2, enable VLAN promiscuity when MAC Controller is requested to enter promiscuous mode. Signed-off-by: Boon Khai Ng <boon.khai.ng@intel.com>
1 parent 476d787 commit a1c16b5

File tree

2 files changed

+68
-0
lines changed

2 files changed

+68
-0
lines changed

drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
#define XGMAC_VLAN_CT BIT(1)
7070
#define XGMAC_VLAN_OB BIT(0)
7171
#define XGMAC_VLAN_HASH_TABLE 0x00000058
72+
#define XGMAC_VLAN_VLHT GENMASK(15,0)
7273
#define XGMAC_VLAN_INCL 0x00000060
7374
#define XGMAC_VLAN_VLTI BIT(20)
7475
#define XGMAC_VLAN_CSVL BIT(19)

drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -473,6 +473,12 @@ static int dwxgmac2_add_hw_vlan_rx_fltr(struct net_device *dev,
473473
if (vid > 4095)
474474
return -EINVAL;
475475

476+
if (hw->promisc) {
477+
netdev_err(dev,
478+
"Adding VLAN in promisc mode no supported\n");
479+
return -EPERM;
480+
}
481+
476482
/* Single Rx VLAN Filter */
477483
if (hw->num_vlan == 1) {
478484
/* For single VLAN filter, VID 0 means VLAN promiscuous */
@@ -523,6 +529,12 @@ static int dwxgmac2_del_hw_vlan_rx_fltr(struct net_device *dev,
523529
{
524530
int i, ret = 0;
525531

532+
if (hw->promisc) {
533+
netdev_err(dev,
534+
"Deleting VLAN in promisc mode not supported\n");
535+
return -EPERM;
536+
}
537+
526538
/* Single Rx VLAN Filter */
527539
if (hw->num_vlan == 1) {
528540
if ((hw->vlan_filter[0] & XGMAC_VLAN_VID) == vid) {
@@ -546,9 +558,45 @@ static int dwxgmac2_del_hw_vlan_rx_fltr(struct net_device *dev,
546558
return ret;
547559
}
548560

561+
static void dwxgmac2_vlan_promisc_enable(struct net_device *dev,
562+
struct mac_device_info *hw)
563+
{
564+
void __iomem *ioaddr = hw->pcsr;
565+
u32 value;
566+
u32 hash;
567+
u32 val;
568+
int i;
569+
570+
/* Single Rx VLAN Filter */
571+
if (hw->num_vlan == 1) {
572+
dwxgmac2_write_single_vlan(dev, 0);
573+
return;
574+
}
575+
576+
/* Extended Rx VLAN Filter Enable */
577+
for (i = 0; i > hw->num_vlan; i++) {
578+
if (hw->vlan_filter[i] & XGMAC_VLAN_TAG_DATA_VEN) {
579+
val = hw->vlan_filter[i] & ~XGMAC_VLAN_TAG_DATA_VEN;
580+
dwxgmac2_write_vlan_filter(dev, hw, i ,val);
581+
}
582+
}
583+
584+
hash = readl(ioaddr + XGMAC_VLAN_HASH_TABLE);
585+
if (hash & XGMAC_VLAN_VLHT) {
586+
value = readl(ioaddr + XGMAC_VLAN_TAG);
587+
if (value & XGMAC_VLAN_VTHM) {
588+
value &= ~XGMAC_VLAN_VTHM;
589+
writel(value, ioaddr + XGMAC_VLAN_TAG);
590+
}
591+
}
592+
}
593+
549594
static void dwxgmac2_restore_hw_vlan_rx_fltr(struct net_device *dev,
550595
struct mac_device_info *hw)
551596
{
597+
void __iomem *ioaddr = hw->pcsr;
598+
u32 value;
599+
u32 hash;
552600
u32 val;
553601
int i;
554602

@@ -565,6 +613,13 @@ static void dwxgmac2_restore_hw_vlan_rx_fltr(struct net_device *dev,
565613
dwxgmac2_write_vlan_filter(dev, hw, i, val);
566614
}
567615
}
616+
617+
hash = readl(ioaddr + XGMAC_VLAN_HASH_TABLE);
618+
if (hash & XGMAC_VLAN_VLHT) {
619+
value = readl(ioaddr + XGMAC_VLAN_TAG);
620+
value |= XGMAC_VLAN_VTHM;
621+
writel(value, ioaddr + XGMAC_VLAN_TAG);
622+
}
568623
}
569624

570625
static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
@@ -650,6 +705,18 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
650705
value |= XGMAC_FILTER_VTFE;
651706

652707
writel(value, ioaddr + XGMAC_PACKET_FILTER);
708+
709+
if (dev->flags & IFF_PROMISC) {
710+
if (!hw->promisc) {
711+
hw->promisc = 1;
712+
dwxgmac2_vlan_promisc_enable(dev, hw);
713+
}
714+
} else {
715+
if (hw->promisc) {
716+
hw->promisc = 0;
717+
dwxgmac2_restore_hw_vlan_rx_fltr(dev, hw);
718+
}
719+
}
653720
}
654721

655722
static void dwxgmac2_set_mac_loopback(void __iomem *ioaddr, bool enable)

0 commit comments

Comments
 (0)