Commit 6dd86902 authored by liuzhongzhu's avatar liuzhongzhu Committed by David S. Miller

net: hns3: Record VF unicast and multicast tables

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: default avatarliuzhongzhu <liuzhongzhu@huawei.com>
Signed-off-by: default avatarPeng Li <lipeng321@huawei.com>
Signed-off-by: default avatarHuazhong Tan <tanhuazhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3aff0ac9
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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
......@@ -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",
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment