]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
net: hns3: Enable promisc mode when mac vlan table is full
authorJian Shen <shenjian15@huawei.com>
Fri, 12 Oct 2018 14:34:04 +0000 (15:34 +0100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 12 Oct 2018 18:23:45 +0000 (11:23 -0700)
Currently, the driver does nothing when mac vlan table is full.
In this case, the packet with new mac address will be dropped
by hardware. This patch adds check for the result of sync mac
address, and enable promisc mode when mac vlan table is full.
Furtherly, disable vlan filter when enable promisc by user
command.

Fixes: 46a3df9f9718 ("net: hns3: Add HNS3 Acceleration Engine & Compatibility Layer Support")
Signed-off-by: Jian Shen <shenjian15@huawei.com>
Signed-off-by: Salil Mehta <salil.mehta@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hnae3.h
drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
drivers/net/ethernet/hisilicon/hns3/hns3_enet.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

index 3df62a5783abfbf483bc7eac1bda99aba764f26b..c3bd2a10bc7d3bccf2b83c2efee2d478e7f861e0 100644 (file)
@@ -503,6 +503,15 @@ struct hnae3_unic_private_info {
 #define HNAE3_SUPPORT_VF             BIT(3)
 #define HNAE3_SUPPORT_SERDES_PARALLEL_LOOPBACK BIT(4)
 
+#define HNAE3_USER_UPE         BIT(0)  /* unicast promisc enabled by user */
+#define HNAE3_USER_MPE         BIT(1)  /* mulitcast promisc enabled by user */
+#define HNAE3_BPE              BIT(2)  /* broadcast promisc enable */
+#define HNAE3_OVERFLOW_UPE     BIT(3)  /* unicast mac vlan overflow */
+#define HNAE3_OVERFLOW_MPE     BIT(4)  /* multicast mac vlan overflow */
+#define HNAE3_VLAN_FLTR                BIT(5)  /* enable vlan filter */
+#define HNAE3_UPE              (HNAE3_USER_UPE | HNAE3_OVERFLOW_UPE)
+#define HNAE3_MPE              (HNAE3_USER_MPE | HNAE3_OVERFLOW_MPE)
+
 struct hnae3_handle {
        struct hnae3_client *client;
        struct pci_dev *pdev;
@@ -521,6 +530,8 @@ struct hnae3_handle {
        };
 
        u32 numa_node_mask;     /* for multi-chip support */
+
+       u8 netdev_flags;
 };
 
 #define hnae3_set_field(origin, mask, shift, val) \
index 9bbb53c934471d68061c379b61b9fde14997e0be..bbd6197799f05fe1ddc6d4300c7c8dfdb5cad4cd 100644 (file)
@@ -459,23 +459,81 @@ static int hns3_nic_mc_unsync(struct net_device *netdev,
        return 0;
 }
 
+static u8 hns3_get_netdev_flags(struct net_device *netdev)
+{
+       u8 flags = 0;
+
+       if (netdev->flags & IFF_PROMISC) {
+               flags = HNAE3_USER_UPE | HNAE3_USER_MPE;
+       } else {
+               flags |= HNAE3_VLAN_FLTR;
+               if (netdev->flags & IFF_ALLMULTI)
+                       flags |= HNAE3_USER_MPE;
+       }
+
+       return flags;
+}
+
 static void hns3_nic_set_rx_mode(struct net_device *netdev)
 {
        struct hnae3_handle *h = hns3_get_handle(netdev);
+       u8 new_flags;
+       int ret;
 
-       if (h->ae_algo->ops->set_promisc_mode) {
-               if (netdev->flags & IFF_PROMISC)
-                       h->ae_algo->ops->set_promisc_mode(h, true, true);
-               else if (netdev->flags & IFF_ALLMULTI)
-                       h->ae_algo->ops->set_promisc_mode(h, false, true);
-               else
-                       h->ae_algo->ops->set_promisc_mode(h, false, false);
-       }
-       if (__dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync))
+       new_flags = hns3_get_netdev_flags(netdev);
+
+       ret = __dev_uc_sync(netdev, hns3_nic_uc_sync, hns3_nic_uc_unsync);
+       if (ret) {
                netdev_err(netdev, "sync uc address fail\n");
+               if (ret == -ENOSPC)
+                       new_flags |= HNAE3_OVERFLOW_UPE;
+       }
+
        if (netdev->flags & IFF_MULTICAST) {
-               if (__dev_mc_sync(netdev, hns3_nic_mc_sync, hns3_nic_mc_unsync))
+               ret = __dev_mc_sync(netdev, hns3_nic_mc_sync,
+                                   hns3_nic_mc_unsync);
+               if (ret) {
                        netdev_err(netdev, "sync mc address fail\n");
+                       if (ret == -ENOSPC)
+                               new_flags |= HNAE3_OVERFLOW_MPE;
+               }
+       }
+
+       hns3_update_promisc_mode(netdev, new_flags);
+       /* User mode Promisc mode enable and vlan filtering is disabled to
+        * let all packets in. MAC-VLAN Table overflow Promisc enabled and
+        * vlan fitering is enabled
+        */
+       hns3_enable_vlan_filter(netdev, new_flags & HNAE3_VLAN_FLTR);
+       h->netdev_flags = new_flags;
+}
+
+void hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags)
+{
+       struct hns3_nic_priv *priv = netdev_priv(netdev);
+       struct hnae3_handle *h = priv->ae_handle;
+
+       if (h->ae_algo->ops->set_promisc_mode) {
+               h->ae_algo->ops->set_promisc_mode(h,
+                                                 promisc_flags & HNAE3_UPE,
+                                                 promisc_flags & HNAE3_MPE);
+       }
+}
+
+void hns3_enable_vlan_filter(struct net_device *netdev, bool enable)
+{
+       struct hns3_nic_priv *priv = netdev_priv(netdev);
+       struct hnae3_handle *h = priv->ae_handle;
+       bool last_state;
+
+       if (h->pdev->revision >= 0x21 && h->ae_algo->ops->enable_vlan_filter) {
+               last_state = h->netdev_flags & HNAE3_VLAN_FLTR ? true : false;
+               if (enable != last_state) {
+                       netdev_info(netdev,
+                                   "%s vlan filter\n",
+                                   enable ? "enable" : "disable");
+                       h->ae_algo->ops->enable_vlan_filter(h, enable);
+               }
        }
 }
 
index ac881e8fc05d7fad0173e3f7e97f47b5b0aa1445..f25b281ff2aaddc1fb3321387911009a1d856875 100644 (file)
@@ -640,6 +640,9 @@ void hns3_set_vector_coalesce_tx_gl(struct hns3_enet_tqp_vector *tqp_vector,
 void hns3_set_vector_coalesce_rl(struct hns3_enet_tqp_vector *tqp_vector,
                                 u32 rl_value);
 
+void hns3_enable_vlan_filter(struct net_device *netdev, bool enable);
+void hns3_update_promisc_mode(struct net_device *netdev, u8 promisc_flags);
+
 #ifdef CONFIG_HNS3_DCB
 void hns3_dcbnl_setup(struct hnae3_handle *handle);
 #else
index db97f6ab7221ed84fbcfcec2105b967eec55df72..1bd83e8268fc606159edf51b6629b0c5729db28b 100644 (file)
@@ -5606,6 +5606,10 @@ static void hclge_enable_vlan_filter(struct hnae3_handle *handle, bool enable)
                hclge_set_vlan_filter_ctrl(hdev, HCLGE_FILTER_TYPE_VF,
                                           HCLGE_FILTER_FE_EGRESS_V1_B, enable);
        }
+       if (enable)
+               handle->netdev_flags |= HNAE3_VLAN_FLTR;
+       else
+               handle->netdev_flags &= ~HNAE3_VLAN_FLTR;
 }
 
 static int hclge_set_vf_vlan_common(struct hclge_dev *hdev, int vfid,
@@ -5902,7 +5906,7 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
 {
 #define HCLGE_DEF_VLAN_TYPE            0x8100
 
-       struct hnae3_handle *handle;
+       struct hnae3_handle *handle = &hdev->vport[0].nic;
        struct hclge_vport *vport;
        int ret;
        int i;
@@ -5925,6 +5929,8 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
                        return ret;
        }
 
+       handle->netdev_flags |= HNAE3_VLAN_FLTR;
+
        hdev->vlan_type_cfg.rx_in_fst_vlan_type = HCLGE_DEF_VLAN_TYPE;
        hdev->vlan_type_cfg.rx_in_sec_vlan_type = HCLGE_DEF_VLAN_TYPE;
        hdev->vlan_type_cfg.rx_ot_fst_vlan_type = HCLGE_DEF_VLAN_TYPE;
@@ -5969,7 +5975,6 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
                        return ret;
        }
 
-       handle = &hdev->vport[0].nic;
        return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
 }