Skip to content

Commit c7ab0b8

Browse files
joabreudavem330
authored andcommitted
net: stmmac: Fallback to VLAN Perfect filtering if HASH is not available
If VLAN Hash Filtering is not available we can fallback to perfect filtering instead. Let's implement this in XGMAC and GMAC cores and let the user use this filter. VLAN VID=0 always passes filter so we check if more than 2 VLANs are created and return proper error code if so because perfect filtering only supports 1 VID at a time. Signed-off-by: Jose Abreu <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 04c1b4c commit c7ab0b8

File tree

4 files changed

+40
-9
lines changed

4 files changed

+40
-9
lines changed

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
733733
}
734734

735735
static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash,
736-
bool is_double)
736+
u16 perfect_match, bool is_double)
737737
{
738738
void __iomem *ioaddr = hw->pcsr;
739739

@@ -748,6 +748,16 @@ static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash,
748748
}
749749

750750
writel(value, ioaddr + GMAC_VLAN_TAG);
751+
} else if (perfect_match) {
752+
u32 value = GMAC_VLAN_ETV;
753+
754+
if (is_double) {
755+
value |= GMAC_VLAN_EDVLP;
756+
value |= GMAC_VLAN_ESVL;
757+
value |= GMAC_VLAN_DOVLTC;
758+
}
759+
760+
writel(value | perfect_match, ioaddr + GMAC_VLAN_TAG);
751761
} else {
752762
u32 value = readl(ioaddr + GMAC_VLAN_TAG);
753763

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

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw,
555555
}
556556

557557
static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
558-
bool is_double)
558+
u16 perfect_match, bool is_double)
559559
{
560560
void __iomem *ioaddr = hw->pcsr;
561561

@@ -576,6 +576,21 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
576576
}
577577

578578
writel(value, ioaddr + XGMAC_VLAN_TAG);
579+
} else if (perfect_match) {
580+
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
581+
582+
value |= XGMAC_FILTER_VTFE;
583+
584+
writel(value, ioaddr + XGMAC_PACKET_FILTER);
585+
586+
value = XGMAC_VLAN_ETV;
587+
if (is_double) {
588+
value |= XGMAC_VLAN_EDVLP;
589+
value |= XGMAC_VLAN_ESVL;
590+
value |= XGMAC_VLAN_DOVLTC;
591+
}
592+
593+
writel(value | perfect_match, ioaddr + XGMAC_VLAN_TAG);
579594
} else {
580595
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
581596

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,7 +357,7 @@ struct stmmac_ops {
357357
struct stmmac_rss *cfg, u32 num_rxq);
358358
/* VLAN */
359359
void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
360-
bool is_double);
360+
u16 perfect_match, bool is_double);
361361
void (*enable_vlan)(struct mac_device_info *hw, u32 type);
362362
/* TX Timestamp */
363363
int (*get_mac_tx_timestamp)(struct mac_device_info *hw, u64 *ts);

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

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4207,15 +4207,25 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le)
42074207
static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
42084208
{
42094209
u32 crc, hash = 0;
4210-
u16 vid;
4210+
int count = 0;
4211+
u16 vid = 0;
42114212

42124213
for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
42134214
__le16 vid_le = cpu_to_le16(vid);
42144215
crc = bitrev32(~stmmac_vid_crc32_le(vid_le)) >> 28;
42154216
hash |= (1 << crc);
4217+
count++;
4218+
}
4219+
4220+
if (!priv->dma_cap.vlhash) {
4221+
if (count > 2) /* VID = 0 always passes filter */
4222+
return -EOPNOTSUPP;
4223+
4224+
vid = cpu_to_le16(vid);
4225+
hash = 0;
42164226
}
42174227

4218-
return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double);
4228+
return stmmac_update_vlan_hash(priv, priv->hw, hash, vid, is_double);
42194229
}
42204230

42214231
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
@@ -4224,8 +4234,6 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
42244234
bool is_double = false;
42254235
int ret;
42264236

4227-
if (!priv->dma_cap.vlhash)
4228-
return -EOPNOTSUPP;
42294237
if (be16_to_cpu(proto) == ETH_P_8021AD)
42304238
is_double = true;
42314239

@@ -4244,8 +4252,6 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
42444252
struct stmmac_priv *priv = netdev_priv(ndev);
42454253
bool is_double = false;
42464254

4247-
if (!priv->dma_cap.vlhash)
4248-
return -EOPNOTSUPP;
42494255
if (be16_to_cpu(proto) == ETH_P_8021AD)
42504256
is_double = true;
42514257

0 commit comments

Comments
 (0)