Skip to content

Commit 0f11b10

Browse files
Ovidiu PanaitSasha Levin
authored andcommitted
net: stmmac: Improve double VLAN handling
[ Upstream commit e38200e ] The double VLAN bits (EDVLP, ESVL, DOVLTC) are handled inconsistently between the two vlan_update_hash() implementations: - dwxgmac2_update_vlan_hash() explicitly clears the double VLAN bits when is_double is false, meaning that adding a 802.1Q VLAN will disable double VLAN mode: $ ip link add link eth0 name eth0.200 type vlan id 200 protocol 802.1ad $ ip link add link eth0 name eth0.100 type vlan id 100 # Double VLAN bits no longer set - vlan_update_hash() sets these bits and only clears them when the last VLAN has been removed, so double VLAN mode remains enabled even after all 802.1AD VLANs are removed. Address both issues by tracking the number of active 802.1AD VLANs in priv->num_double_vlans. Pass this count to stmmac_vlan_update() so both implementations correctly set the double VLAN bits when any 802.1AD VLAN is active, and clear them only when none remain. Also update vlan_update_hash() to explicitly clear the double VLAN bits when is_double is false, matching the dwxgmac2 behavior. Signed-off-by: Ovidiu Panait <ovidiu.panait.rb@renesas.com> Link: https://patch.msgid.link/20260303145828.7845-3-ovidiu.panait.rb@renesas.com Signed-off-by: Jakub Kicinski <kuba@kernel.org> Stable-dep-of: bd7ad51 ("net: stmmac: Fix VLAN HW state restore") Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 4ab6023 commit 0f11b10

3 files changed

Lines changed: 21 additions & 4 deletions

File tree

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ struct stmmac_priv {
322322
void __iomem *ptpaddr;
323323
void __iomem *estaddr;
324324
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
325+
unsigned int num_double_vlans;
325326
int sfty_irq;
326327
int sfty_ce_irq;
327328
int sfty_ue_irq;

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

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6727,6 +6727,7 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
67276727
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
67286728
{
67296729
struct stmmac_priv *priv = netdev_priv(ndev);
6730+
unsigned int num_double_vlans;
67306731
bool is_double = false;
67316732
int ret;
67326733

@@ -6738,7 +6739,8 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
67386739
is_double = true;
67396740

67406741
set_bit(vid, priv->active_vlans);
6741-
ret = stmmac_vlan_update(priv, is_double);
6742+
num_double_vlans = priv->num_double_vlans + is_double;
6743+
ret = stmmac_vlan_update(priv, num_double_vlans);
67426744
if (ret) {
67436745
clear_bit(vid, priv->active_vlans);
67446746
goto err_pm_put;
@@ -6748,11 +6750,13 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
67486750
ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
67496751
if (ret) {
67506752
clear_bit(vid, priv->active_vlans);
6751-
stmmac_vlan_update(priv, is_double);
6753+
stmmac_vlan_update(priv, priv->num_double_vlans);
67526754
goto err_pm_put;
67536755
}
67546756
}
67556757

6758+
priv->num_double_vlans = num_double_vlans;
6759+
67566760
err_pm_put:
67576761
pm_runtime_put(priv->device);
67586762

@@ -6765,6 +6769,7 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
67656769
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
67666770
{
67676771
struct stmmac_priv *priv = netdev_priv(ndev);
6772+
unsigned int num_double_vlans;
67686773
bool is_double = false;
67696774
int ret;
67706775

@@ -6776,7 +6781,8 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
67766781
is_double = true;
67776782

67786783
clear_bit(vid, priv->active_vlans);
6779-
ret = stmmac_vlan_update(priv, is_double);
6784+
num_double_vlans = priv->num_double_vlans - is_double;
6785+
ret = stmmac_vlan_update(priv, num_double_vlans);
67806786
if (ret) {
67816787
set_bit(vid, priv->active_vlans);
67826788
goto del_vlan_error;
@@ -6786,11 +6792,13 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
67866792
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
67876793
if (ret) {
67886794
set_bit(vid, priv->active_vlans);
6789-
stmmac_vlan_update(priv, is_double);
6795+
stmmac_vlan_update(priv, priv->num_double_vlans);
67906796
goto del_vlan_error;
67916797
}
67926798
}
67936799

6800+
priv->num_double_vlans = num_double_vlans;
6801+
67946802
del_vlan_error:
67956803
pm_runtime_put(priv->device);
67966804

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

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,10 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
183183
value |= VLAN_EDVLP;
184184
value |= VLAN_ESVL;
185185
value |= VLAN_DOVLTC;
186+
} else {
187+
value &= ~VLAN_EDVLP;
188+
value &= ~VLAN_ESVL;
189+
value &= ~VLAN_DOVLTC;
186190
}
187191

188192
writel(value, ioaddr + VLAN_TAG);
@@ -193,6 +197,10 @@ static void vlan_update_hash(struct mac_device_info *hw, u32 hash,
193197
value |= VLAN_EDVLP;
194198
value |= VLAN_ESVL;
195199
value |= VLAN_DOVLTC;
200+
} else {
201+
value &= ~VLAN_EDVLP;
202+
value &= ~VLAN_ESVL;
203+
value &= ~VLAN_DOVLTC;
196204
}
197205

198206
writel(value | perfect_match, ioaddr + VLAN_TAG);

0 commit comments

Comments
 (0)