Add a write_hw parameter to the VLAN add/delete HW filter functions and to stmmac_vlan_update(). This flag controls whether the actual hardware register accesses are performed. When set to false, only the software state is updated. The next commit will use this to defer hardware writes when the interface is down. No functional change. Signed-off-by: Ovidiu Panait --- v2 changes: none. drivers/net/ethernet/stmicro/stmmac/hwif.h | 6 ++-- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 25 +++++++++----- .../net/ethernet/stmicro/stmmac/stmmac_vlan.c | 34 ++++++++++++------- 3 files changed, 41 insertions(+), 24 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h index 0db96a387259..d7598c76251f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/hwif.h +++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h @@ -647,10 +647,12 @@ struct stmmac_vlan_ops { void (*set_hw_vlan_mode)(struct mac_device_info *hw); int (*add_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid); + __be16 proto, u16 vid, + bool write_hw); int (*del_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid); + __be16 proto, u16 vid, + bool write_hw); void (*restore_hw_vlan_rx_fltr)(struct net_device *dev, struct mac_device_info *hw); }; diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index a02575f67057..19c86e3b42cc 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -6751,7 +6751,8 @@ static u32 stmmac_vid_crc32_le(__le16 vid_le) return crc; } -static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) +static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double, + bool write_hw) { u32 crc, hash = 0; u16 pmatch = 0; @@ -6773,7 +6774,11 @@ static int stmmac_vlan_update(struct stmmac_priv *priv, bool is_double) hash = 0; } - return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, is_double); + if (write_hw) + return stmmac_update_vlan_hash(priv, priv->hw, hash, pmatch, + is_double); + + return 0; } /* FIXME: This may need RXC to be running, but it may be called with BH @@ -6795,17 +6800,18 @@ static int stmmac_vlan_rx_add_vid(struct net_device *ndev, __be16 proto, u16 vid set_bit(vid, priv->active_vlans); num_double_vlans = priv->num_double_vlans + is_double; - ret = stmmac_vlan_update(priv, num_double_vlans); + ret = stmmac_vlan_update(priv, num_double_vlans, true); if (ret) { clear_bit(vid, priv->active_vlans); goto err_pm_put; } if (priv->hw->num_vlan) { - ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); + ret = stmmac_add_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, + vid, true); if (ret) { clear_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, priv->num_double_vlans); + stmmac_vlan_update(priv, priv->num_double_vlans, true); goto err_pm_put; } } @@ -6837,17 +6843,18 @@ static int stmmac_vlan_rx_kill_vid(struct net_device *ndev, __be16 proto, u16 vi clear_bit(vid, priv->active_vlans); num_double_vlans = priv->num_double_vlans - is_double; - ret = stmmac_vlan_update(priv, num_double_vlans); + ret = stmmac_vlan_update(priv, num_double_vlans, true); if (ret) { set_bit(vid, priv->active_vlans); goto del_vlan_error; } if (priv->hw->num_vlan) { - ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, vid); + ret = stmmac_del_hw_vlan_rx_fltr(priv, ndev, priv->hw, proto, + vid, true); if (ret) { set_bit(vid, priv->active_vlans); - stmmac_vlan_update(priv, priv->num_double_vlans); + stmmac_vlan_update(priv, priv->num_double_vlans, true); goto del_vlan_error; } } @@ -6870,7 +6877,7 @@ static int stmmac_vlan_restore(struct stmmac_priv *priv) if (priv->hw->num_vlan) stmmac_restore_hw_vlan_rx_fltr(priv, priv->dev, priv->hw); - ret = stmmac_vlan_update(priv, priv->num_double_vlans); + ret = stmmac_vlan_update(priv, priv->num_double_vlans, true); if (ret) netdev_err(priv->dev, "Failed to restore VLANs\n"); diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c index fcc34867405e..f81015179d04 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_vlan.c @@ -53,7 +53,8 @@ static int vlan_write_filter(struct net_device *dev, static int vlan_add_hw_rx_fltr(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid) + __be16 proto, u16 vid, + bool write_hw) { int index = -1; u32 val = 0; @@ -76,7 +77,8 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev, } hw->vlan_filter[0] = vid; - vlan_write_single(dev, vid); + if (write_hw) + vlan_write_single(dev, vid); return 0; } @@ -97,17 +99,21 @@ static int vlan_add_hw_rx_fltr(struct net_device *dev, return -EPERM; } - ret = vlan_write_filter(dev, hw, index, val); + if (write_hw) { + ret = vlan_write_filter(dev, hw, index, val); + if (ret) + return ret; + } - if (!ret) - hw->vlan_filter[index] = val; + hw->vlan_filter[index] = val; - return ret; + return 0; } static int vlan_del_hw_rx_fltr(struct net_device *dev, struct mac_device_info *hw, - __be16 proto, u16 vid) + __be16 proto, u16 vid, + bool write_hw) { int i, ret = 0; @@ -115,7 +121,8 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev, if (hw->num_vlan == 1) { if ((hw->vlan_filter[0] & VLAN_TAG_VID) == vid) { hw->vlan_filter[0] = 0; - vlan_write_single(dev, 0); + if (write_hw) + vlan_write_single(dev, 0); } return 0; } @@ -124,12 +131,13 @@ static int vlan_del_hw_rx_fltr(struct net_device *dev, for (i = 0; i < hw->num_vlan; i++) { if ((hw->vlan_filter[i] & VLAN_TAG_DATA_VEN) && ((hw->vlan_filter[i] & VLAN_TAG_DATA_VID) == vid)) { - ret = vlan_write_filter(dev, hw, i, 0); + if (write_hw) { + ret = vlan_write_filter(dev, hw, i, 0); + if (ret) + return ret; + } - if (!ret) - hw->vlan_filter[i] = 0; - else - return ret; + hw->vlan_filter[i] = 0; } } -- 2.51.0