Skip to content

Commit 476d787

Browse files
committed
HSD #15012455743: net: stmmac: Add support for VLAN Rx filtering
Add support for VLAN ID-based filtering by the MAC controller for MAC drivers that support it. Only the 12-bit VID field is used. Signed-off-by: Boon Khai Ng <boon.khai.ng@intel.com>
1 parent 81c1113 commit 476d787

File tree

2 files changed

+211
-2
lines changed

2 files changed

+211
-2
lines changed

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

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@
6464
#define XGMAC_VLAN_ESVL BIT(18)
6565
#define XGMAC_VLAN_ETV BIT(16)
6666
#define XGMAC_VLAN_VID GENMASK(15, 0)
67+
#define XGMAC_VLAN_OFS GENMASK(6, 2)
68+
#define XGMAC_VLAN_OFS_SHIFT 2
69+
#define XGMAC_VLAN_CT BIT(1)
70+
#define XGMAC_VLAN_OB BIT(0)
6771
#define XGMAC_VLAN_HASH_TABLE 0x00000058
6872
#define XGMAC_VLAN_INCL 0x00000060
6973
#define XGMAC_VLAN_VLTI BIT(20)
@@ -149,6 +153,7 @@
149153
#define XGMAC_HWFEAT_FRPES GENMASK(12, 11)
150154
#define XGMAC_HWFEAT_FRPPB GENMASK(10, 9)
151155
#define XGMAC_HWFEAT_FRPSEL BIT(3)
156+
#define XGMAC_HWFEAT_NRVF GENMASK(2, 0)
152157
#define XGMAC_MAC_DPP_FSM_INT_STATUS 0x00000150
153158
#define XGMAC_MAC_FSM_CONTROL 0x00000158
154159
#define XGMAC_PRTYEN BIT(1)
@@ -477,7 +482,8 @@
477482
/* RDES0 (write back format) */
478483
#define XGMAC_RDES0_VLAN_TAG_MASK GENMASK(15,0)
479484

480-
/* MAC VLAN Tag Control */
485+
/* MAC VLAN Tag Control and VLAN Tag Data */
486+
#define XGMAC_VLAN_TAG_CTRL 0x00000050
481487
#define XGMAC_VLAN_TAG_CTRL_OB BIT(0)
482488
#define XGMAC_VLAN_TAG_CTRL_CT BIT(1)
483489
#define XGMAC_VLAN_TAG_CTRL_OFS_MASK GENMASK(6, 2)
@@ -491,6 +497,11 @@
491497
#define XGMAC_VLAN_TAG_STRIP_FAIL (0x2 << XGMAC_VLAN_TAG_CTRL_EVLS_SHIFT)
492498
#define XGMAC_VLAN_TAG_STRIP_ALL (0x3 << XGMAC_VLAN_TAG_CTRL_EVLS_SHIFT)
493499

500+
#define XGMAC_VLAN_TAG_DATA 0x00000054
501+
#define XGMAC_VLAN_TAG_DATA_ETV BIT(17)
502+
#define XGMAC_VLAN_TAG_DATA_VEN BIT(16)
503+
#define XGMAC_VLAN_TAG_DATA_VID GENMASK(15, 0)
504+
494505
/* Error Type or L2 Type(ET/LT) Field Number */
495506
#define XGMAC_ET_LT_VLAN_STAG 8
496507
#define XGMAC_ET_LT_VLAN_CTAG 9
@@ -499,4 +510,12 @@
499510
#define XGMAC_ET_LT_DVLAN_CTAG_STAG 12
500511
#define XGMAC_ET_LT_DVLAN_STAG_CTAG 13
501512

513+
/* EXT VLAN Filtering HW FEAT */
514+
#define XGMAC_HWFEAT_NO_EXT 0
515+
#define XGMAC_HWFEAT_EXT_VLAN_4 1
516+
#define XGMAC_HWFEAT_EXT_VLAN_8 2
517+
#define XGMAC_HWFEAT_EXT_VLAN_16 3
518+
#define XGMAC_HWFEAT_EXT_VLAN_24 4
519+
#define XGMAC_HWFEAT_EXT_VLAN_32 5
520+
502521
#endif /* __STMMAC_DWXGMAC2_H__ */

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

Lines changed: 191 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,158 @@ static void dwxgmac2_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
415415
writel(value, ioaddr + XGMAC_LPI_TIMER_CTRL);
416416
}
417417

418+
static void dwxgmac2_write_single_vlan(struct net_device *dev, u16 vid)
419+
{
420+
void __iomem *ioaddr = (void __iomem *)dev->base_addr;
421+
u32 val;
422+
423+
val = readl(ioaddr + XGMAC_VLAN_TAG);
424+
val &= ~XGMAC_VLAN_VID;
425+
val |= XGMAC_VLAN_ETV | vid;
426+
427+
writel(val, ioaddr + XGMAC_VLAN_TAG);
428+
}
429+
430+
static int dwxgmac2_write_vlan_filter(struct net_device *dev,
431+
struct mac_device_info *hw,
432+
u8 index, u32 data)
433+
{
434+
void __iomem *ioaddr = (void __iomem *)dev->base_addr;
435+
int i, timeout = 10;
436+
u32 val;
437+
438+
if (index >= hw->num_vlan)
439+
return -EINVAL;
440+
441+
writel(data, ioaddr + XGMAC_VLAN_TAG_DATA);
442+
443+
val = readl(ioaddr + XGMAC_VLAN_TAG);
444+
val &= ~(XGMAC_VLAN_TAG_CTRL_OFS_MASK |
445+
XGMAC_VLAN_CT |
446+
XGMAC_VLAN_OB);
447+
448+
val |= (index << XGMAC_VLAN_OFS_SHIFT | XGMAC_VLAN_OB);
449+
450+
writel(val, ioaddr + XGMAC_VLAN_TAG);
451+
452+
for (i = 0; i < timeout; i++) {
453+
val = readl(ioaddr + XGMAC_VLAN_TAG);
454+
if(!(val & XGMAC_VLAN_OB))
455+
return 0;
456+
udelay(1);
457+
458+
}
459+
460+
netdev_err(dev, "Timeout accesing MAC_VLAN_TAG_FILTER\n");
461+
462+
return -EBUSY;
463+
}
464+
465+
static int dwxgmac2_add_hw_vlan_rx_fltr(struct net_device *dev,
466+
struct mac_device_info *hw,
467+
__be16 proto, u16 vid)
468+
{
469+
int index = -1;
470+
u32 val = 0;
471+
int i, ret;
472+
473+
if (vid > 4095)
474+
return -EINVAL;
475+
476+
/* Single Rx VLAN Filter */
477+
if (hw->num_vlan == 1) {
478+
/* For single VLAN filter, VID 0 means VLAN promiscuous */
479+
if (vid == 0) {
480+
netdev_warn(dev, "Adding VLAN ID 0 is not supported\n");
481+
return -EPERM;
482+
}
483+
484+
if (hw->vlan_filter[0] & XGMAC_VLAN_VID) {
485+
netdev_err(dev, "Only single VLAN ID supported\n");
486+
return -EPERM;
487+
}
488+
489+
hw->vlan_filter[0] = vid;
490+
dwxgmac2_write_single_vlan(dev, vid);
491+
492+
return 0;
493+
}
494+
495+
/* Extended Rx VLAN Filter Enable */
496+
val |= XGMAC_VLAN_TAG_DATA_ETV | XGMAC_VLAN_TAG_DATA_VEN | vid;
497+
498+
for (i = 0; i < hw->num_vlan; i++) {
499+
if (hw->vlan_filter[i] == val)
500+
return 0;
501+
502+
else if(!(hw->vlan_filter[i] & XGMAC_VLAN_TAG_DATA_VEN))
503+
index = i;
504+
}
505+
506+
if (index == -1){
507+
netdev_err(dev, "MAC_VLAN_TAG_FILTER full (size: %0u)\n",
508+
hw->num_vlan);
509+
return -EPERM;
510+
}
511+
512+
ret = dwxgmac2_write_vlan_filter(dev, hw, index, val);
513+
514+
if (!ret)
515+
hw->vlan_filter[index] = val;
516+
517+
return ret;
518+
}
519+
520+
static int dwxgmac2_del_hw_vlan_rx_fltr(struct net_device *dev,
521+
struct mac_device_info *hw,
522+
__be16 proto, u16 vid)
523+
{
524+
int i, ret = 0;
525+
526+
/* Single Rx VLAN Filter */
527+
if (hw->num_vlan == 1) {
528+
if ((hw->vlan_filter[0] & XGMAC_VLAN_VID) == vid) {
529+
hw->vlan_filter[0] = 0;
530+
dwxgmac2_write_single_vlan(dev, 0);
531+
}
532+
return 0;
533+
}
534+
535+
/* Extended Rx VLAN Filter Enable */
536+
for (i = 0; i < hw->num_vlan; i++) {
537+
if((hw->vlan_filter[i] & XGMAC_VLAN_TAG_DATA_VID) == vid) {
538+
ret = dwxgmac2_write_vlan_filter(dev, hw, i, 0);
539+
540+
if (!ret)
541+
hw->vlan_filter[i] = 0;
542+
else
543+
return ret;
544+
}
545+
}
546+
return ret;
547+
}
548+
549+
static void dwxgmac2_restore_hw_vlan_rx_fltr(struct net_device *dev,
550+
struct mac_device_info *hw)
551+
{
552+
u32 val;
553+
int i;
554+
555+
/* Single Rx VLAN Filter */
556+
if (hw->num_vlan == 1) {
557+
dwxgmac2_write_single_vlan(dev, hw->vlan_filter[0]);
558+
return;
559+
}
560+
561+
/* Extended Rx VLAN Filter Enable */
562+
for (i = 0; i < hw->num_vlan; i++) {
563+
if (hw->vlan_filter[i] & XGMAC_VLAN_TAG_DATA_VEN) {
564+
val = hw->vlan_filter[i];
565+
dwxgmac2_write_vlan_filter(dev, hw, i, val);
566+
}
567+
}
568+
}
569+
418570
static void dwxgmac2_set_mchash(void __iomem *ioaddr, u32 *mcfilterbits,
419571
int mcbitslog2)
420572
{
@@ -493,6 +645,10 @@ static void dwxgmac2_set_filter(struct mac_device_info *hw,
493645
}
494646
}
495647

648+
/* VLAN Filtering */
649+
if (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)
650+
value |= XGMAC_FILTER_VTFE;
651+
496652
writel(value, ioaddr + XGMAC_PACKET_FILTER);
497653
}
498654

@@ -1528,6 +1684,9 @@ const struct stmmac_ops dwxgmac210_ops = {
15281684
.enable_vlan = dwxgmac2_enable_vlan,
15291685
.config_l3_filter = dwxgmac2_config_l3_filter,
15301686
.config_l4_filter = dwxgmac2_config_l4_filter,
1687+
.add_hw_vlan_rx_fltr = dwxgmac2_add_hw_vlan_rx_fltr,
1688+
.del_hw_vlan_rx_fltr = dwxgmac2_del_hw_vlan_rx_fltr,
1689+
.restore_hw_vlan_rx_fltr = dwxgmac2_restore_hw_vlan_rx_fltr,
15311690
.set_arp_offload = dwxgmac2_set_arp_offload,
15321691
.est_configure = dwxgmac3_est_configure,
15331692
.fpe_configure = dwxgmac3_fpe_configure,
@@ -1598,6 +1757,37 @@ const struct stmmac_ops dwxlgmac2_ops = {
15981757
.set_hw_vlan_mode = dwxgmac2_set_hw_vlan_mode,
15991758
};
16001759

1760+
static u32 dwxgmac2_get_num_vlan(void __iomem *ioaddr)
1761+
{
1762+
u32 val, num_vlan;
1763+
1764+
val = readl(ioaddr + XGMAC_HW_FEATURE3);
1765+
switch (val & XGMAC_HWFEAT_NRVF) {
1766+
case 0:
1767+
num_vlan = 1;
1768+
break;
1769+
case 1:
1770+
num_vlan = 4;
1771+
break;
1772+
case 2:
1773+
num_vlan = 8;
1774+
break;
1775+
case 3:
1776+
num_vlan = 16;
1777+
break;
1778+
case 4:
1779+
num_vlan = 24;
1780+
break;
1781+
case 5:
1782+
num_vlan = 32;
1783+
break;
1784+
default:
1785+
num_vlan = 1;
1786+
}
1787+
1788+
return num_vlan;
1789+
}
1790+
16011791
int dwxgmac2_setup(struct stmmac_priv *priv)
16021792
{
16031793
struct mac_device_info *mac = priv->hw;
@@ -1631,7 +1821,7 @@ int dwxgmac2_setup(struct stmmac_priv *priv)
16311821
mac->mii.reg_mask = GENMASK(15, 0);
16321822
mac->mii.clk_csr_shift = 19;
16331823
mac->mii.clk_csr_mask = GENMASK(21, 19);
1634-
1824+
mac->num_vlan = dwxgmac2_get_num_vlan(priv->ioaddr);
16351825
return 0;
16361826
}
16371827

0 commit comments

Comments
 (0)