net: hns3: Record VF vlan tables
authorliuzhongzhu <liuzhongzhu@huawei.com>
Wed, 20 Feb 2019 02:32:49 +0000 (10:32 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Feb 2019 00:29:05 +0000 (16:29 -0800)
Record the vlan tables that the VF sends to the chip.
After the VF exception, the PF actively clears the VF to chip config.

Signed-off-by: liuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: Peng Li <lipeng321@huawei.com>
Signed-off-by: Huazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h
drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mbx.c

index b1f5c6fa69542663fea75f9353ab0c1397c01e2f..4a596460271c36205a3990c0577e464eff7802d1 100644 (file)
@@ -1329,6 +1329,7 @@ static int hclge_alloc_vport(struct hclge_dev *hdev)
                vport->back = hdev;
                vport->vport_id = i;
                vport->mps = HCLGE_MAC_DEFAULT_FRAME;
+               INIT_LIST_HEAD(&vport->vlan_list);
                INIT_LIST_HEAD(&vport->uc_mac_list);
                INIT_LIST_HEAD(&vport->mc_mac_list);
 
@@ -6746,6 +6747,84 @@ static int hclge_init_vlan_config(struct hclge_dev *hdev)
        return hclge_set_vlan_filter(handle, htons(ETH_P_8021Q), 0, false);
 }
 
+void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id)
+{
+       struct hclge_vport_vlan_cfg *vlan;
+
+       /* vlan 0 is reserved */
+       if (!vlan_id)
+               return;
+
+       vlan = kzalloc(sizeof(*vlan), GFP_KERNEL);
+       if (!vlan)
+               return;
+
+       vlan->hd_tbl_status = true;
+       vlan->vlan_id = vlan_id;
+
+       list_add_tail(&vlan->node, &vport->vlan_list);
+}
+
+void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+                              bool is_write_tbl)
+{
+       struct hclge_vport_vlan_cfg *vlan, *tmp;
+       struct hclge_dev *hdev = vport->back;
+
+       list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+               if (vlan->vlan_id == vlan_id) {
+                       if (is_write_tbl && vlan->hd_tbl_status)
+                               hclge_set_vlan_filter_hw(hdev,
+                                                        htons(ETH_P_8021Q),
+                                                        vport->vport_id,
+                                                        vlan_id, 0,
+                                                        true);
+
+                       list_del(&vlan->node);
+                       kfree(vlan);
+                       break;
+               }
+       }
+}
+
+void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list)
+{
+       struct hclge_vport_vlan_cfg *vlan, *tmp;
+       struct hclge_dev *hdev = vport->back;
+
+       list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+               if (vlan->hd_tbl_status)
+                       hclge_set_vlan_filter_hw(hdev,
+                                                htons(ETH_P_8021Q),
+                                                vport->vport_id,
+                                                vlan->vlan_id, 0,
+                                                true);
+
+               vlan->hd_tbl_status = false;
+               if (is_del_list) {
+                       list_del(&vlan->node);
+                       kfree(vlan);
+               }
+       }
+}
+
+void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev)
+{
+       struct hclge_vport_vlan_cfg *vlan, *tmp;
+       struct hclge_vport *vport;
+       int i;
+
+       mutex_lock(&hdev->vport_cfg_mutex);
+       for (i = 0; i < hdev->num_alloc_vport; i++) {
+               vport = &hdev->vport[i];
+               list_for_each_entry_safe(vlan, tmp, &vport->vlan_list, node) {
+                       list_del(&vlan->node);
+                       kfree(vlan);
+               }
+       }
+       mutex_unlock(&hdev->vport_cfg_mutex);
+}
+
 int hclge_en_hw_strip_rxvtag(struct hnae3_handle *handle, bool enable)
 {
        struct hclge_vport *vport = hclge_get_vport(handle);
@@ -7722,6 +7801,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
        hclge_pci_uninit(hdev);
        mutex_destroy(&hdev->vport_lock);
        hclge_uninit_vport_mac_table(hdev);
+       hclge_uninit_vport_vlan_table(hdev);
        mutex_destroy(&hdev->vport_cfg_mutex);
        ae_dev->priv = NULL;
 }
index 781bd1145e2c8b35f31d682d96cb4e165557c969..abbc58ea4864964bc093b1b6abdf0184a5710e85 100644 (file)
@@ -643,6 +643,12 @@ enum HCLGE_MAC_ADDR_TYPE {
        HCLGE_MAC_ADDR_MC
 };
 
+struct hclge_vport_vlan_cfg {
+       struct list_head node;
+       int hd_tbl_status;
+       u16 vlan_id;
+};
+
 /* For each bit of TCAM entry, it uses a pair of 'x' and
  * 'y' to indicate which value to match, like below:
  * ----------------------------------
@@ -854,6 +860,7 @@ struct hclge_vport {
 
        struct list_head uc_mac_list;   /* Store VF unicast table */
        struct list_head mc_mac_list;   /* Store VF multicast table */
+       struct list_head vlan_list;     /* Store VF vlan table */
 };
 
 void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
@@ -916,5 +923,9 @@ void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
 void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
                                  enum HCLGE_MAC_ADDR_TYPE mac_type);
 void hclge_uninit_vport_mac_table(struct hclge_dev *hdev);
-
+void hclge_add_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id);
+void hclge_rm_vport_vlan_table(struct hclge_vport *vport, u16 vlan_id,
+                              bool is_write_tbl);
+void hclge_rm_vport_all_vlan_table(struct hclge_vport *vport, bool is_del_list);
+void hclge_uninit_vport_vlan_table(struct hclge_dev *hdev);
 #endif
index 476ca8399446229336aa022cf1fbfb201fb8a544..9e0952c329bb2b240161cd70e6e95a8263b86731 100644 (file)
@@ -305,6 +305,9 @@ static int hclge_set_vf_vlan_cfg(struct hclge_vport *vport,
                memcpy(&proto, &mbx_req->msg[5], sizeof(proto));
                status = hclge_set_vlan_filter(handle, cpu_to_be16(proto),
                                               vlan, is_kill);
+               if (!status)
+                       is_kill ? hclge_rm_vport_vlan_table(vport, vlan, false)
+                       : hclge_add_vport_vlan_table(vport, vlan);
        } else if (mbx_req->msg[1] == HCLGE_MBX_VLAN_RX_OFF_CFG) {
                struct hnae3_handle *handle = &vport->nic;
                bool en = mbx_req->msg[2] ? true : false;
@@ -609,6 +612,7 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
                                                     HCLGE_MAC_ADDR_UC);
                        hclge_rm_vport_all_mac_table(vport, true,
                                                     HCLGE_MAC_ADDR_MC);
+                       hclge_rm_vport_all_vlan_table(vport, true);
                        mutex_unlock(&hdev->vport_cfg_mutex);
                        break;
                default: