xref: /openbmc/linux/drivers/net/ethernet/huawei/hinic/hinic_sriov.c (revision 2d78eb0342dd2c9c5cde9ae9ada1d33f189a858b)
17dd29ee1SLuo bin // SPDX-License-Identifier: GPL-2.0-only
27dd29ee1SLuo bin /* Huawei HiNIC PCI Express Linux driver
37dd29ee1SLuo bin  * Copyright(c) 2017 Huawei Technologies Co., Ltd
47dd29ee1SLuo bin  */
57dd29ee1SLuo bin 
67dd29ee1SLuo bin #include <linux/pci.h>
77dd29ee1SLuo bin #include <linux/if_vlan.h>
87dd29ee1SLuo bin #include <linux/interrupt.h>
97dd29ee1SLuo bin #include <linux/etherdevice.h>
107dd29ee1SLuo bin #include <linux/netdevice.h>
118581fd40SJakub Kicinski #include <linux/module.h>
127dd29ee1SLuo bin 
137dd29ee1SLuo bin #include "hinic_hw_dev.h"
147dd29ee1SLuo bin #include "hinic_dev.h"
157dd29ee1SLuo bin #include "hinic_hw_mbox.h"
167dd29ee1SLuo bin #include "hinic_hw_cmdq.h"
177dd29ee1SLuo bin #include "hinic_port.h"
187dd29ee1SLuo bin #include "hinic_sriov.h"
197dd29ee1SLuo bin 
207dd29ee1SLuo bin static unsigned char set_vf_link_state;
217dd29ee1SLuo bin module_param(set_vf_link_state, byte, 0444);
227dd29ee1SLuo bin MODULE_PARM_DESC(set_vf_link_state, "Set vf link state, 0 represents link auto, 1 represents link always up, 2 represents link always down. - default is 0.");
237dd29ee1SLuo bin 
247dd29ee1SLuo bin #define HINIC_VLAN_PRIORITY_SHIFT 13
257dd29ee1SLuo bin #define HINIC_ADD_VLAN_IN_MAC 0x8000
2672ef908bSLuo bin #define HINIC_TX_RATE_TABLE_FULL 12
27*57ac5715SZhengchao Shao #define HINIC_MAX_QOS 7
287dd29ee1SLuo bin 
hinic_set_mac(struct hinic_hwdev * hwdev,const u8 * mac_addr,u16 vlan_id,u16 func_id)29ddc2118eSYueHaibing static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
30ddc2118eSYueHaibing 			 u16 vlan_id, u16 func_id)
317dd29ee1SLuo bin {
327dd29ee1SLuo bin 	struct hinic_port_mac_cmd mac_info = {0};
337dd29ee1SLuo bin 	u16 out_size = sizeof(mac_info);
347dd29ee1SLuo bin 	int err;
357dd29ee1SLuo bin 
367dd29ee1SLuo bin 	mac_info.func_idx = func_id;
377dd29ee1SLuo bin 	mac_info.vlan_id = vlan_id;
387dd29ee1SLuo bin 	memcpy(mac_info.mac, mac_addr, ETH_ALEN);
397dd29ee1SLuo bin 
407dd29ee1SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
417dd29ee1SLuo bin 				 sizeof(mac_info), &mac_info, &out_size);
427dd29ee1SLuo bin 	if (err || out_size != sizeof(mac_info) ||
43f68910a8SLuo bin 	    (mac_info.status && mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
4490f86b8aSLuo bin 		dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",
4590f86b8aSLuo bin 			err, mac_info.status, out_size);
4690f86b8aSLuo bin 		return -EIO;
477dd29ee1SLuo bin 	}
487dd29ee1SLuo bin 
497dd29ee1SLuo bin 	return 0;
507dd29ee1SLuo bin }
517dd29ee1SLuo bin 
hinic_notify_vf_link_status(struct hinic_hwdev * hwdev,u16 vf_id,u8 link_status)527dd29ee1SLuo bin static void hinic_notify_vf_link_status(struct hinic_hwdev *hwdev, u16 vf_id,
537dd29ee1SLuo bin 					u8 link_status)
547dd29ee1SLuo bin {
557dd29ee1SLuo bin 	struct vf_data_storage *vf_infos = hwdev->func_to_io.vf_infos;
567dd29ee1SLuo bin 	struct hinic_port_link_status link = {0};
577dd29ee1SLuo bin 	u16 out_size = sizeof(link);
587dd29ee1SLuo bin 	int err;
597dd29ee1SLuo bin 
607dd29ee1SLuo bin 	if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) {
617dd29ee1SLuo bin 		link.link = link_status;
627dd29ee1SLuo bin 		link.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
637dd29ee1SLuo bin 		err = hinic_mbox_to_vf(hwdev, HINIC_MOD_L2NIC,
647dd29ee1SLuo bin 				       vf_id, HINIC_PORT_CMD_LINK_STATUS_REPORT,
657dd29ee1SLuo bin 				       &link, sizeof(link),
667dd29ee1SLuo bin 				       &link, &out_size, 0);
677dd29ee1SLuo bin 		if (err || !out_size || link.status)
687dd29ee1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev,
697dd29ee1SLuo bin 				"Send link change event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n",
707dd29ee1SLuo bin 				HW_VF_ID_TO_OS(vf_id), err,
717dd29ee1SLuo bin 				link.status, out_size);
727dd29ee1SLuo bin 	}
737dd29ee1SLuo bin }
747dd29ee1SLuo bin 
757dd29ee1SLuo bin /* send link change event mbox msg to active vfs under the pf */
hinic_notify_all_vfs_link_changed(struct hinic_hwdev * hwdev,u8 link_status)767dd29ee1SLuo bin void hinic_notify_all_vfs_link_changed(struct hinic_hwdev *hwdev,
777dd29ee1SLuo bin 				       u8 link_status)
787dd29ee1SLuo bin {
797dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
807dd29ee1SLuo bin 	u16 i;
817dd29ee1SLuo bin 
827dd29ee1SLuo bin 	nic_io->link_status = link_status;
837dd29ee1SLuo bin 	for (i = 1; i <= nic_io->max_vfs; i++) {
847dd29ee1SLuo bin 		if (!nic_io->vf_infos[HW_VF_ID_TO_OS(i)].link_forced)
857dd29ee1SLuo bin 			hinic_notify_vf_link_status(hwdev, i,  link_status);
867dd29ee1SLuo bin 	}
877dd29ee1SLuo bin }
887dd29ee1SLuo bin 
hinic_vf_info_vlanprio(struct hinic_hwdev * hwdev,int vf_id)89ddc2118eSYueHaibing static u16 hinic_vf_info_vlanprio(struct hinic_hwdev *hwdev, int vf_id)
907dd29ee1SLuo bin {
917dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
927dd29ee1SLuo bin 	u16 pf_vlan, vlanprio;
937dd29ee1SLuo bin 	u8 pf_qos;
947dd29ee1SLuo bin 
957dd29ee1SLuo bin 	pf_vlan = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan;
967dd29ee1SLuo bin 	pf_qos = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos;
977dd29ee1SLuo bin 	vlanprio = pf_vlan | pf_qos << HINIC_VLAN_PRIORITY_SHIFT;
987dd29ee1SLuo bin 
997dd29ee1SLuo bin 	return vlanprio;
1007dd29ee1SLuo bin }
1017dd29ee1SLuo bin 
hinic_set_vf_vlan(struct hinic_hwdev * hwdev,bool add,u16 vid,u8 qos,int vf_id)102ddc2118eSYueHaibing static int hinic_set_vf_vlan(struct hinic_hwdev *hwdev, bool add, u16 vid,
1037dd29ee1SLuo bin 			     u8 qos, int vf_id)
1047dd29ee1SLuo bin {
1057dd29ee1SLuo bin 	struct hinic_vf_vlan_config vf_vlan = {0};
1067dd29ee1SLuo bin 	u16 out_size = sizeof(vf_vlan);
1077dd29ee1SLuo bin 	int err;
1087dd29ee1SLuo bin 	u8 cmd;
1097dd29ee1SLuo bin 
1107dd29ee1SLuo bin 	/* VLAN 0 is a special case, don't allow it to be removed */
1117dd29ee1SLuo bin 	if (!vid && !add)
1127dd29ee1SLuo bin 		return 0;
1137dd29ee1SLuo bin 
1147dd29ee1SLuo bin 	vf_vlan.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
1157dd29ee1SLuo bin 	vf_vlan.vlan_id = vid;
1167dd29ee1SLuo bin 	vf_vlan.qos = qos;
1177dd29ee1SLuo bin 
1187dd29ee1SLuo bin 	if (add)
1197dd29ee1SLuo bin 		cmd = HINIC_PORT_CMD_SET_VF_VLAN;
1207dd29ee1SLuo bin 	else
1217dd29ee1SLuo bin 		cmd = HINIC_PORT_CMD_CLR_VF_VLAN;
1227dd29ee1SLuo bin 
1237dd29ee1SLuo bin 	err = hinic_port_msg_cmd(hwdev, cmd, &vf_vlan,
1247dd29ee1SLuo bin 				 sizeof(vf_vlan), &vf_vlan, &out_size);
1257dd29ee1SLuo bin 	if (err || !out_size || vf_vlan.status) {
1267dd29ee1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d vlan, err: %d, status: 0x%x, out size: 0x%x\n",
1277dd29ee1SLuo bin 			HW_VF_ID_TO_OS(vf_id), err, vf_vlan.status, out_size);
1287dd29ee1SLuo bin 		return -EFAULT;
1297dd29ee1SLuo bin 	}
1307dd29ee1SLuo bin 
1317dd29ee1SLuo bin 	return 0;
1327dd29ee1SLuo bin }
1337dd29ee1SLuo bin 
hinic_set_vf_tx_rate_max_min(struct hinic_hwdev * hwdev,u16 vf_id,u32 max_rate,u32 min_rate)13472ef908bSLuo bin static int hinic_set_vf_tx_rate_max_min(struct hinic_hwdev *hwdev, u16 vf_id,
13572ef908bSLuo bin 					u32 max_rate, u32 min_rate)
13672ef908bSLuo bin {
13772ef908bSLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
13872ef908bSLuo bin 	struct hinic_tx_rate_cfg_max_min rate_cfg = {0};
13972ef908bSLuo bin 	u16 out_size = sizeof(rate_cfg);
14072ef908bSLuo bin 	int err;
14172ef908bSLuo bin 
14272ef908bSLuo bin 	rate_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
14372ef908bSLuo bin 	rate_cfg.max_rate = max_rate;
14472ef908bSLuo bin 	rate_cfg.min_rate = min_rate;
14572ef908bSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE,
14672ef908bSLuo bin 				 &rate_cfg, sizeof(rate_cfg), &rate_cfg,
14772ef908bSLuo bin 				 &out_size);
14872ef908bSLuo bin 	if ((rate_cfg.status != HINIC_MGMT_CMD_UNSUPPORTED &&
14972ef908bSLuo bin 	     rate_cfg.status) || err || !out_size) {
15072ef908bSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) max rate(%d), min rate(%d), err: %d, status: 0x%x, out size: 0x%x\n",
15172ef908bSLuo bin 			HW_VF_ID_TO_OS(vf_id), max_rate, min_rate, err,
15272ef908bSLuo bin 			rate_cfg.status, out_size);
15372ef908bSLuo bin 		return -EIO;
15472ef908bSLuo bin 	}
15572ef908bSLuo bin 
15672ef908bSLuo bin 	if (!rate_cfg.status) {
15772ef908bSLuo bin 		nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate;
15872ef908bSLuo bin 		nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = min_rate;
15972ef908bSLuo bin 	}
16072ef908bSLuo bin 
16172ef908bSLuo bin 	return rate_cfg.status;
16272ef908bSLuo bin }
16372ef908bSLuo bin 
hinic_set_vf_rate_limit(struct hinic_hwdev * hwdev,u16 vf_id,u32 tx_rate)16472ef908bSLuo bin static int hinic_set_vf_rate_limit(struct hinic_hwdev *hwdev, u16 vf_id,
16572ef908bSLuo bin 				   u32 tx_rate)
16672ef908bSLuo bin {
16772ef908bSLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
16872ef908bSLuo bin 	struct hinic_tx_rate_cfg rate_cfg = {0};
16972ef908bSLuo bin 	u16 out_size = sizeof(rate_cfg);
17072ef908bSLuo bin 	int err;
17172ef908bSLuo bin 
17272ef908bSLuo bin 	rate_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
17372ef908bSLuo bin 	rate_cfg.tx_rate = tx_rate;
17472ef908bSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VF_RATE,
17572ef908bSLuo bin 				 &rate_cfg, sizeof(rate_cfg), &rate_cfg,
17672ef908bSLuo bin 				 &out_size);
17772ef908bSLuo bin 	if (err || !out_size || rate_cfg.status) {
17872ef908bSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) rate(%d), err: %d, status: 0x%x, out size: 0x%x\n",
17972ef908bSLuo bin 			HW_VF_ID_TO_OS(vf_id), tx_rate, err, rate_cfg.status,
18072ef908bSLuo bin 			out_size);
18172ef908bSLuo bin 		if (rate_cfg.status)
18272ef908bSLuo bin 			return rate_cfg.status;
18372ef908bSLuo bin 
18472ef908bSLuo bin 		return -EIO;
18572ef908bSLuo bin 	}
18672ef908bSLuo bin 
18772ef908bSLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = tx_rate;
18872ef908bSLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = 0;
18972ef908bSLuo bin 
19072ef908bSLuo bin 	return 0;
19172ef908bSLuo bin }
19272ef908bSLuo bin 
hinic_set_vf_tx_rate(struct hinic_hwdev * hwdev,u16 vf_id,u32 max_rate,u32 min_rate)19372ef908bSLuo bin static int hinic_set_vf_tx_rate(struct hinic_hwdev *hwdev, u16 vf_id,
19472ef908bSLuo bin 				u32 max_rate, u32 min_rate)
19572ef908bSLuo bin {
19672ef908bSLuo bin 	int err;
19772ef908bSLuo bin 
19872ef908bSLuo bin 	err = hinic_set_vf_tx_rate_max_min(hwdev, vf_id, max_rate, min_rate);
19972ef908bSLuo bin 	if (err != HINIC_MGMT_CMD_UNSUPPORTED)
20072ef908bSLuo bin 		return err;
20172ef908bSLuo bin 
20272ef908bSLuo bin 	if (min_rate) {
20372ef908bSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate\n");
20472ef908bSLuo bin 		return -EOPNOTSUPP;
20572ef908bSLuo bin 	}
20672ef908bSLuo bin 
20772ef908bSLuo bin 	dev_info(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate, force min_tx_rate = max_tx_rate\n");
20872ef908bSLuo bin 
20972ef908bSLuo bin 	return hinic_set_vf_rate_limit(hwdev, vf_id, max_rate);
21072ef908bSLuo bin }
21172ef908bSLuo bin 
hinic_init_vf_config(struct hinic_hwdev * hwdev,u16 vf_id)2127dd29ee1SLuo bin static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id)
2137dd29ee1SLuo bin {
2147dd29ee1SLuo bin 	struct vf_data_storage *vf_info;
2157dd29ee1SLuo bin 	u16 func_id, vlan_id;
2167dd29ee1SLuo bin 	int err = 0;
2177dd29ee1SLuo bin 
2187dd29ee1SLuo bin 	vf_info = hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);
2197dd29ee1SLuo bin 	if (vf_info->pf_set_mac) {
2207dd29ee1SLuo bin 		func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
2217dd29ee1SLuo bin 
2227dd29ee1SLuo bin 		vlan_id = 0;
2237dd29ee1SLuo bin 
2247dd29ee1SLuo bin 		err = hinic_set_mac(hwdev, vf_info->vf_mac_addr, vlan_id,
2257dd29ee1SLuo bin 				    func_id);
2267dd29ee1SLuo bin 		if (err) {
2277dd29ee1SLuo bin 			dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set VF %d MAC\n",
2287dd29ee1SLuo bin 				HW_VF_ID_TO_OS(vf_id));
2297dd29ee1SLuo bin 			return err;
2307dd29ee1SLuo bin 		}
2317dd29ee1SLuo bin 	}
2327dd29ee1SLuo bin 
2337dd29ee1SLuo bin 	if (hinic_vf_info_vlanprio(hwdev, vf_id)) {
2347dd29ee1SLuo bin 		err = hinic_set_vf_vlan(hwdev, true, vf_info->pf_vlan,
2357dd29ee1SLuo bin 					vf_info->pf_qos, vf_id);
2367dd29ee1SLuo bin 		if (err) {
2377dd29ee1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Failed to add VF %d VLAN_QOS\n",
2387dd29ee1SLuo bin 				HW_VF_ID_TO_OS(vf_id));
2397dd29ee1SLuo bin 			return err;
2407dd29ee1SLuo bin 		}
2417dd29ee1SLuo bin 	}
2427dd29ee1SLuo bin 
24372ef908bSLuo bin 	if (vf_info->max_rate) {
24472ef908bSLuo bin 		err = hinic_set_vf_tx_rate(hwdev, vf_id, vf_info->max_rate,
24572ef908bSLuo bin 					   vf_info->min_rate);
24672ef908bSLuo bin 		if (err) {
24772ef908bSLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d max rate: %d, min rate: %d\n",
24872ef908bSLuo bin 				HW_VF_ID_TO_OS(vf_id), vf_info->max_rate,
24972ef908bSLuo bin 				vf_info->min_rate);
25072ef908bSLuo bin 			return err;
25172ef908bSLuo bin 		}
25272ef908bSLuo bin 	}
25372ef908bSLuo bin 
2547dd29ee1SLuo bin 	return 0;
2557dd29ee1SLuo bin }
2567dd29ee1SLuo bin 
hinic_register_vf_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)257ddc2118eSYueHaibing static int hinic_register_vf_msg_handler(void *hwdev, u16 vf_id,
2587dd29ee1SLuo bin 					 void *buf_in, u16 in_size,
2597dd29ee1SLuo bin 					 void *buf_out, u16 *out_size)
2607dd29ee1SLuo bin {
2617dd29ee1SLuo bin 	struct hinic_register_vf *register_info = buf_out;
2627dd29ee1SLuo bin 	struct hinic_hwdev *hw_dev = hwdev;
2637dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
2647dd29ee1SLuo bin 	int err;
2657dd29ee1SLuo bin 
2667dd29ee1SLuo bin 	nic_io = &hw_dev->func_to_io;
2677dd29ee1SLuo bin 	if (vf_id > nic_io->max_vfs) {
2687dd29ee1SLuo bin 		dev_err(&hw_dev->hwif->pdev->dev, "Register VF id %d exceed limit[0-%d]\n",
2697dd29ee1SLuo bin 			HW_VF_ID_TO_OS(vf_id), HW_VF_ID_TO_OS(nic_io->max_vfs));
2707dd29ee1SLuo bin 		register_info->status = EFAULT;
2717dd29ee1SLuo bin 		return -EFAULT;
2727dd29ee1SLuo bin 	}
2737dd29ee1SLuo bin 
2747dd29ee1SLuo bin 	*out_size = sizeof(*register_info);
2757dd29ee1SLuo bin 	err = hinic_init_vf_config(hw_dev, vf_id);
2767dd29ee1SLuo bin 	if (err) {
2777dd29ee1SLuo bin 		register_info->status = EFAULT;
2787dd29ee1SLuo bin 		return err;
2797dd29ee1SLuo bin 	}
2807dd29ee1SLuo bin 
2817dd29ee1SLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true;
2827dd29ee1SLuo bin 
2837dd29ee1SLuo bin 	return 0;
2847dd29ee1SLuo bin }
2857dd29ee1SLuo bin 
hinic_unregister_vf_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)286ddc2118eSYueHaibing static int hinic_unregister_vf_msg_handler(void *hwdev, u16 vf_id,
2877dd29ee1SLuo bin 					   void *buf_in, u16 in_size,
2887dd29ee1SLuo bin 					   void *buf_out, u16 *out_size)
2897dd29ee1SLuo bin {
2907dd29ee1SLuo bin 	struct hinic_hwdev *hw_dev = hwdev;
2917dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
2927dd29ee1SLuo bin 
2937dd29ee1SLuo bin 	nic_io = &hw_dev->func_to_io;
2947dd29ee1SLuo bin 	*out_size = 0;
2957dd29ee1SLuo bin 	if (vf_id > nic_io->max_vfs)
2967dd29ee1SLuo bin 		return 0;
2977dd29ee1SLuo bin 
2987dd29ee1SLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = false;
2997dd29ee1SLuo bin 
3007dd29ee1SLuo bin 	return 0;
3017dd29ee1SLuo bin }
3027dd29ee1SLuo bin 
hinic_change_vf_mtu_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)303ddc2118eSYueHaibing static int hinic_change_vf_mtu_msg_handler(void *hwdev, u16 vf_id,
3047dd29ee1SLuo bin 					   void *buf_in, u16 in_size,
3057dd29ee1SLuo bin 					   void *buf_out, u16 *out_size)
3067dd29ee1SLuo bin {
3077dd29ee1SLuo bin 	struct hinic_hwdev *hw_dev = hwdev;
3087dd29ee1SLuo bin 	int err;
3097dd29ee1SLuo bin 
3107dd29ee1SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU, buf_in,
3117dd29ee1SLuo bin 				 in_size, buf_out, out_size);
3127dd29ee1SLuo bin 	if (err) {
3137dd29ee1SLuo bin 		dev_err(&hw_dev->hwif->pdev->dev, "Failed to set VF %u mtu\n",
3147dd29ee1SLuo bin 			vf_id);
3157dd29ee1SLuo bin 		return err;
3167dd29ee1SLuo bin 	}
3177dd29ee1SLuo bin 
3187dd29ee1SLuo bin 	return 0;
3197dd29ee1SLuo bin }
3207dd29ee1SLuo bin 
hinic_get_vf_mac_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)321ddc2118eSYueHaibing static int hinic_get_vf_mac_msg_handler(void *hwdev, u16 vf_id,
3227dd29ee1SLuo bin 					void *buf_in, u16 in_size,
3237dd29ee1SLuo bin 					void *buf_out, u16 *out_size)
3247dd29ee1SLuo bin {
3257dd29ee1SLuo bin 	struct hinic_port_mac_cmd *mac_info = buf_out;
3267dd29ee1SLuo bin 	struct hinic_hwdev *dev = hwdev;
3277dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
3287dd29ee1SLuo bin 	struct vf_data_storage *vf_info;
3297dd29ee1SLuo bin 
3307dd29ee1SLuo bin 	nic_io = &dev->func_to_io;
3317dd29ee1SLuo bin 	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
3327dd29ee1SLuo bin 
3337dd29ee1SLuo bin 	memcpy(mac_info->mac, vf_info->vf_mac_addr, ETH_ALEN);
3347dd29ee1SLuo bin 	mac_info->status = 0;
3357dd29ee1SLuo bin 	*out_size = sizeof(*mac_info);
3367dd29ee1SLuo bin 
3377dd29ee1SLuo bin 	return 0;
3387dd29ee1SLuo bin }
3397dd29ee1SLuo bin 
hinic_set_vf_mac_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)340ddc2118eSYueHaibing static int hinic_set_vf_mac_msg_handler(void *hwdev, u16 vf_id,
3417dd29ee1SLuo bin 					void *buf_in, u16 in_size,
3427dd29ee1SLuo bin 					void *buf_out, u16 *out_size)
3437dd29ee1SLuo bin {
3447dd29ee1SLuo bin 	struct hinic_port_mac_cmd *mac_out = buf_out;
3457dd29ee1SLuo bin 	struct hinic_port_mac_cmd *mac_in = buf_in;
3467dd29ee1SLuo bin 	struct hinic_hwdev *hw_dev = hwdev;
3477dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
3487dd29ee1SLuo bin 	struct vf_data_storage *vf_info;
3497dd29ee1SLuo bin 	int err;
3507dd29ee1SLuo bin 
3517dd29ee1SLuo bin 	nic_io =  &hw_dev->func_to_io;
3527dd29ee1SLuo bin 	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
3537dd29ee1SLuo bin 	if (vf_info->pf_set_mac && !(vf_info->trust) &&
3547dd29ee1SLuo bin 	    is_valid_ether_addr(mac_in->mac)) {
3557dd29ee1SLuo bin 		dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF %d MAC address\n",
3567dd29ee1SLuo bin 			 HW_VF_ID_TO_OS(vf_id));
3577dd29ee1SLuo bin 		mac_out->status = HINIC_PF_SET_VF_ALREADY;
3587dd29ee1SLuo bin 		*out_size = sizeof(*mac_out);
3597dd29ee1SLuo bin 		return 0;
3607dd29ee1SLuo bin 	}
3617dd29ee1SLuo bin 
3627dd29ee1SLuo bin 	err = hinic_port_msg_cmd(hw_dev, HINIC_PORT_CMD_SET_MAC, buf_in,
3637dd29ee1SLuo bin 				 in_size, buf_out, out_size);
3647dd29ee1SLuo bin 	if ((err &&  err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) || !(*out_size)) {
3657dd29ee1SLuo bin 		dev_err(&hw_dev->hwif->pdev->dev,
3667dd29ee1SLuo bin 			"Failed to set VF %d MAC address, err: %d, status: 0x%x, out size: 0x%x\n",
3677dd29ee1SLuo bin 			HW_VF_ID_TO_OS(vf_id), err, mac_out->status, *out_size);
3687dd29ee1SLuo bin 		return -EFAULT;
3697dd29ee1SLuo bin 	}
3707dd29ee1SLuo bin 
3717dd29ee1SLuo bin 	return err;
3727dd29ee1SLuo bin }
3737dd29ee1SLuo bin 
hinic_del_vf_mac_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)374ddc2118eSYueHaibing static int hinic_del_vf_mac_msg_handler(void *hwdev, u16 vf_id,
3757dd29ee1SLuo bin 					void *buf_in, u16 in_size,
3767dd29ee1SLuo bin 					void *buf_out, u16 *out_size)
3777dd29ee1SLuo bin {
3787dd29ee1SLuo bin 	struct hinic_port_mac_cmd *mac_out = buf_out;
3797dd29ee1SLuo bin 	struct hinic_port_mac_cmd *mac_in = buf_in;
3807dd29ee1SLuo bin 	struct hinic_hwdev *hw_dev = hwdev;
3817dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
3827dd29ee1SLuo bin 	struct vf_data_storage *vf_info;
3837dd29ee1SLuo bin 	int err;
3847dd29ee1SLuo bin 
3857dd29ee1SLuo bin 	nic_io = &hw_dev->func_to_io;
3867dd29ee1SLuo bin 	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
3877dd29ee1SLuo bin 	if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
3887dd29ee1SLuo bin 	    !memcmp(vf_info->vf_mac_addr, mac_in->mac, ETH_ALEN)) {
3897dd29ee1SLuo bin 		dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF mac.\n");
3907dd29ee1SLuo bin 		mac_out->status = HINIC_PF_SET_VF_ALREADY;
3917dd29ee1SLuo bin 		*out_size = sizeof(*mac_out);
3927dd29ee1SLuo bin 		return 0;
3937dd29ee1SLuo bin 	}
3947dd29ee1SLuo bin 
3957dd29ee1SLuo bin 	err = hinic_port_msg_cmd(hw_dev, HINIC_PORT_CMD_DEL_MAC, buf_in,
3967dd29ee1SLuo bin 				 in_size, buf_out, out_size);
3977dd29ee1SLuo bin 	if ((err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) || !(*out_size)) {
3987dd29ee1SLuo bin 		dev_err(&hw_dev->hwif->pdev->dev, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n",
3997dd29ee1SLuo bin 			HW_VF_ID_TO_OS(vf_id), err, mac_out->status, *out_size);
4007dd29ee1SLuo bin 		return -EFAULT;
4017dd29ee1SLuo bin 	}
4027dd29ee1SLuo bin 
4037dd29ee1SLuo bin 	return err;
4047dd29ee1SLuo bin }
4057dd29ee1SLuo bin 
hinic_get_vf_link_status_msg_handler(void * hwdev,u16 vf_id,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)406ddc2118eSYueHaibing static int hinic_get_vf_link_status_msg_handler(void *hwdev, u16 vf_id,
4077dd29ee1SLuo bin 						void *buf_in, u16 in_size,
4087dd29ee1SLuo bin 						void *buf_out, u16 *out_size)
4097dd29ee1SLuo bin {
4107dd29ee1SLuo bin 	struct hinic_port_link_cmd *get_link = buf_out;
4117dd29ee1SLuo bin 	struct hinic_hwdev *hw_dev = hwdev;
4127dd29ee1SLuo bin 	struct vf_data_storage *vf_infos;
4137dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
4147dd29ee1SLuo bin 	bool link_forced, link_up;
4157dd29ee1SLuo bin 
4167dd29ee1SLuo bin 	nic_io = &hw_dev->func_to_io;
4177dd29ee1SLuo bin 	vf_infos = nic_io->vf_infos;
4187dd29ee1SLuo bin 	link_forced = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced;
4197dd29ee1SLuo bin 	link_up = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up;
4207dd29ee1SLuo bin 
4217dd29ee1SLuo bin 	if (link_forced)
4227dd29ee1SLuo bin 		get_link->state = link_up ?
4237dd29ee1SLuo bin 			HINIC_LINK_STATE_UP : HINIC_LINK_STATE_DOWN;
4247dd29ee1SLuo bin 	else
4257dd29ee1SLuo bin 		get_link->state = nic_io->link_status;
4267dd29ee1SLuo bin 
4277dd29ee1SLuo bin 	get_link->status = 0;
4287dd29ee1SLuo bin 	*out_size = sizeof(*get_link);
4297dd29ee1SLuo bin 
4307dd29ee1SLuo bin 	return 0;
4317dd29ee1SLuo bin }
4327dd29ee1SLuo bin 
check_func_table(struct hinic_hwdev * hwdev,u16 func_idx,void * buf_in,u16 in_size)433c8c29ec3SLuo bin static bool check_func_table(struct hinic_hwdev *hwdev, u16 func_idx,
434c8c29ec3SLuo bin 			     void *buf_in, u16 in_size)
435c8c29ec3SLuo bin {
436c8c29ec3SLuo bin 	struct hinic_cmd_fw_ctxt *function_table = buf_in;
437c8c29ec3SLuo bin 
438c8c29ec3SLuo bin 	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size) ||
439c8c29ec3SLuo bin 	    !function_table->rx_buf_sz)
440c8c29ec3SLuo bin 		return false;
441c8c29ec3SLuo bin 
442c8c29ec3SLuo bin 	return true;
443c8c29ec3SLuo bin }
444c8c29ec3SLuo bin 
445ddc2118eSYueHaibing static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = {
4467dd29ee1SLuo bin 	{HINIC_PORT_CMD_VF_REGISTER, hinic_register_vf_msg_handler},
4477dd29ee1SLuo bin 	{HINIC_PORT_CMD_VF_UNREGISTER, hinic_unregister_vf_msg_handler},
4487dd29ee1SLuo bin 	{HINIC_PORT_CMD_CHANGE_MTU, hinic_change_vf_mtu_msg_handler},
4497dd29ee1SLuo bin 	{HINIC_PORT_CMD_GET_MAC, hinic_get_vf_mac_msg_handler},
4507dd29ee1SLuo bin 	{HINIC_PORT_CMD_SET_MAC, hinic_set_vf_mac_msg_handler},
4517dd29ee1SLuo bin 	{HINIC_PORT_CMD_DEL_MAC, hinic_del_vf_mac_msg_handler},
4527dd29ee1SLuo bin 	{HINIC_PORT_CMD_GET_LINK_STATE, hinic_get_vf_link_status_msg_handler},
4537dd29ee1SLuo bin };
4547dd29ee1SLuo bin 
455c8c29ec3SLuo bin static struct vf_cmd_check_handle nic_cmd_support_vf[] = {
456c8c29ec3SLuo bin 	{HINIC_PORT_CMD_VF_REGISTER, NULL},
457c8c29ec3SLuo bin 	{HINIC_PORT_CMD_VF_UNREGISTER, NULL},
458c8c29ec3SLuo bin 	{HINIC_PORT_CMD_CHANGE_MTU, hinic_mbox_check_func_id_8B},
459c8c29ec3SLuo bin 	{HINIC_PORT_CMD_ADD_VLAN, hinic_mbox_check_func_id_8B},
460c8c29ec3SLuo bin 	{HINIC_PORT_CMD_DEL_VLAN, hinic_mbox_check_func_id_8B},
461c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_MAC, hinic_mbox_check_func_id_8B},
462c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_MAC, hinic_mbox_check_func_id_8B},
463c8c29ec3SLuo bin 	{HINIC_PORT_CMD_DEL_MAC, hinic_mbox_check_func_id_8B},
464c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RX_MODE, hinic_mbox_check_func_id_8B},
465c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_PAUSE_INFO, hinic_mbox_check_func_id_8B},
466c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_LINK_STATE, hinic_mbox_check_func_id_8B},
467c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_LRO, hinic_mbox_check_func_id_8B},
468c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RX_CSUM, hinic_mbox_check_func_id_8B},
469c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD, hinic_mbox_check_func_id_8B},
470c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_VPORT_STAT, hinic_mbox_check_func_id_8B},
471c8c29ec3SLuo bin 	{HINIC_PORT_CMD_CLEAN_VPORT_STAT, hinic_mbox_check_func_id_8B},
472c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
473c8c29ec3SLuo bin 	 hinic_mbox_check_func_id_8B},
474c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},
475c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},
476c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},
477c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},
478c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},
479c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},
480c8c29ec3SLuo bin 	{HINIC_PORT_CMD_RSS_TEMP_MGR, hinic_mbox_check_func_id_8B},
481c8c29ec3SLuo bin 	{HINIC_PORT_CMD_RSS_CFG, hinic_mbox_check_func_id_8B},
482c8c29ec3SLuo bin 	{HINIC_PORT_CMD_FWCTXT_INIT, check_func_table},
483c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_MGMT_VERSION, NULL},
484c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_FUNC_STATE, hinic_mbox_check_func_id_8B},
485c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_GLOBAL_QPN, hinic_mbox_check_func_id_8B},
486c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_TSO, hinic_mbox_check_func_id_8B},
487c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_RQ_IQ_MAP, hinic_mbox_check_func_id_8B},
488c8c29ec3SLuo bin 	{HINIC_PORT_CMD_LINK_STATUS_REPORT, hinic_mbox_check_func_id_8B},
489c8c29ec3SLuo bin 	{HINIC_PORT_CMD_UPDATE_MAC, hinic_mbox_check_func_id_8B},
490c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_CAP, hinic_mbox_check_func_id_8B},
491c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_LINK_MODE, hinic_mbox_check_func_id_8B},
492c8c29ec3SLuo bin 	{HINIC_PORT_CMD_GET_VF_COS, NULL},
493c8c29ec3SLuo bin 	{HINIC_PORT_CMD_SET_VHD_CFG, hinic_mbox_check_func_id_8B},
4947dd29ee1SLuo bin 	{HINIC_PORT_CMD_SET_VLAN_FILTER, hinic_mbox_check_func_id_8B},
4957dd29ee1SLuo bin 	{HINIC_PORT_CMD_Q_FILTER, hinic_mbox_check_func_id_8B},
496ddc2118eSYueHaibing 	{HINIC_PORT_CMD_TCAM_FILTER, NULL},
4977dd29ee1SLuo bin 	{HINIC_PORT_CMD_UP_TC_ADD_FLOW, NULL},
4987dd29ee1SLuo bin 	{HINIC_PORT_CMD_UP_TC_DEL_FLOW, NULL},
4997dd29ee1SLuo bin 	{HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, hinic_mbox_check_func_id_8B},
5007dd29ee1SLuo bin 	{HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, hinic_mbox_check_func_id_8B},
5017dd29ee1SLuo bin 	{HINIC_PORT_CMD_UP_TC_ENABLE, hinic_mbox_check_func_id_8B},
5027dd29ee1SLuo bin 	{HINIC_PORT_CMD_CABLE_PLUG_EVENT, NULL},
5037dd29ee1SLuo bin 	{HINIC_PORT_CMD_LINK_ERR_EVENT, NULL},
5047dd29ee1SLuo bin 	{HINIC_PORT_CMD_SET_PORT_STATE, hinic_mbox_check_func_id_8B},
5051f62cfa1SLuo bin 	{HINIC_PORT_CMD_SET_ETS, NULL},
5061f62cfa1SLuo bin 	{HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE, NULL},
507f68910a8SLuo bin 	{HINIC_PORT_CMD_RESET_LINK_CFG, hinic_mbox_check_func_id_8B},
5081f62cfa1SLuo bin 	{HINIC_PORT_CMD_SET_LINK_FOLLOW, NULL},
5091f62cfa1SLuo bin 	{HINIC_PORT_CMD_CLEAR_QP_RES, NULL},
5101f62cfa1SLuo bin };
5111f62cfa1SLuo bin 
5121f62cfa1SLuo bin #define CHECK_IPSU_15BIT	0X8000
5131f62cfa1SLuo bin 
5141f62cfa1SLuo bin static
hinic_get_sriov_info_by_pcidev(struct pci_dev * pdev)5151f62cfa1SLuo bin struct hinic_sriov_info *hinic_get_sriov_info_by_pcidev(struct pci_dev *pdev)
5161f62cfa1SLuo bin {
517ddc2118eSYueHaibing 	struct net_device *netdev = pci_get_drvdata(pdev);
518ddc2118eSYueHaibing 	struct hinic_dev *nic_dev = netdev_priv(netdev);
5191f62cfa1SLuo bin 
5201f62cfa1SLuo bin 	return &nic_dev->sriov_info;
5211f62cfa1SLuo bin }
5221f62cfa1SLuo bin 
hinic_check_mac_info(u8 status,u16 vlan_id)5231f62cfa1SLuo bin static int hinic_check_mac_info(u8 status, u16 vlan_id)
5241f62cfa1SLuo bin {
5251f62cfa1SLuo bin 	if ((status && status != HINIC_MGMT_STATUS_EXIST) ||
5261f62cfa1SLuo bin 	    (vlan_id & CHECK_IPSU_15BIT &&
5271f62cfa1SLuo bin 	     status == HINIC_MGMT_STATUS_EXIST))
5281f62cfa1SLuo bin 		return -EINVAL;
5291f62cfa1SLuo bin 
5301f62cfa1SLuo bin 	return 0;
5311f62cfa1SLuo bin }
5321f62cfa1SLuo bin 
5331f62cfa1SLuo bin #define HINIC_VLAN_ID_MASK	0x7FFF
5341f62cfa1SLuo bin 
hinic_update_mac(struct hinic_hwdev * hwdev,u8 * old_mac,u8 * new_mac,u16 vlan_id,u16 func_id)5351f62cfa1SLuo bin static int hinic_update_mac(struct hinic_hwdev *hwdev, u8 *old_mac,
5361f62cfa1SLuo bin 			    u8 *new_mac, u16 vlan_id, u16 func_id)
5371f62cfa1SLuo bin {
5381f62cfa1SLuo bin 	struct hinic_port_mac_update mac_info = {0};
5391f62cfa1SLuo bin 	u16 out_size = sizeof(mac_info);
5401f62cfa1SLuo bin 	int err;
5411f62cfa1SLuo bin 
5421f62cfa1SLuo bin 	if (!hwdev || !old_mac || !new_mac)
5431f62cfa1SLuo bin 		return -EINVAL;
5441f62cfa1SLuo bin 
5451f62cfa1SLuo bin 	if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) {
5461f62cfa1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Invalid VLAN number: %d\n",
5471f62cfa1SLuo bin 			(vlan_id & HINIC_VLAN_ID_MASK));
5481f62cfa1SLuo bin 		return -EINVAL;
5491f62cfa1SLuo bin 	}
5501f62cfa1SLuo bin 
5511f62cfa1SLuo bin 	mac_info.func_id = func_id;
5521f62cfa1SLuo bin 	mac_info.vlan_id = vlan_id;
5531f62cfa1SLuo bin 	memcpy(mac_info.old_mac, old_mac, ETH_ALEN);
5541f62cfa1SLuo bin 	memcpy(mac_info.new_mac, new_mac, ETH_ALEN);
555ddc2118eSYueHaibing 
5561f62cfa1SLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_UPDATE_MAC, &mac_info,
5571f62cfa1SLuo bin 				 sizeof(mac_info), &mac_info, &out_size);
5581f62cfa1SLuo bin 
5591f62cfa1SLuo bin 	if (err || !out_size ||
5601f62cfa1SLuo bin 	    hinic_check_mac_info(mac_info.status, mac_info.vlan_id)) {
5611f62cfa1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev,
5621f62cfa1SLuo bin 			"Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n",
5631f62cfa1SLuo bin 			err, mac_info.status, out_size);
5641f62cfa1SLuo bin 		return -EINVAL;
5651f62cfa1SLuo bin 	}
5661f62cfa1SLuo bin 
5671f62cfa1SLuo bin 	if (mac_info.status == HINIC_MGMT_STATUS_EXIST)
5681f62cfa1SLuo bin 		dev_warn(&hwdev->hwif->pdev->dev, "MAC is repeated. Ignore update operation\n");
5691f62cfa1SLuo bin 
5701f62cfa1SLuo bin 	return 0;
5711f62cfa1SLuo bin }
5721f62cfa1SLuo bin 
hinic_get_vf_config(struct hinic_hwdev * hwdev,u16 vf_id,struct ifla_vf_info * ivi)5731f62cfa1SLuo bin static void hinic_get_vf_config(struct hinic_hwdev *hwdev, u16 vf_id,
5741f62cfa1SLuo bin 				struct ifla_vf_info *ivi)
5751f62cfa1SLuo bin {
5761f62cfa1SLuo bin 	struct vf_data_storage *vfinfo;
5771f62cfa1SLuo bin 
5781f62cfa1SLuo bin 	vfinfo = hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);
5791f62cfa1SLuo bin 
5801f62cfa1SLuo bin 	ivi->vf = HW_VF_ID_TO_OS(vf_id);
5811f62cfa1SLuo bin 	memcpy(ivi->mac, vfinfo->vf_mac_addr, ETH_ALEN);
5821f62cfa1SLuo bin 	ivi->vlan = vfinfo->pf_vlan;
5831f62cfa1SLuo bin 	ivi->qos = vfinfo->pf_qos;
5841f62cfa1SLuo bin 	ivi->spoofchk = vfinfo->spoofchk;
5851f62cfa1SLuo bin 	ivi->trusted = vfinfo->trust;
5861f62cfa1SLuo bin 	ivi->max_tx_rate = vfinfo->max_rate;
5871f62cfa1SLuo bin 	ivi->min_tx_rate = vfinfo->min_rate;
5881f62cfa1SLuo bin 
5891f62cfa1SLuo bin 	if (!vfinfo->link_forced)
5901f62cfa1SLuo bin 		ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;
5911f62cfa1SLuo bin 	else if (vfinfo->link_up)
5921f62cfa1SLuo bin 		ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE;
5931f62cfa1SLuo bin 	else
594ddc2118eSYueHaibing 		ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE;
595ddc2118eSYueHaibing }
5961f62cfa1SLuo bin 
hinic_ndo_get_vf_config(struct net_device * netdev,int vf,struct ifla_vf_info * ivi)5971f62cfa1SLuo bin int hinic_ndo_get_vf_config(struct net_device *netdev,
5981f62cfa1SLuo bin 			    int vf, struct ifla_vf_info *ivi)
5991f62cfa1SLuo bin {
6001f62cfa1SLuo bin 	struct hinic_dev *nic_dev = netdev_priv(netdev);
6011f62cfa1SLuo bin 	struct hinic_sriov_info *sriov_info;
6021f62cfa1SLuo bin 
6031f62cfa1SLuo bin 	sriov_info = &nic_dev->sriov_info;
6041f62cfa1SLuo bin 	if (vf >= sriov_info->num_vfs)
6051f62cfa1SLuo bin 		return -EINVAL;
6061f62cfa1SLuo bin 
6071f62cfa1SLuo bin 	hinic_get_vf_config(sriov_info->hwdev, OS_VF_ID_TO_HW(vf), ivi);
6081f62cfa1SLuo bin 
6091f62cfa1SLuo bin 	return 0;
6101f62cfa1SLuo bin }
6111f62cfa1SLuo bin 
hinic_set_vf_mac(struct hinic_hwdev * hwdev,int vf,unsigned char * mac_addr)6121f62cfa1SLuo bin static int hinic_set_vf_mac(struct hinic_hwdev *hwdev, int vf,
6131f62cfa1SLuo bin 			    unsigned char *mac_addr)
6141f62cfa1SLuo bin {
6151f62cfa1SLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
6161f62cfa1SLuo bin 	struct vf_data_storage *vf_info;
6171f62cfa1SLuo bin 	u16 func_id;
6181f62cfa1SLuo bin 	int err;
6191f62cfa1SLuo bin 
6201f62cfa1SLuo bin 	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf);
6211f62cfa1SLuo bin 
6221f62cfa1SLuo bin 	/* duplicate request, so just return success */
6231f62cfa1SLuo bin 	if (vf_info->pf_set_mac &&
6241f62cfa1SLuo bin 	    !memcmp(vf_info->vf_mac_addr, mac_addr, ETH_ALEN))
6251f62cfa1SLuo bin 		return 0;
6261f62cfa1SLuo bin 
6271f62cfa1SLuo bin 	vf_info->pf_set_mac = true;
6281f62cfa1SLuo bin 
6291f62cfa1SLuo bin 	func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf;
6301f62cfa1SLuo bin 	err = hinic_update_mac(hwdev, vf_info->vf_mac_addr,
6311f62cfa1SLuo bin 			       mac_addr, 0, func_id);
6321f62cfa1SLuo bin 	if (err) {
6331f62cfa1SLuo bin 		vf_info->pf_set_mac = false;
6341f62cfa1SLuo bin 		return err;
6351f62cfa1SLuo bin 	}
6361f62cfa1SLuo bin 
6371f62cfa1SLuo bin 	memcpy(vf_info->vf_mac_addr, mac_addr, ETH_ALEN);
6381f62cfa1SLuo bin 
6391f62cfa1SLuo bin 	return 0;
6401f62cfa1SLuo bin }
6411f62cfa1SLuo bin 
hinic_ndo_set_vf_mac(struct net_device * netdev,int vf,u8 * mac)6421f62cfa1SLuo bin int hinic_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
6431f62cfa1SLuo bin {
644ddc2118eSYueHaibing 	struct hinic_dev *nic_dev = netdev_priv(netdev);
645ddc2118eSYueHaibing 	struct hinic_sriov_info *sriov_info;
6461f62cfa1SLuo bin 	int err;
6471f62cfa1SLuo bin 
6481f62cfa1SLuo bin 	sriov_info = &nic_dev->sriov_info;
6491f62cfa1SLuo bin 	if (!is_valid_ether_addr(mac) || vf >= sriov_info->num_vfs)
6501f62cfa1SLuo bin 		return -EINVAL;
6511f62cfa1SLuo bin 
6521f62cfa1SLuo bin 	err = hinic_set_vf_mac(sriov_info->hwdev, OS_VF_ID_TO_HW(vf), mac);
6531f62cfa1SLuo bin 	if (err)
6541f62cfa1SLuo bin 		return err;
6551f62cfa1SLuo bin 
6561f62cfa1SLuo bin 	netif_info(nic_dev, drv, netdev, "Setting MAC %pM on VF %d\n", mac, vf);
6571f62cfa1SLuo bin 	netif_info(nic_dev, drv, netdev, "Reload the VF driver to make this change effective.");
6581f62cfa1SLuo bin 
6591f62cfa1SLuo bin 	return 0;
6601f62cfa1SLuo bin }
6611f62cfa1SLuo bin 
hinic_add_vf_vlan(struct hinic_hwdev * hwdev,int vf_id,u16 vlan,u8 qos)662ddc2118eSYueHaibing static int hinic_add_vf_vlan(struct hinic_hwdev *hwdev, int vf_id,
6637dd29ee1SLuo bin 			     u16 vlan, u8 qos)
6647dd29ee1SLuo bin {
6657dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
6667dd29ee1SLuo bin 	int err;
6677dd29ee1SLuo bin 
6687dd29ee1SLuo bin 	err = hinic_set_vf_vlan(hwdev, true, vlan, qos, vf_id);
6697dd29ee1SLuo bin 	if (err)
6707dd29ee1SLuo bin 		return err;
6717dd29ee1SLuo bin 
6727dd29ee1SLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan;
6737dd29ee1SLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = qos;
6747dd29ee1SLuo bin 
6757dd29ee1SLuo bin 	dev_info(&hwdev->hwif->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",
6767dd29ee1SLuo bin 		 vlan, qos, HW_VF_ID_TO_OS(vf_id));
6777dd29ee1SLuo bin 	return 0;
6787dd29ee1SLuo bin }
6797dd29ee1SLuo bin 
hinic_kill_vf_vlan(struct hinic_hwdev * hwdev,int vf_id)6807dd29ee1SLuo bin static int hinic_kill_vf_vlan(struct hinic_hwdev *hwdev, int vf_id)
6817dd29ee1SLuo bin {
6827dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
6837dd29ee1SLuo bin 	int err;
684ddc2118eSYueHaibing 
685ddc2118eSYueHaibing 	err = hinic_set_vf_vlan(hwdev, false,
6861f62cfa1SLuo bin 				nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,
6871f62cfa1SLuo bin 				nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos,
6881f62cfa1SLuo bin 				vf_id);
6891f62cfa1SLuo bin 	if (err)
6901f62cfa1SLuo bin 		return err;
6911f62cfa1SLuo bin 
6921f62cfa1SLuo bin 	dev_info(&hwdev->hwif->pdev->dev, "Remove VLAN %d on VF %d\n",
6931f62cfa1SLuo bin 		 nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,
6941f62cfa1SLuo bin 		 HW_VF_ID_TO_OS(vf_id));
6951f62cfa1SLuo bin 
6961f62cfa1SLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = 0;
6971f62cfa1SLuo bin 	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = 0;
6981f62cfa1SLuo bin 
6991f62cfa1SLuo bin 	return 0;
7001f62cfa1SLuo bin }
7011f62cfa1SLuo bin 
hinic_update_mac_vlan(struct hinic_dev * nic_dev,u16 old_vlan,u16 new_vlan,int vf_id)7021f62cfa1SLuo bin static int hinic_update_mac_vlan(struct hinic_dev *nic_dev, u16 old_vlan,
7031f62cfa1SLuo bin 				 u16 new_vlan, int vf_id)
7041f62cfa1SLuo bin {
7051f62cfa1SLuo bin 	struct vf_data_storage *vf_info;
7061f62cfa1SLuo bin 	u16 vlan_id;
7071f62cfa1SLuo bin 	int err;
7081f62cfa1SLuo bin 
7091f62cfa1SLuo bin 	if (!nic_dev || old_vlan >= VLAN_N_VID || new_vlan >= VLAN_N_VID)
7101f62cfa1SLuo bin 		return -EINVAL;
7111f62cfa1SLuo bin 
7121f62cfa1SLuo bin 	vf_info = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);
7131f62cfa1SLuo bin 	if (!vf_info->pf_set_mac)
7141f62cfa1SLuo bin 		return 0;
7151f62cfa1SLuo bin 
7161f62cfa1SLuo bin 	vlan_id = old_vlan;
7171f62cfa1SLuo bin 	if (vlan_id)
7181f62cfa1SLuo bin 		vlan_id |= HINIC_ADD_VLAN_IN_MAC;
7191f62cfa1SLuo bin 
7201f62cfa1SLuo bin 	err = hinic_port_del_mac(nic_dev, vf_info->vf_mac_addr, vlan_id);
7211f62cfa1SLuo bin 	if (err) {
7221f62cfa1SLuo bin 		dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to delete VF %d MAC %pM vlan %d\n",
7231f62cfa1SLuo bin 			HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, old_vlan);
7241f62cfa1SLuo bin 		return err;
7251f62cfa1SLuo bin 	}
7261f62cfa1SLuo bin 
7271f62cfa1SLuo bin 	vlan_id = new_vlan;
7281f62cfa1SLuo bin 	if (vlan_id)
7291f62cfa1SLuo bin 		vlan_id |= HINIC_ADD_VLAN_IN_MAC;
7301f62cfa1SLuo bin 
7311f62cfa1SLuo bin 	err = hinic_port_add_mac(nic_dev, vf_info->vf_mac_addr, vlan_id);
7321f62cfa1SLuo bin 	if (err) {
7331f62cfa1SLuo bin 		dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to add VF %d MAC %pM vlan %d\n",
7341f62cfa1SLuo bin 			HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, new_vlan);
7351f62cfa1SLuo bin 		goto out;
7361f62cfa1SLuo bin 	}
7371f62cfa1SLuo bin 
7381f62cfa1SLuo bin 	return 0;
7391f62cfa1SLuo bin 
7401f62cfa1SLuo bin out:
7411f62cfa1SLuo bin 	vlan_id = old_vlan;
7421f62cfa1SLuo bin 	if (vlan_id)
7431f62cfa1SLuo bin 		vlan_id |= HINIC_ADD_VLAN_IN_MAC;
7441f62cfa1SLuo bin 	hinic_port_add_mac(nic_dev, vf_info->vf_mac_addr, vlan_id);
7451f62cfa1SLuo bin 
7461f62cfa1SLuo bin 	return err;
7471f62cfa1SLuo bin }
7481f62cfa1SLuo bin 
set_hw_vf_vlan(struct hinic_dev * nic_dev,u16 cur_vlanprio,int vf,u16 vlan,u8 qos)7491f62cfa1SLuo bin static int set_hw_vf_vlan(struct hinic_dev *nic_dev,
7501f62cfa1SLuo bin 			  u16 cur_vlanprio, int vf, u16 vlan, u8 qos)
7511f62cfa1SLuo bin {
7521f62cfa1SLuo bin 	u16 old_vlan = cur_vlanprio & VLAN_VID_MASK;
7531f62cfa1SLuo bin 	int err = 0;
7541f62cfa1SLuo bin 
7551f62cfa1SLuo bin 	if (vlan || qos) {
7561f62cfa1SLuo bin 		if (cur_vlanprio) {
7571f62cfa1SLuo bin 			err = hinic_kill_vf_vlan(nic_dev->hwdev,
7581f62cfa1SLuo bin 						 OS_VF_ID_TO_HW(vf));
7591f62cfa1SLuo bin 			if (err) {
7601f62cfa1SLuo bin 				dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to delete vf %d old vlan %d\n",
7611f62cfa1SLuo bin 					vf, old_vlan);
7621f62cfa1SLuo bin 				goto out;
7631f62cfa1SLuo bin 			}
7641f62cfa1SLuo bin 		}
7651f62cfa1SLuo bin 		err = hinic_add_vf_vlan(nic_dev->hwdev,
7661f62cfa1SLuo bin 					OS_VF_ID_TO_HW(vf), vlan, qos);
7671f62cfa1SLuo bin 		if (err) {
7681f62cfa1SLuo bin 			dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to add vf %d new vlan %d\n",
7691f62cfa1SLuo bin 				vf, vlan);
7701f62cfa1SLuo bin 			goto out;
7711f62cfa1SLuo bin 		}
7721f62cfa1SLuo bin 	} else {
7731f62cfa1SLuo bin 		err = hinic_kill_vf_vlan(nic_dev->hwdev, OS_VF_ID_TO_HW(vf));
7741f62cfa1SLuo bin 		if (err) {
7751f62cfa1SLuo bin 			dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to delete vf %d vlan %d\n",
7761f62cfa1SLuo bin 				vf, old_vlan);
7771f62cfa1SLuo bin 			goto out;
778*57ac5715SZhengchao Shao 		}
7791f62cfa1SLuo bin 	}
7801f62cfa1SLuo bin 
7811f62cfa1SLuo bin 	err = hinic_update_mac_vlan(nic_dev, old_vlan, vlan,
7821f62cfa1SLuo bin 				    OS_VF_ID_TO_HW(vf));
7831f62cfa1SLuo bin 
7841f62cfa1SLuo bin out:
7851f62cfa1SLuo bin 	return err;
7861f62cfa1SLuo bin }
7871f62cfa1SLuo bin 
hinic_ndo_set_vf_vlan(struct net_device * netdev,int vf,u16 vlan,u8 qos,__be16 vlan_proto)7881f62cfa1SLuo bin int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
7891f62cfa1SLuo bin 			  __be16 vlan_proto)
7901f62cfa1SLuo bin {
7911f62cfa1SLuo bin 	struct hinic_dev *nic_dev = netdev_priv(netdev);
792ddc2118eSYueHaibing 	struct hinic_sriov_info *sriov_info;
793ddc2118eSYueHaibing 	u16 vlanprio, cur_vlanprio;
7941f62cfa1SLuo bin 
7951f62cfa1SLuo bin 	sriov_info = &nic_dev->sriov_info;
7961f62cfa1SLuo bin 	if (vf >= sriov_info->num_vfs || vlan >= VLAN_N_VID || qos > HINIC_MAX_QOS)
7971f62cfa1SLuo bin 		return -EINVAL;
7981f62cfa1SLuo bin 	if (vlan_proto != htons(ETH_P_8021Q))
7991f62cfa1SLuo bin 		return -EPROTONOSUPPORT;
8001f62cfa1SLuo bin 	vlanprio = vlan | qos << HINIC_VLAN_PRIORITY_SHIFT;
8011f62cfa1SLuo bin 	cur_vlanprio = hinic_vf_info_vlanprio(nic_dev->hwdev,
8021f62cfa1SLuo bin 					      OS_VF_ID_TO_HW(vf));
8031f62cfa1SLuo bin 	/* duplicate request, so just return success */
8041f62cfa1SLuo bin 	if (vlanprio == cur_vlanprio)
8051f62cfa1SLuo bin 		return 0;
8061f62cfa1SLuo bin 
8071f62cfa1SLuo bin 	return set_hw_vf_vlan(nic_dev, cur_vlanprio, vf, vlan, qos);
8081f62cfa1SLuo bin }
8091f62cfa1SLuo bin 
hinic_set_vf_trust(struct hinic_hwdev * hwdev,u16 vf_id,bool trust)8101f62cfa1SLuo bin static int hinic_set_vf_trust(struct hinic_hwdev *hwdev, u16 vf_id,
8111f62cfa1SLuo bin 			      bool trust)
8121f62cfa1SLuo bin {
8131f62cfa1SLuo bin 	struct vf_data_storage *vf_infos;
8141f62cfa1SLuo bin 	struct hinic_func_to_io *nic_io;
8151f62cfa1SLuo bin 
8161f62cfa1SLuo bin 	if (!hwdev)
8171f62cfa1SLuo bin 		return -EINVAL;
8181f62cfa1SLuo bin 
8191f62cfa1SLuo bin 	nic_io = &hwdev->func_to_io;
8201f62cfa1SLuo bin 	vf_infos = nic_io->vf_infos;
8211f62cfa1SLuo bin 	vf_infos[vf_id].trust = trust;
8221f62cfa1SLuo bin 
8231f62cfa1SLuo bin 	return 0;
8244f304250SZhengchao Shao }
8251f62cfa1SLuo bin 
hinic_ndo_set_vf_trust(struct net_device * netdev,int vf,bool setting)8261f62cfa1SLuo bin int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
8271f62cfa1SLuo bin {
8281f62cfa1SLuo bin 	struct hinic_dev *adapter = netdev_priv(netdev);
8291f62cfa1SLuo bin 	struct hinic_sriov_info *sriov_info;
8301f62cfa1SLuo bin 	struct hinic_func_to_io *nic_io;
8311f62cfa1SLuo bin 	bool cur_trust;
8321f62cfa1SLuo bin 	int err;
8331f62cfa1SLuo bin 
8341f62cfa1SLuo bin 	sriov_info = &adapter->sriov_info;
8351f62cfa1SLuo bin 	nic_io = &adapter->hwdev->func_to_io;
8361f62cfa1SLuo bin 
8371f62cfa1SLuo bin 	if (vf >= sriov_info->num_vfs)
83872ef908bSLuo bin 		return -EINVAL;
83972ef908bSLuo bin 
84072ef908bSLuo bin 	cur_trust = nic_io->vf_infos[vf].trust;
84136d5825bSColin Ian King 	/* same request, so just return success */
84236d5825bSColin Ian King 	if (setting == cur_trust)
84336d5825bSColin Ian King 		return 0;
84436d5825bSColin Ian King 
84572ef908bSLuo bin 	err = hinic_set_vf_trust(adapter->hwdev, vf, setting);
84672ef908bSLuo bin 	if (!err)
84772ef908bSLuo bin 		dev_info(&sriov_info->pdev->dev, "Set VF %d trusted %s succeed\n",
84872ef908bSLuo bin 			 vf, setting ? "on" : "off");
84972ef908bSLuo bin 	else
85072ef908bSLuo bin 		dev_err(&sriov_info->pdev->dev, "Failed set VF %d trusted %s\n",
85172ef908bSLuo bin 			vf, setting ? "on" : "off");
85272ef908bSLuo bin 
85372ef908bSLuo bin 	return err;
85472ef908bSLuo bin }
85572ef908bSLuo bin 
hinic_ndo_set_vf_bw(struct net_device * netdev,int vf,int min_tx_rate,int max_tx_rate)85672ef908bSLuo bin int hinic_ndo_set_vf_bw(struct net_device *netdev,
85772ef908bSLuo bin 			int vf, int min_tx_rate, int max_tx_rate)
85872ef908bSLuo bin {
85972ef908bSLuo bin 	static const u32 speeds[] = {
86072ef908bSLuo bin 		SPEED_10, SPEED_100, SPEED_1000, SPEED_10000,
86172ef908bSLuo bin 		SPEED_25000, SPEED_40000, SPEED_100000
86272ef908bSLuo bin 	};
86372ef908bSLuo bin 	struct hinic_dev *nic_dev = netdev_priv(netdev);
86472ef908bSLuo bin 	struct hinic_port_cap port_cap = { 0 };
86572ef908bSLuo bin 	enum hinic_port_link_state link_state;
86672ef908bSLuo bin 	int err;
86772ef908bSLuo bin 
86872ef908bSLuo bin 	if (vf >= nic_dev->sriov_info.num_vfs) {
86972ef908bSLuo bin 		netif_err(nic_dev, drv, netdev, "VF number must be less than %d\n",
87072ef908bSLuo bin 			  nic_dev->sriov_info.num_vfs);
87172ef908bSLuo bin 		return -EINVAL;
87272ef908bSLuo bin 	}
87372ef908bSLuo bin 
87472ef908bSLuo bin 	err = hinic_port_link_state(nic_dev, &link_state);
87572ef908bSLuo bin 	if (err) {
87672ef908bSLuo bin 		netif_err(nic_dev, drv, netdev,
87772ef908bSLuo bin 			  "Get link status failed when setting vf tx rate\n");
87872ef908bSLuo bin 		return -EIO;
87972ef908bSLuo bin 	}
88072ef908bSLuo bin 
88172ef908bSLuo bin 	if (link_state == HINIC_LINK_STATE_DOWN) {
88272ef908bSLuo bin 		netif_err(nic_dev, drv, netdev,
88372ef908bSLuo bin 			  "Link status must be up when setting vf tx rate\n");
88472ef908bSLuo bin 		return -EPERM;
88572ef908bSLuo bin 	}
88672ef908bSLuo bin 
88772ef908bSLuo bin 	err = hinic_port_get_cap(nic_dev, &port_cap);
88872ef908bSLuo bin 	if (err || port_cap.speed > LINK_SPEED_100GB)
88972ef908bSLuo bin 		return -EIO;
89072ef908bSLuo bin 
89172ef908bSLuo bin 	/* rate limit cannot be less than 0 and greater than link speed */
89272ef908bSLuo bin 	if (max_tx_rate < 0 || max_tx_rate > speeds[port_cap.speed]) {
89372ef908bSLuo bin 		netif_err(nic_dev, drv, netdev, "Max tx rate must be in [0 - %d]\n",
89472ef908bSLuo bin 			  speeds[port_cap.speed]);
89572ef908bSLuo bin 		return -EINVAL;
89672ef908bSLuo bin 	}
89772ef908bSLuo bin 
89872ef908bSLuo bin 	err = hinic_set_vf_tx_rate(nic_dev->hwdev, OS_VF_ID_TO_HW(vf),
89972ef908bSLuo bin 				   max_tx_rate, min_tx_rate);
90072ef908bSLuo bin 	if (err) {
90172ef908bSLuo bin 		netif_err(nic_dev, drv, netdev,
90272ef908bSLuo bin 			  "Unable to set VF %d max rate %d min rate %d%s\n",
90372ef908bSLuo bin 			  vf, max_tx_rate, min_tx_rate,
90472ef908bSLuo bin 			  err == HINIC_TX_RATE_TABLE_FULL ?
90572ef908bSLuo bin 			  ", tx rate profile is full" : "");
90672ef908bSLuo bin 		return -EIO;
90772ef908bSLuo bin 	}
90872ef908bSLuo bin 
90972ef908bSLuo bin 	netif_info(nic_dev, drv, netdev,
91072ef908bSLuo bin 		   "Set VF %d max tx rate %d min tx rate %d successfully\n",
91172ef908bSLuo bin 		   vf, max_tx_rate, min_tx_rate);
91272ef908bSLuo bin 
91372ef908bSLuo bin 	return 0;
91472ef908bSLuo bin }
91572ef908bSLuo bin 
hinic_set_vf_spoofchk(struct hinic_hwdev * hwdev,u16 vf_id,bool spoofchk)91672ef908bSLuo bin static int hinic_set_vf_spoofchk(struct hinic_hwdev *hwdev, u16 vf_id,
91772ef908bSLuo bin 				 bool spoofchk)
91872ef908bSLuo bin {
91972ef908bSLuo bin 	struct hinic_spoofchk_set spoofchk_cfg = {0};
92072ef908bSLuo bin 	struct vf_data_storage *vf_infos = NULL;
92172ef908bSLuo bin 	u16 out_size = sizeof(spoofchk_cfg);
92272ef908bSLuo bin 	int err;
92372ef908bSLuo bin 
92472ef908bSLuo bin 	if (!hwdev)
92572ef908bSLuo bin 		return -EINVAL;
92672ef908bSLuo bin 
92772ef908bSLuo bin 	vf_infos = hwdev->func_to_io.vf_infos;
92872ef908bSLuo bin 
92972ef908bSLuo bin 	spoofchk_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
93072ef908bSLuo bin 	spoofchk_cfg.state = spoofchk ? 1 : 0;
93172ef908bSLuo bin 	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ENABLE_SPOOFCHK,
93272ef908bSLuo bin 				 &spoofchk_cfg, sizeof(spoofchk_cfg),
93372ef908bSLuo bin 				 &spoofchk_cfg, &out_size);
93472ef908bSLuo bin 	if (spoofchk_cfg.status == HINIC_MGMT_CMD_UNSUPPORTED) {
93572ef908bSLuo bin 		err = HINIC_MGMT_CMD_UNSUPPORTED;
93672ef908bSLuo bin 	} else if (err || !out_size || spoofchk_cfg.status) {
93772ef908bSLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) spoofchk, err: %d, status: 0x%x, out size: 0x%x\n",
93872ef908bSLuo bin 			HW_VF_ID_TO_OS(vf_id), err, spoofchk_cfg.status,
93972ef908bSLuo bin 			out_size);
94072ef908bSLuo bin 		err = -EIO;
94172ef908bSLuo bin 	}
94272ef908bSLuo bin 
94372ef908bSLuo bin 	vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk = spoofchk;
9444f304250SZhengchao Shao 
94572ef908bSLuo bin 	return err;
94672ef908bSLuo bin }
94772ef908bSLuo bin 
hinic_ndo_set_vf_spoofchk(struct net_device * netdev,int vf,bool setting)94872ef908bSLuo bin int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
94972ef908bSLuo bin {
95072ef908bSLuo bin 	struct hinic_dev *nic_dev = netdev_priv(netdev);
95172ef908bSLuo bin 	struct hinic_sriov_info *sriov_info;
95272ef908bSLuo bin 	bool cur_spoofchk;
95372ef908bSLuo bin 	int err;
95472ef908bSLuo bin 
95572ef908bSLuo bin 	sriov_info = &nic_dev->sriov_info;
95672ef908bSLuo bin 	if (vf >= sriov_info->num_vfs)
95772ef908bSLuo bin 		return -EINVAL;
95872ef908bSLuo bin 
95972ef908bSLuo bin 	cur_spoofchk = nic_dev->hwdev->func_to_io.vf_infos[vf].spoofchk;
96072ef908bSLuo bin 
96172ef908bSLuo bin 	/* same request, so just return success */
96272ef908bSLuo bin 	if (setting == cur_spoofchk)
96372ef908bSLuo bin 		return 0;
96472ef908bSLuo bin 
96572ef908bSLuo bin 	err = hinic_set_vf_spoofchk(sriov_info->hwdev,
96672ef908bSLuo bin 				    OS_VF_ID_TO_HW(vf), setting);
96772ef908bSLuo bin 	if (!err) {
96872ef908bSLuo bin 		netif_info(nic_dev, drv, netdev, "Set VF %d spoofchk %s successfully\n",
96972ef908bSLuo bin 			   vf, setting ? "on" : "off");
97072ef908bSLuo bin 	} else if (err == HINIC_MGMT_CMD_UNSUPPORTED) {
97172ef908bSLuo bin 		netif_err(nic_dev, drv, netdev,
97272ef908bSLuo bin 			  "Current firmware doesn't support to set vf spoofchk, need to upgrade latest firmware version\n");
97372ef908bSLuo bin 		err = -EOPNOTSUPP;
97472ef908bSLuo bin 	}
97572ef908bSLuo bin 
97672ef908bSLuo bin 	return err;
97772ef908bSLuo bin }
97872ef908bSLuo bin 
hinic_set_vf_link_state(struct hinic_hwdev * hwdev,u16 vf_id,int link)97972ef908bSLuo bin static int hinic_set_vf_link_state(struct hinic_hwdev *hwdev, u16 vf_id,
98072ef908bSLuo bin 				   int link)
98172ef908bSLuo bin {
98272ef908bSLuo bin 	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
98372ef908bSLuo bin 	struct vf_data_storage *vf_infos = nic_io->vf_infos;
98472ef908bSLuo bin 	u8 link_status = 0;
98572ef908bSLuo bin 
98672ef908bSLuo bin 	switch (link) {
98772ef908bSLuo bin 	case HINIC_IFLA_VF_LINK_STATE_AUTO:
98872ef908bSLuo bin 		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false;
98972ef908bSLuo bin 		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = nic_io->link_status ?
99072ef908bSLuo bin 			true : false;
99172ef908bSLuo bin 		link_status = nic_io->link_status;
99272ef908bSLuo bin 		break;
99372ef908bSLuo bin 	case HINIC_IFLA_VF_LINK_STATE_ENABLE:
99472ef908bSLuo bin 		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true;
99572ef908bSLuo bin 		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = true;
99672ef908bSLuo bin 		link_status = HINIC_LINK_UP;
99772ef908bSLuo bin 		break;
99872ef908bSLuo bin 	case HINIC_IFLA_VF_LINK_STATE_DISABLE:
99972ef908bSLuo bin 		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true;
100072ef908bSLuo bin 		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = false;
100172ef908bSLuo bin 		link_status = HINIC_LINK_DOWN;
100272ef908bSLuo bin 		break;
100372ef908bSLuo bin 	default:
100472ef908bSLuo bin 		return -EINVAL;
100572ef908bSLuo bin 	}
100672ef908bSLuo bin 
100772ef908bSLuo bin 	/* Notify the VF of its new link state */
100872ef908bSLuo bin 	hinic_notify_vf_link_status(hwdev, vf_id, link_status);
100972ef908bSLuo bin 
101072ef908bSLuo bin 	return 0;
101172ef908bSLuo bin }
10127dd29ee1SLuo bin 
hinic_ndo_set_vf_link_state(struct net_device * netdev,int vf_id,int link)1013ddc2118eSYueHaibing int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
10147dd29ee1SLuo bin {
10157dd29ee1SLuo bin 	struct hinic_dev *nic_dev = netdev_priv(netdev);
1016c8c29ec3SLuo bin 	struct hinic_sriov_info *sriov_info;
10177dd29ee1SLuo bin 
10187dd29ee1SLuo bin 	sriov_info = &nic_dev->sriov_info;
10197dd29ee1SLuo bin 
10207dd29ee1SLuo bin 	if (vf_id >= sriov_info->num_vfs) {
10217dd29ee1SLuo bin 		netif_err(nic_dev, drv, netdev,
102240cf7fbeSZou Wei 			  "Invalid VF Identifier %d\n", vf_id);
10237dd29ee1SLuo bin 		return -EINVAL;
10247dd29ee1SLuo bin 	}
1025c8c29ec3SLuo bin 
1026c8c29ec3SLuo bin 	return hinic_set_vf_link_state(sriov_info->hwdev,
1027c8c29ec3SLuo bin 				      OS_VF_ID_TO_HW(vf_id), link);
1028c8c29ec3SLuo bin }
1029c8c29ec3SLuo bin 
1030c8c29ec3SLuo bin /* pf receive message from vf */
nic_pf_mbox_handler(void * hwdev,u16 vf_id,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)1031c8c29ec3SLuo bin static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
1032c8c29ec3SLuo bin 			       u16 in_size, void *buf_out, u16 *out_size)
1033c8c29ec3SLuo bin {
10347dd29ee1SLuo bin 	u8 size = ARRAY_SIZE(nic_cmd_support_vf);
10357dd29ee1SLuo bin 	struct vf_cmd_msg_handle *vf_msg_handle;
10367dd29ee1SLuo bin 	struct hinic_hwdev *dev = hwdev;
103740cf7fbeSZou Wei 	struct hinic_func_to_io *nic_io;
10387dd29ee1SLuo bin 	struct hinic_pfhwdev *pfhwdev;
10397dd29ee1SLuo bin 	int err = 0;
10407dd29ee1SLuo bin 	u32 i;
10417dd29ee1SLuo bin 
10427dd29ee1SLuo bin 	if (!hwdev)
10437dd29ee1SLuo bin 		return -EINVAL;
10447dd29ee1SLuo bin 
10457dd29ee1SLuo bin 	if (!hinic_mbox_check_cmd_valid(hwdev, nic_cmd_support_vf, vf_id, cmd,
10467dd29ee1SLuo bin 					buf_in, in_size, size)) {
10477dd29ee1SLuo bin 		dev_err(&dev->hwif->pdev->dev,
104840cf7fbeSZou Wei 			"PF Receive VF nic cmd: 0x%x, mbox len: 0x%x is invalid\n",
10497dd29ee1SLuo bin 			cmd, in_size);
10507dd29ee1SLuo bin 		return HINIC_MBOX_VF_CMD_ERROR;
10517dd29ee1SLuo bin 	}
10527dd29ee1SLuo bin 
10537dd29ee1SLuo bin 	pfhwdev = container_of(dev, struct hinic_pfhwdev, hwdev);
10547dd29ee1SLuo bin 	nic_io = &dev->func_to_io;
10557dd29ee1SLuo bin 	for (i = 0; i < ARRAY_SIZE(nic_vf_cmd_msg_handler); i++) {
10567dd29ee1SLuo bin 		vf_msg_handle = &nic_vf_cmd_msg_handler[i];
10577dd29ee1SLuo bin 		if (cmd == vf_msg_handle->cmd &&
10587dd29ee1SLuo bin 		    vf_msg_handle->cmd_msg_handler) {
10597dd29ee1SLuo bin 			err = vf_msg_handle->cmd_msg_handler(hwdev, vf_id,
10607dd29ee1SLuo bin 							     buf_in, in_size,
10617dd29ee1SLuo bin 							     buf_out,
10627dd29ee1SLuo bin 							     out_size);
10637dd29ee1SLuo bin 			break;
10647dd29ee1SLuo bin 		}
10657dd29ee1SLuo bin 	}
10667dd29ee1SLuo bin 	if (i == ARRAY_SIZE(nic_vf_cmd_msg_handler))
10677dd29ee1SLuo bin 		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC,
10687dd29ee1SLuo bin 					cmd, buf_in, in_size, buf_out,
10697dd29ee1SLuo bin 					out_size, HINIC_MGMT_MSG_SYNC);
10707dd29ee1SLuo bin 
10717dd29ee1SLuo bin 	if (err &&  err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)
107207afcc7aSLuo bin 		dev_err(&nic_io->hwif->pdev->dev, "PF receive VF L2NIC cmd: %d process error, err:%d\n",
10737dd29ee1SLuo bin 			cmd, err);
10747dd29ee1SLuo bin 	return err;
10757dd29ee1SLuo bin }
10767dd29ee1SLuo bin 
cfg_mbx_pf_proc_vf_msg(void * hwdev,u16 vf_id,u8 cmd,void * buf_in,u16 in_size,void * buf_out,u16 * out_size)10777dd29ee1SLuo bin static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
10787dd29ee1SLuo bin 				  u16 in_size, void *buf_out, u16 *out_size)
10797dd29ee1SLuo bin {
10807dd29ee1SLuo bin 	struct hinic_dev_cap *dev_cap = buf_out;
10817dd29ee1SLuo bin 	struct hinic_hwdev *dev = hwdev;
10827dd29ee1SLuo bin 	struct hinic_cap *cap;
10837dd29ee1SLuo bin 
10847dd29ee1SLuo bin 	cap = &dev->nic_cap;
10857dd29ee1SLuo bin 	memset(dev_cap, 0, sizeof(*dev_cap));
10867dd29ee1SLuo bin 
10877dd29ee1SLuo bin 	dev_cap->max_vf = cap->max_vf;
10887dd29ee1SLuo bin 	dev_cap->max_sqs = cap->max_vf_qps;
10897dd29ee1SLuo bin 	dev_cap->max_rqs = cap->max_vf_qps;
10907dd29ee1SLuo bin 	dev_cap->port_id = dev->port_id;
10917dd29ee1SLuo bin 
10927dd29ee1SLuo bin 	*out_size = sizeof(*dev_cap);
10937dd29ee1SLuo bin 
10947dd29ee1SLuo bin 	return 0;
10957dd29ee1SLuo bin }
10967dd29ee1SLuo bin 
hinic_init_vf_infos(struct hinic_func_to_io * nic_io,u16 vf_id)10977dd29ee1SLuo bin static int hinic_init_vf_infos(struct hinic_func_to_io *nic_io, u16 vf_id)
10987dd29ee1SLuo bin {
10997dd29ee1SLuo bin 	struct vf_data_storage *vf_infos = nic_io->vf_infos;
11007dd29ee1SLuo bin 
11017dd29ee1SLuo bin 	if (set_vf_link_state > HINIC_IFLA_VF_LINK_STATE_DISABLE) {
11027dd29ee1SLuo bin 		dev_warn(&nic_io->hwif->pdev->dev, "Module Parameter set_vf_link_state value %d is out of range, resetting to %d\n",
11037dd29ee1SLuo bin 			 set_vf_link_state, HINIC_IFLA_VF_LINK_STATE_AUTO);
11047dd29ee1SLuo bin 		set_vf_link_state = HINIC_IFLA_VF_LINK_STATE_AUTO;
11057dd29ee1SLuo bin 	}
11067dd29ee1SLuo bin 
11077dd29ee1SLuo bin 	switch (set_vf_link_state) {
11087dd29ee1SLuo bin 	case HINIC_IFLA_VF_LINK_STATE_AUTO:
11097dd29ee1SLuo bin 		vf_infos[vf_id].link_forced = false;
1110ddc2118eSYueHaibing 		break;
11117dd29ee1SLuo bin 	case HINIC_IFLA_VF_LINK_STATE_ENABLE:
11127dd29ee1SLuo bin 		vf_infos[vf_id].link_forced = true;
11137dd29ee1SLuo bin 		vf_infos[vf_id].link_up = true;
11147dd29ee1SLuo bin 		break;
11157dd29ee1SLuo bin 	case HINIC_IFLA_VF_LINK_STATE_DISABLE:
11167dd29ee1SLuo bin 		vf_infos[vf_id].link_forced = true;
11177dd29ee1SLuo bin 		vf_infos[vf_id].link_up = false;
11187dd29ee1SLuo bin 		break;
11197dd29ee1SLuo bin 	default:
11207dd29ee1SLuo bin 		dev_err(&nic_io->hwif->pdev->dev, "Invalid input parameter set_vf_link_state: %d\n",
112172ef908bSLuo bin 			set_vf_link_state);
112272ef908bSLuo bin 		return -EINVAL;
112372ef908bSLuo bin 	}
112472ef908bSLuo bin 
112572ef908bSLuo bin 	return 0;
112672ef908bSLuo bin }
11271f62cfa1SLuo bin 
hinic_clear_vf_infos(struct hinic_dev * nic_dev,u16 vf_id)11281f62cfa1SLuo bin static void hinic_clear_vf_infos(struct hinic_dev *nic_dev, u16 vf_id)
11291f62cfa1SLuo bin {
11307dd29ee1SLuo bin 	struct vf_data_storage *vf_infos;
11317dd29ee1SLuo bin 
11327dd29ee1SLuo bin 	vf_infos = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);
11337dd29ee1SLuo bin 	if (vf_infos->pf_set_mac)
11347dd29ee1SLuo bin 		hinic_port_del_mac(nic_dev, vf_infos->vf_mac_addr, 0);
1135dcbe72d2SZhengchao Shao 
1136ddc2118eSYueHaibing 	if (hinic_vf_info_vlanprio(nic_dev->hwdev, vf_id))
11377dd29ee1SLuo bin 		hinic_kill_vf_vlan(nic_dev->hwdev, vf_id);
11387dd29ee1SLuo bin 
11397dd29ee1SLuo bin 	if (vf_infos->max_rate)
11407dd29ee1SLuo bin 		hinic_set_vf_tx_rate(nic_dev->hwdev, vf_id, 0, 0);
11417dd29ee1SLuo bin 
11427dd29ee1SLuo bin 	if (vf_infos->spoofchk)
11437dd29ee1SLuo bin 		hinic_set_vf_spoofchk(nic_dev->hwdev, vf_id, false);
11447dd29ee1SLuo bin 
11457dd29ee1SLuo bin 	if (vf_infos->trust)
11467dd29ee1SLuo bin 		hinic_set_vf_trust(nic_dev->hwdev, vf_id, false);
11477dd29ee1SLuo bin 
11487dd29ee1SLuo bin 	memset(vf_infos, 0, sizeof(*vf_infos));
11497dd29ee1SLuo bin 	/* set vf_infos to default */
11507dd29ee1SLuo bin 	hinic_init_vf_infos(&nic_dev->hwdev->func_to_io, HW_VF_ID_TO_OS(vf_id));
11517dd29ee1SLuo bin }
11527dd29ee1SLuo bin 
hinic_deinit_vf_hw(struct hinic_sriov_info * sriov_info,u16 start_vf_id,u16 end_vf_id)11537dd29ee1SLuo bin static void hinic_deinit_vf_hw(struct hinic_sriov_info *sriov_info,
11547dd29ee1SLuo bin 			       u16 start_vf_id, u16 end_vf_id)
11557dd29ee1SLuo bin {
11567dd29ee1SLuo bin 	struct hinic_dev *nic_dev;
11577dd29ee1SLuo bin 	u16 func_idx, idx;
11587dd29ee1SLuo bin 
1159088c5f0dSLuo bin 	nic_dev = container_of(sriov_info, struct hinic_dev, sriov_info);
1160088c5f0dSLuo bin 
1161088c5f0dSLuo bin 	for (idx = start_vf_id; idx <= end_vf_id; idx++) {
1162088c5f0dSLuo bin 		func_idx = hinic_glb_pf_vf_offset(nic_dev->hwdev->hwif) + idx;
1163088c5f0dSLuo bin 		hinic_set_wq_page_size(nic_dev->hwdev, func_idx,
1164088c5f0dSLuo bin 				       HINIC_HW_WQ_PAGE_SIZE);
1165088c5f0dSLuo bin 		hinic_clear_vf_infos(nic_dev, idx);
11667dd29ee1SLuo bin 	}
11677dd29ee1SLuo bin }
11687dd29ee1SLuo bin 
hinic_vf_func_init(struct hinic_hwdev * hwdev)11697dd29ee1SLuo bin int hinic_vf_func_init(struct hinic_hwdev *hwdev)
11707dd29ee1SLuo bin {
11717dd29ee1SLuo bin 	struct hinic_register_vf register_info = {0};
11727dd29ee1SLuo bin 	u16 out_size = sizeof(register_info);
11737dd29ee1SLuo bin 	struct hinic_func_to_io *nic_io;
11747dd29ee1SLuo bin 	int err = 0;
11757dd29ee1SLuo bin 	u32 size, i;
11767dd29ee1SLuo bin 
11777dd29ee1SLuo bin 	err = hinic_vf_mbox_random_id_init(hwdev);
11787dd29ee1SLuo bin 	if (err) {
11797dd29ee1SLuo bin 		dev_err(&hwdev->hwif->pdev->dev, "Failed to init vf mbox random id, err: %d\n",
11807dd29ee1SLuo bin 			err);
11817dd29ee1SLuo bin 		return err;
11827dd29ee1SLuo bin 	}
11837dd29ee1SLuo bin 
11847dd29ee1SLuo bin 	nic_io = &hwdev->func_to_io;
11857dd29ee1SLuo bin 
11867dd29ee1SLuo bin 	if (HINIC_IS_VF(hwdev->hwif)) {
11877dd29ee1SLuo bin 		err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
11887dd29ee1SLuo bin 				       HINIC_PORT_CMD_VF_REGISTER,
11897dd29ee1SLuo bin 				       &register_info, sizeof(register_info),
11907dd29ee1SLuo bin 				       &register_info, &out_size, 0);
11917dd29ee1SLuo bin 		if (err || register_info.status || !out_size) {
11927dd29ee1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev,
11937dd29ee1SLuo bin 				"Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",
11947dd29ee1SLuo bin 				err, register_info.status, out_size);
11957dd29ee1SLuo bin 			return -EIO;
11967dd29ee1SLuo bin 		}
11977dd29ee1SLuo bin 	} else {
11987dd29ee1SLuo bin 		err = hinic_register_pf_mbox_cb(hwdev, HINIC_MOD_CFGM,
11997dd29ee1SLuo bin 						cfg_mbx_pf_proc_vf_msg);
12007dd29ee1SLuo bin 		if (err) {
12017dd29ee1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev,
12027dd29ee1SLuo bin 				"Register PF mailbox callback failed\n");
12037dd29ee1SLuo bin 			return err;
12047dd29ee1SLuo bin 		}
12057dd29ee1SLuo bin 		nic_io->max_vfs = hwdev->nic_cap.max_vf;
12067dd29ee1SLuo bin 		size = sizeof(*nic_io->vf_infos) * nic_io->max_vfs;
12077dd29ee1SLuo bin 		if (size != 0) {
12087dd29ee1SLuo bin 			nic_io->vf_infos = kzalloc(size, GFP_KERNEL);
12097dd29ee1SLuo bin 			if (!nic_io->vf_infos) {
12107dd29ee1SLuo bin 				err = -ENOMEM;
12117dd29ee1SLuo bin 				goto out_free_nic_io;
12127dd29ee1SLuo bin 			}
12137dd29ee1SLuo bin 
12147dd29ee1SLuo bin 			for (i = 0; i < nic_io->max_vfs; i++) {
12157dd29ee1SLuo bin 				err = hinic_init_vf_infos(nic_io, i);
12167dd29ee1SLuo bin 				if (err)
12177dd29ee1SLuo bin 					goto err_init_vf_infos;
12187dd29ee1SLuo bin 			}
12197dd29ee1SLuo bin 
12207dd29ee1SLuo bin 			err = hinic_register_pf_mbox_cb(hwdev, HINIC_MOD_L2NIC,
12217dd29ee1SLuo bin 							nic_pf_mbox_handler);
12227dd29ee1SLuo bin 			if (err)
12237dd29ee1SLuo bin 				goto err_register_pf_mbox_cb;
12247dd29ee1SLuo bin 		}
12257dd29ee1SLuo bin 	}
12267dd29ee1SLuo bin 
12277dd29ee1SLuo bin 	return 0;
12287dd29ee1SLuo bin 
12297dd29ee1SLuo bin err_register_pf_mbox_cb:
12307dd29ee1SLuo bin err_init_vf_infos:
12317dd29ee1SLuo bin 	kfree(nic_io->vf_infos);
12327dd29ee1SLuo bin out_free_nic_io:
12337dd29ee1SLuo bin 	return err;
12347dd29ee1SLuo bin }
12357dd29ee1SLuo bin 
hinic_vf_func_free(struct hinic_hwdev * hwdev)12367dd29ee1SLuo bin void hinic_vf_func_free(struct hinic_hwdev *hwdev)
12377dd29ee1SLuo bin {
12387dd29ee1SLuo bin 	struct hinic_register_vf unregister = {0};
12397dd29ee1SLuo bin 	u16 out_size = sizeof(unregister);
1240ddc2118eSYueHaibing 	int err;
1241ddc2118eSYueHaibing 
12427dd29ee1SLuo bin 	if (HINIC_IS_VF(hwdev->hwif)) {
12437dd29ee1SLuo bin 		err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,
12447dd29ee1SLuo bin 				       HINIC_PORT_CMD_VF_UNREGISTER,
12457dd29ee1SLuo bin 				       &unregister, sizeof(unregister),
12467dd29ee1SLuo bin 				       &unregister, &out_size, 0);
12477dd29ee1SLuo bin 		if (err || !out_size || unregister.status)
12487dd29ee1SLuo bin 			dev_err(&hwdev->hwif->pdev->dev, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n",
12497dd29ee1SLuo bin 				err, unregister.status, out_size);
12507dd29ee1SLuo bin 	} else {
12517dd29ee1SLuo bin 		if (hwdev->func_to_io.vf_infos) {
12527dd29ee1SLuo bin 			hinic_unregister_pf_mbox_cb(hwdev, HINIC_MOD_L2NIC);
12537dd29ee1SLuo bin 			kfree(hwdev->func_to_io.vf_infos);
12547dd29ee1SLuo bin 		}
12557dd29ee1SLuo bin 	}
12567dd29ee1SLuo bin }
12577dd29ee1SLuo bin 
hinic_init_vf_hw(struct hinic_hwdev * hwdev,u16 start_vf_id,u16 end_vf_id)12587dd29ee1SLuo bin static int hinic_init_vf_hw(struct hinic_hwdev *hwdev, u16 start_vf_id,
12597dd29ee1SLuo bin 			    u16 end_vf_id)
12607dd29ee1SLuo bin {
12617dd29ee1SLuo bin 	u16 i, func_idx;
12627dd29ee1SLuo bin 	int err;
12637dd29ee1SLuo bin 
12647dd29ee1SLuo bin 	/* vf use 256K as default wq page size, and can't change it */
12657dd29ee1SLuo bin 	for (i = start_vf_id; i <= end_vf_id; i++) {
12667dd29ee1SLuo bin 		func_idx = hinic_glb_pf_vf_offset(hwdev->hwif) + i;
12677dd29ee1SLuo bin 		err = hinic_set_wq_page_size(hwdev, func_idx,
12687dd29ee1SLuo bin 					     HINIC_DEFAULT_WQ_PAGE_SIZE);
12697dd29ee1SLuo bin 		if (err)
12707dd29ee1SLuo bin 			return err;
12717dd29ee1SLuo bin 	}
12727dd29ee1SLuo bin 
12737dd29ee1SLuo bin 	return 0;
12747dd29ee1SLuo bin }
12757dd29ee1SLuo bin 
hinic_pci_sriov_disable(struct pci_dev * pdev)12767dd29ee1SLuo bin int hinic_pci_sriov_disable(struct pci_dev *pdev)
12777dd29ee1SLuo bin {
12787dd29ee1SLuo bin 	struct hinic_sriov_info *sriov_info;
12797dd29ee1SLuo bin 	u16 tmp_vfs;
12807dd29ee1SLuo bin 
12817dd29ee1SLuo bin 	sriov_info = hinic_get_sriov_info_by_pcidev(pdev);
12827dd29ee1SLuo bin 	/* if SR-IOV is already disabled then nothing will be done */
12837dd29ee1SLuo bin 	if (!sriov_info->sriov_enabled)
12847dd29ee1SLuo bin 		return 0;
12857dd29ee1SLuo bin 
12867dd29ee1SLuo bin 	set_bit(HINIC_SRIOV_DISABLE, &sriov_info->state);
12877dd29ee1SLuo bin 
12887dd29ee1SLuo bin 	/* If our VFs are assigned we cannot shut down SR-IOV
12897dd29ee1SLuo bin 	 * without causing issues, so just leave the hardware
12907dd29ee1SLuo bin 	 * available but disabled
12917dd29ee1SLuo bin 	 */
12927dd29ee1SLuo bin 	if (pci_vfs_assigned(sriov_info->pdev)) {
12937dd29ee1SLuo bin 		clear_bit(HINIC_SRIOV_DISABLE, &sriov_info->state);
129473f25f16SZhengchao Shao 		dev_warn(&pdev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n");
12957dd29ee1SLuo bin 		return -EPERM;
12967dd29ee1SLuo bin 	}
12977dd29ee1SLuo bin 	sriov_info->sriov_enabled = false;
12987dd29ee1SLuo bin 
12997dd29ee1SLuo bin 	/* disable iov and allow time for transactions to clear */
13007dd29ee1SLuo bin 	pci_disable_sriov(sriov_info->pdev);
13017dd29ee1SLuo bin 
13027dd29ee1SLuo bin 	tmp_vfs = (u16)sriov_info->num_vfs;
13037dd29ee1SLuo bin 	sriov_info->num_vfs = 0;
13047dd29ee1SLuo bin 	hinic_deinit_vf_hw(sriov_info, OS_VF_ID_TO_HW(0),
13057dd29ee1SLuo bin 			   OS_VF_ID_TO_HW(tmp_vfs - 1));
13067dd29ee1SLuo bin 
13077dd29ee1SLuo bin 	clear_bit(HINIC_SRIOV_DISABLE, &sriov_info->state);
13087dd29ee1SLuo bin 
13097dd29ee1SLuo bin 	return 0;
13107dd29ee1SLuo bin }
13117dd29ee1SLuo bin 
hinic_pci_sriov_enable(struct pci_dev * pdev,int num_vfs)13127dd29ee1SLuo bin static int hinic_pci_sriov_enable(struct pci_dev *pdev, int num_vfs)
13137dd29ee1SLuo bin {
13147dd29ee1SLuo bin 	struct hinic_sriov_info *sriov_info;
13157dd29ee1SLuo bin 	int err;
13167dd29ee1SLuo bin 
13177dd29ee1SLuo bin 	sriov_info = hinic_get_sriov_info_by_pcidev(pdev);
13187dd29ee1SLuo bin 
13197dd29ee1SLuo bin 	if (test_and_set_bit(HINIC_SRIOV_ENABLE, &sriov_info->state)) {
13207dd29ee1SLuo bin 		dev_err(&pdev->dev,
13217dd29ee1SLuo bin 			"SR-IOV enable in process, please wait, num_vfs %d\n",
13227dd29ee1SLuo bin 			num_vfs);
13237dd29ee1SLuo bin 		return -EPERM;
13247dd29ee1SLuo bin 	}
13257dd29ee1SLuo bin 
13267dd29ee1SLuo bin 	err = hinic_init_vf_hw(sriov_info->hwdev, OS_VF_ID_TO_HW(0),
13277dd29ee1SLuo bin 			       OS_VF_ID_TO_HW((u16)num_vfs - 1));
13287dd29ee1SLuo bin 	if (err) {
13297dd29ee1SLuo bin 		dev_err(&sriov_info->pdev->dev,
13307dd29ee1SLuo bin 			"Failed to init vf in hardware before enable sriov, error %d\n",
13317dd29ee1SLuo bin 			err);
13327dd29ee1SLuo bin 		clear_bit(HINIC_SRIOV_ENABLE, &sriov_info->state);
13337dd29ee1SLuo bin 		return err;
13347dd29ee1SLuo bin 	}
13357dd29ee1SLuo bin 
13367dd29ee1SLuo bin 	err = pci_enable_sriov(sriov_info->pdev, num_vfs);
13377dd29ee1SLuo bin 	if (err) {
13387dd29ee1SLuo bin 		dev_err(&pdev->dev,
13397dd29ee1SLuo bin 			"Failed to enable SR-IOV, error %d\n", err);
13407dd29ee1SLuo bin 		clear_bit(HINIC_SRIOV_ENABLE, &sriov_info->state);
13417dd29ee1SLuo bin 		return err;
13427dd29ee1SLuo bin 	}
13437dd29ee1SLuo bin 
13447dd29ee1SLuo bin 	sriov_info->sriov_enabled = true;
13457dd29ee1SLuo bin 	sriov_info->num_vfs = num_vfs;
13467dd29ee1SLuo bin 	clear_bit(HINIC_SRIOV_ENABLE, &sriov_info->state);
1347 
1348 	return num_vfs;
1349 }
1350 
hinic_pci_sriov_configure(struct pci_dev * dev,int num_vfs)1351 int hinic_pci_sriov_configure(struct pci_dev *dev, int num_vfs)
1352 {
1353 	struct hinic_sriov_info *sriov_info;
1354 
1355 	sriov_info = hinic_get_sriov_info_by_pcidev(dev);
1356 
1357 	if (test_bit(HINIC_FUNC_REMOVE, &sriov_info->state))
1358 		return -EBUSY;
1359 
1360 	if (!num_vfs)
1361 		return hinic_pci_sriov_disable(dev);
1362 	else
1363 		return hinic_pci_sriov_enable(dev, num_vfs);
1364 }
1365