net: hns3: Record VF unicast and multicast tables
authorliuzhongzhu <liuzhongzhu@huawei.com>
Wed, 20 Feb 2019 02:32:48 +0000 (10:32 +0800)
committerDavid S. Miller <davem@davemloft.net>
Fri, 22 Feb 2019 00:29:05 +0000 (16:29 -0800)
Record the unicast and multicast 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/hclge_mbx.h
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 53089cd980d9b7d0d925526d4927d7ae0b109d6a..9b6b7b45dde3a8f0e2705ebd4c8c2171cbd9ee5c 100644 (file)
@@ -42,6 +42,8 @@ enum HCLGE_MBX_OPCODE {
        HCLGE_MBX_GET_QID_IN_PF,        /* (VF -> PF) get queue id in pf */
        HCLGE_MBX_LINK_STAT_MODE,       /* (PF -> VF) link mode has changed */
        HCLGE_MBX_GET_LINK_MODE,        /* (VF -> PF) get the link mode of pf */
+
+       HCLGE_MBX_GET_VF_FLR_STATUS = 200, /* (M7 -> PF) get vf reset status */
 };
 
 /* below are per-VF mac-vlan subcodes */
index 87edac45c040e72fffcd0ce01c4ba004e2e9d4e2..b1f5c6fa69542663fea75f9353ab0c1397c01e2f 100644 (file)
@@ -1329,6 +1329,8 @@ 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->uc_mac_list);
+               INIT_LIST_HEAD(&vport->mc_mac_list);
 
                if (i == 0)
                        ret = hclge_vport_setup(vport, tqp_main_vport);
@@ -6074,6 +6076,103 @@ int hclge_rm_mc_addr_common(struct hclge_vport *vport,
        return status;
 }
 
+void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+                              enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+       struct hclge_vport_mac_addr_cfg *mac_cfg;
+       struct list_head *list;
+
+       if (!vport->vport_id)
+               return;
+
+       mac_cfg = kzalloc(sizeof(*mac_cfg), GFP_KERNEL);
+       if (!mac_cfg)
+               return;
+
+       mac_cfg->hd_tbl_status = true;
+       memcpy(mac_cfg->mac_addr, mac_addr, ETH_ALEN);
+
+       list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+              &vport->uc_mac_list : &vport->mc_mac_list;
+
+       list_add_tail(&mac_cfg->node, list);
+}
+
+void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+                             bool is_write_tbl,
+                             enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+       struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp;
+       struct list_head *list;
+       bool uc_flag, mc_flag;
+
+       list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+              &vport->uc_mac_list : &vport->mc_mac_list;
+
+       uc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_UC;
+       mc_flag = is_write_tbl && mac_type == HCLGE_MAC_ADDR_MC;
+
+       list_for_each_entry_safe(mac_cfg, tmp, list, node) {
+               if (strncmp(mac_cfg->mac_addr, mac_addr, ETH_ALEN) == 0) {
+                       if (uc_flag && mac_cfg->hd_tbl_status)
+                               hclge_rm_uc_addr_common(vport, mac_addr);
+
+                       if (mc_flag && mac_cfg->hd_tbl_status)
+                               hclge_rm_mc_addr_common(vport, mac_addr);
+
+                       list_del(&mac_cfg->node);
+                       kfree(mac_cfg);
+                       break;
+               }
+       }
+}
+
+void hclge_rm_vport_all_mac_table(struct hclge_vport *vport, bool is_del_list,
+                                 enum HCLGE_MAC_ADDR_TYPE mac_type)
+{
+       struct hclge_vport_mac_addr_cfg *mac_cfg, *tmp;
+       struct list_head *list;
+
+       list = (mac_type == HCLGE_MAC_ADDR_UC) ?
+              &vport->uc_mac_list : &vport->mc_mac_list;
+
+       list_for_each_entry_safe(mac_cfg, tmp, list, node) {
+               if (mac_type == HCLGE_MAC_ADDR_UC && mac_cfg->hd_tbl_status)
+                       hclge_rm_uc_addr_common(vport, mac_cfg->mac_addr);
+
+               if (mac_type == HCLGE_MAC_ADDR_MC && mac_cfg->hd_tbl_status)
+                       hclge_rm_mc_addr_common(vport, mac_cfg->mac_addr);
+
+               mac_cfg->hd_tbl_status = false;
+               if (is_del_list) {
+                       list_del(&mac_cfg->node);
+                       kfree(mac_cfg);
+               }
+       }
+}
+
+void hclge_uninit_vport_mac_table(struct hclge_dev *hdev)
+{
+       struct hclge_vport_mac_addr_cfg *mac, *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(mac, tmp, &vport->uc_mac_list, node) {
+                       list_del(&mac->node);
+                       kfree(mac);
+               }
+
+               list_for_each_entry_safe(mac, tmp, &vport->mc_mac_list, node) {
+                       list_del(&mac->node);
+                       kfree(mac);
+               }
+       }
+       mutex_unlock(&hdev->vport_cfg_mutex);
+}
+
 static int hclge_get_mac_ethertype_cmd_status(struct hclge_dev *hdev,
                                              u16 cmdq_resp, u8 resp_code)
 {
@@ -7329,6 +7428,7 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
        hdev->mps = ETH_FRAME_LEN + ETH_FCS_LEN + 2 * VLAN_HLEN;
 
        mutex_init(&hdev->vport_lock);
+       mutex_init(&hdev->vport_cfg_mutex);
 
        ret = hclge_pci_init(hdev);
        if (ret) {
@@ -7621,6 +7721,8 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
        hclge_misc_irq_uninit(hdev);
        hclge_pci_uninit(hdev);
        mutex_destroy(&hdev->vport_lock);
+       hclge_uninit_vport_mac_table(hdev);
+       mutex_destroy(&hdev->vport_cfg_mutex);
        ae_dev->priv = NULL;
 }
 
index 3303919d089d37484a01ac281f4f7975e313b921..781bd1145e2c8b35f31d682d96cb4e165557c969 100644 (file)
@@ -632,6 +632,17 @@ struct hclge_fd_ad_data {
        u16 rule_id;
 };
 
+struct hclge_vport_mac_addr_cfg {
+       struct list_head node;
+       int hd_tbl_status;
+       u8 mac_addr[ETH_ALEN];
+};
+
+enum HCLGE_MAC_ADDR_TYPE {
+       HCLGE_MAC_ADDR_UC,
+       HCLGE_MAC_ADDR_MC
+};
+
 /* For each bit of TCAM entry, it uses a pair of 'x' and
  * 'y' to indicate which value to match, like below:
  * ----------------------------------
@@ -771,6 +782,8 @@ struct hclge_dev {
        /* unicast mac vlan space shared by PF and its VFs */
        u16 share_umv_size;
        struct mutex umv_mutex; /* protect share_umv_size */
+
+       struct mutex vport_cfg_mutex;   /* Protect stored vf table */
 };
 
 /* VPort level vlan tag configuration for TX direction */
@@ -838,6 +851,9 @@ struct hclge_vport {
        unsigned long state;
        unsigned long last_active_jiffies;
        u32 mps; /* Max packet size */
+
+       struct list_head uc_mac_list;   /* Store VF unicast table */
+       struct list_head mc_mac_list;   /* Store VF multicast table */
 };
 
 void hclge_promisc_param_init(struct hclge_promisc_param *param, bool en_uc,
@@ -892,4 +908,13 @@ int hclge_dbg_run_cmd(struct hnae3_handle *handle, char *cmd_buf);
 u16 hclge_covert_handle_qid_global(struct hnae3_handle *handle, u16 queue_id);
 int hclge_notify_client(struct hclge_dev *hdev,
                        enum hnae3_reset_notify_type type);
+void hclge_add_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+                              enum HCLGE_MAC_ADDR_TYPE mac_type);
+void hclge_rm_vport_mac_table(struct hclge_vport *vport, const u8 *mac_addr,
+                             bool is_write_tbl,
+                             enum HCLGE_MAC_ADDR_TYPE mac_type);
+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);
+
 #endif
index 7e4a104582d6ff92e0afb106fe2871631df0a665..476ca8399446229336aa022cf1fbfb201fb8a544 100644 (file)
@@ -224,12 +224,24 @@ static int hclge_set_vf_uc_mac_addr(struct hclge_vport *vport,
 
                hclge_rm_uc_addr_common(vport, old_addr);
                status = hclge_add_uc_addr_common(vport, mac_addr);
-               if (status)
+               if (status) {
                        hclge_add_uc_addr_common(vport, old_addr);
+               } else {
+                       hclge_rm_vport_mac_table(vport, mac_addr,
+                                                false, HCLGE_MAC_ADDR_UC);
+                       hclge_add_vport_mac_table(vport, mac_addr,
+                                                 HCLGE_MAC_ADDR_UC);
+               }
        } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_ADD) {
                status = hclge_add_uc_addr_common(vport, mac_addr);
+               if (!status)
+                       hclge_add_vport_mac_table(vport, mac_addr,
+                                                 HCLGE_MAC_ADDR_UC);
        } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_UC_REMOVE) {
                status = hclge_rm_uc_addr_common(vport, mac_addr);
+               if (!status)
+                       hclge_rm_vport_mac_table(vport, mac_addr,
+                                                false, HCLGE_MAC_ADDR_UC);
        } else {
                dev_err(&hdev->pdev->dev,
                        "failed to set unicast mac addr, unknown subcode %d\n",
@@ -255,8 +267,14 @@ static int hclge_set_vf_mc_mac_addr(struct hclge_vport *vport,
 
        if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_ADD) {
                status = hclge_add_mc_addr_common(vport, mac_addr);
+               if (!status)
+                       hclge_add_vport_mac_table(vport, mac_addr,
+                                                 HCLGE_MAC_ADDR_MC);
        } else if (mbx_req->msg[1] == HCLGE_MBX_MAC_VLAN_MC_REMOVE) {
                status = hclge_rm_mc_addr_common(vport, mac_addr);
+               if (!status)
+                       hclge_rm_vport_mac_table(vport, mac_addr,
+                                                false, HCLGE_MAC_ADDR_MC);
        } else {
                dev_err(&hdev->pdev->dev,
                        "failed to set mcast mac addr, unknown subcode %d\n",
@@ -585,6 +603,14 @@ void hclge_mbx_handler(struct hclge_dev *hdev)
                case HCLGE_MBX_GET_LINK_MODE:
                        hclge_get_link_mode(vport, req);
                        break;
+               case HCLGE_MBX_GET_VF_FLR_STATUS:
+                       mutex_lock(&hdev->vport_cfg_mutex);
+                       hclge_rm_vport_all_mac_table(vport, true,
+                                                    HCLGE_MAC_ADDR_UC);
+                       hclge_rm_vport_all_mac_table(vport, true,
+                                                    HCLGE_MAC_ADDR_MC);
+                       mutex_unlock(&hdev->vport_cfg_mutex);
+                       break;
                default:
                        dev_err(&hdev->pdev->dev,
                                "un-supported mailbox message, code = %d\n",