]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net: aquantia: fix vlans not working over bridged network
authorDmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Sat, 22 Jun 2019 08:46:37 +0000 (08:46 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 26 Jun 2019 20:16:45 +0000 (13:16 -0700)
In configuration of vlan over bridge over aquantia device
it was found that vlan tagged traffic is dropped on chip.

The reason is that bridge device enables promisc mode,
but in atlantic chip vlan filters will still apply.
So we have to corellate promisc settings with vlan configuration.

The solution is to track in a separate state variable the
need of vlan forced promisc. And also consider generic
promisc configuration when doing vlan filter config.

Fixes: 7975d2aff5af ("net: aquantia: add support of rx-vlan-filter offload")
Signed-off-by: Dmitry Bogdanov <dmitry.bogdanov@aquantia.com>
Signed-off-by: Igor Russkikh <igor.russkikh@aquantia.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/aquantia/atlantic/aq_filters.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.c
drivers/net/ethernet/aquantia/atlantic/aq_nic.h
drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c

index 18bc035da850eb4d9555602f7422d419859ee3f7..1fff462a4175e87eba57e7d7e63b2bbf9bf0e16a 100644 (file)
@@ -843,9 +843,14 @@ int aq_filters_vlans_update(struct aq_nic_s *aq_nic)
                return err;
 
        if (aq_nic->ndev->features & NETIF_F_HW_VLAN_CTAG_FILTER) {
-               if (hweight < AQ_VLAN_MAX_FILTERS)
-                       err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw, true);
+               if (hweight < AQ_VLAN_MAX_FILTERS && hweight > 0) {
+                       err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw,
+                               !(aq_nic->packet_filter & IFF_PROMISC));
+                       aq_nic->aq_nic_cfg.is_vlan_force_promisc = false;
+               } else {
                /* otherwise left in promiscue mode */
+                       aq_nic->aq_nic_cfg.is_vlan_force_promisc = true;
+               }
        }
 
        return err;
@@ -866,6 +871,7 @@ int aq_filters_vlan_offload_off(struct aq_nic_s *aq_nic)
        if (unlikely(!aq_hw_ops->hw_filter_vlan_ctrl))
                return -EOPNOTSUPP;
 
+       aq_nic->aq_nic_cfg.is_vlan_force_promisc = true;
        err = aq_hw_ops->hw_filter_vlan_ctrl(aq_hw, false);
        if (err)
                return err;
index 0da5e161ec5d532d24c3b6556548fca0d23e2640..41172fbebddd3c5cb14307b4e3c691ef044eac9b 100644 (file)
@@ -126,6 +126,7 @@ void aq_nic_cfg_start(struct aq_nic_s *self)
 
        cfg->link_speed_msk &= cfg->aq_hw_caps->link_speed_msk;
        cfg->features = cfg->aq_hw_caps->hw_features;
+       cfg->is_vlan_force_promisc = true;
 }
 
 static int aq_nic_update_link_status(struct aq_nic_s *self)
index eb2e3c7c36f95c94189e23e8d66bdd4e48963d26..0f22f5d5691b30c1ba025b7a9c5eb65339c0f798 100644 (file)
@@ -35,6 +35,7 @@ struct aq_nic_cfg_s {
        u32 flow_control;
        u32 link_speed_msk;
        u32 wol;
+       bool is_vlan_force_promisc;
        u16 is_mc_list_enabled;
        u16 mc_list_count;
        bool is_autoneg;
index 1c7593d54035a44455db81166ef26eec772dc489..13ac2661a473c866d0a53a327e67fd77458738fe 100644 (file)
@@ -778,8 +778,15 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
                                          unsigned int packet_filter)
 {
        unsigned int i = 0U;
+       struct aq_nic_cfg_s *cfg = self->aq_nic_cfg;
+
+       hw_atl_rpfl2promiscuous_mode_en_set(self,
+                                           IS_FILTER_ENABLED(IFF_PROMISC));
+
+       hw_atl_rpf_vlan_prom_mode_en_set(self,
+                                    IS_FILTER_ENABLED(IFF_PROMISC) ||
+                                    cfg->is_vlan_force_promisc);
 
-       hw_atl_rpfl2promiscuous_mode_en_set(self, IS_FILTER_ENABLED(IFF_PROMISC));
        hw_atl_rpfl2multicast_flr_en_set(self,
                                         IS_FILTER_ENABLED(IFF_ALLMULTI), 0);
 
@@ -788,13 +795,13 @@ static int hw_atl_b0_hw_packet_filter_set(struct aq_hw_s *self,
 
        hw_atl_rpfl2broadcast_en_set(self, IS_FILTER_ENABLED(IFF_BROADCAST));
 
-       self->aq_nic_cfg->is_mc_list_enabled = IS_FILTER_ENABLED(IFF_MULTICAST);
+       cfg->is_mc_list_enabled = IS_FILTER_ENABLED(IFF_MULTICAST);
 
        for (i = HW_ATL_B0_MAC_MIN; i < HW_ATL_B0_MAC_MAX; ++i)
                hw_atl_rpfl2_uc_flr_en_set(self,
-                                          (self->aq_nic_cfg->is_mc_list_enabled &&
-                                   (i <= self->aq_nic_cfg->mc_list_count)) ?
-                                   1U : 0U, i);
+                                          (cfg->is_mc_list_enabled &&
+                                           (i <= cfg->mc_list_count)) ?
+                                          1U : 0U, i);
 
        return aq_hw_err_from_flags(self);
 }
@@ -1086,7 +1093,7 @@ static int hw_atl_b0_hw_vlan_set(struct aq_hw_s *self,
 static int hw_atl_b0_hw_vlan_ctrl(struct aq_hw_s *self, bool enable)
 {
        /* set promisc in case of disabing the vland filter */
-       hw_atl_rpf_vlan_prom_mode_en_set(self, !!!enable);
+       hw_atl_rpf_vlan_prom_mode_en_set(self, !enable);
 
        return aq_hw_err_from_flags(self);
 }