Skip to content

Commit e38200e

Browse files
Ovidiu Panaitkuba-moo
authored andcommitted
net: stmmac: Improve double VLAN handling
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>
1 parent 35dfedc commit e38200e

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
@@ -323,6 +323,7 @@ struct stmmac_priv {
323323
void __iomem *ptpaddr;
324324
void __iomem *estaddr;
325325
unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
326+
unsigned int num_double_vlans;
326327
int sfty_irq;
327328
int sfty_ce_irq;
328329
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
@@ -6775,6 +6775,7 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double)
67756775
static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid)
67766776
{
67776777
struct stmmac_priv *priv = netdev_priv(ndev);
6778+
unsigned int num_double_vlans;
67786779
bool is_double = false;
67796780
int ret;
67806781

@@ -6786,7 +6787,8 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
67866787
is_double = true;
67876788

67886789
set_bit(vid, priv->active_vlans);
6789-
ret = stmmac_vlan_update(priv, is_double);
6790+
num_double_vlans = priv->num_double_vlans + is_double;
6791+
ret = stmmac_vlan_update(priv, num_double_vlans);
67906792
if (ret) {
67916793
clear_bit(vid, priv->active_vlans);
67926794
goto err_pm_put;
@@ -6796,11 +6798,13 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
67966798
ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
67976799
if (ret) {
67986800
clear_bit(vid, priv->active_vlans);
6799-
stmmac_vlan_update(priv, is_double);
6801+
stmmac_vlan_update(priv, priv->num_double_vlans);
68006802
goto err_pm_put;
68016803
}
68026804
}
68036805

6806+
priv->num_double_vlans = num_double_vlans;
6807+
68046808
err_pm_put:
68056809
pm_runtime_put(priv->device);
68066810

@@ -6813,6 +6817,7 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid
68136817
static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vid)
68146818
{
68156819
struct stmmac_priv *priv = netdev_priv(ndev);
6820+
unsigned int num_double_vlans;
68166821
bool is_double = false;
68176822
int ret;
68186823

@@ -6824,7 +6829,8 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
68246829
is_double = true;
68256830

68266831
clear_bit(vid, priv->active_vlans);
6827-
ret = stmmac_vlan_update(priv, is_double);
6832+
num_double_vlans = priv->num_double_vlans - is_double;
6833+
ret = stmmac_vlan_update(priv, num_double_vlans);
68286834
if (ret) {
68296835
set_bit(vid, priv->active_vlans);
68306836
goto del_vlan_error;
@@ -6834,11 +6840,13 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi
68346840
ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid);
68356841
if (ret) {
68366842
set_bit(vid, priv->active_vlans);
6837-
stmmac_vlan_update(priv, is_double);
6843+
stmmac_vlan_update(priv, priv->num_double_vlans);
68386844
goto del_vlan_error;
68396845
}
68406846
}
68416847

6848+
priv->num_double_vlans = num_double_vlans;
6849+
68426850
del_vlan_error:
68436851
pm_runtime_put(priv->device);
68446852

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)