mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-19 00:16:57 +07:00
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 <joabreu@synopsys.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
04c1b4c70d
commit
c7ab0b8088
@ -733,7 +733,7 @@ static void dwmac4_set_mac_loopback(void __iomem *ioaddr, bool enable)
|
||||
}
|
||||
|
||||
static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash,
|
||||
bool is_double)
|
||||
u16 perfect_match, bool is_double)
|
||||
{
|
||||
void __iomem *ioaddr = hw->pcsr;
|
||||
|
||||
@ -748,6 +748,16 @@ static void dwmac4_update_vlan_hash(struct mac_device_info *hw, u32 hash,
|
||||
}
|
||||
|
||||
writel(value, ioaddr + GMAC_VLAN_TAG);
|
||||
} else if (perfect_match) {
|
||||
u32 value = GMAC_VLAN_ETV;
|
||||
|
||||
if (is_double) {
|
||||
value |= GMAC_VLAN_EDVLP;
|
||||
value |= GMAC_VLAN_ESVL;
|
||||
value |= GMAC_VLAN_DOVLTC;
|
||||
}
|
||||
|
||||
writel(value | perfect_match, ioaddr + GMAC_VLAN_TAG);
|
||||
} else {
|
||||
u32 value = readl(ioaddr + GMAC_VLAN_TAG);
|
||||
|
||||
|
@ -555,7 +555,7 @@ static int dwxgmac2_rss_configure(struct mac_device_info *hw,
|
||||
}
|
||||
|
||||
static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
|
||||
bool is_double)
|
||||
u16 perfect_match, bool is_double)
|
||||
{
|
||||
void __iomem *ioaddr = hw->pcsr;
|
||||
|
||||
@ -576,6 +576,21 @@ static void dwxgmac2_update_vlan_hash(struct mac_device_info *hw, u32 hash,
|
||||
}
|
||||
|
||||
writel(value, ioaddr + XGMAC_VLAN_TAG);
|
||||
} else if (perfect_match) {
|
||||
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
|
||||
|
||||
value |= XGMAC_FILTER_VTFE;
|
||||
|
||||
writel(value, ioaddr + XGMAC_PACKET_FILTER);
|
||||
|
||||
value = XGMAC_VLAN_ETV;
|
||||
if (is_double) {
|
||||
value |= XGMAC_VLAN_EDVLP;
|
||||
value |= XGMAC_VLAN_ESVL;
|
||||
value |= XGMAC_VLAN_DOVLTC;
|
||||
}
|
||||
|
||||
writel(value | perfect_match, ioaddr + XGMAC_VLAN_TAG);
|
||||
} else {
|
||||
u32 value = readl(ioaddr + XGMAC_PACKET_FILTER);
|
||||
|
||||
|
@ -357,7 +357,7 @@ struct stmmac_ops {
|
||||
struct stmmac_rss *cfg, u32 num_rxq);
|
||||
/* VLAN */
|
||||
void (*update_vlan_hash)(struct mac_device_info *hw, u32 hash,
|
||||
bool is_double);
|
||||
u16 perfect_match, bool is_double);
|
||||
void (*enable_vlan)(struct mac_device_info *hw, u32 type);
|
||||
/* TX Timestamp */
|
||||
int (*get_mac_tx_timestamp)(struct mac_device_info *hw, u64 *ts);
|
||||
|
@ -4207,15 +4207,25 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le)
|
||||
static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
|
||||
{
|
||||
u32 crc, hash = 0;
|
||||
u16 vid;
|
||||
int count = 0;
|
||||
u16 vid = 0;
|
||||
|
||||
for_each_set_bit(vid, priv->active_vlans, VLAN_N_VID) {
|
||||
__le16 vid_le = cpu_to_le16(vid);
|
||||
crc = bitrev32(~stmmac_vid_crc32_le(vid_le)) >> 28;
|
||||
hash |= (1 << crc);
|
||||
count++;
|
||||
}
|
||||
|
||||
return stmmac_update_vlan_hash(priv, priv->hw, hash, is_double);
|
||||
if (!priv->dma_cap.vlhash) {
|
||||
if (count > 2) /* VID = 0 always passes filter */
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
vid = cpu_to_le16(vid);
|
||||
hash = 0;
|
||||
}
|
||||
|
||||
return stmmac_update_vlan_hash(priv, priv->hw, hash, vid, is_double);
|
||||
}
|
||||
|
||||
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
|
||||
bool is_double = false;
|
||||
int ret;
|
||||
|
||||
if (!priv->dma_cap.vlhash)
|
||||
return -EOPNOTSUPP;
|
||||
if (be16_to_cpu(proto) == ETH_P_8021AD)
|
||||
is_double = true;
|
||||
|
||||
@ -4244,8 +4252,6 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
|
||||
struct stmmac_priv *priv = netdev_priv(ndev);
|
||||
bool is_double = false;
|
||||
|
||||
if (!priv->dma_cap.vlhash)
|
||||
return -EOPNOTSUPP;
|
||||
if (be16_to_cpu(proto) == ETH_P_8021AD)
|
||||
is_double = true;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user