brintos

brintos / linux-shallow public Read only

0
0
Text · 38.4 KiB · ee35708 Raw
1365 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/* Huawei HiNIC PCI Express Linux driver3 * Copyright(c) 2017 Huawei Technologies Co., Ltd4 */5 6#include <linux/pci.h>7#include <linux/if_vlan.h>8#include <linux/interrupt.h>9#include <linux/etherdevice.h>10#include <linux/netdevice.h>11#include <linux/module.h>12 13#include "hinic_hw_dev.h"14#include "hinic_dev.h"15#include "hinic_hw_mbox.h"16#include "hinic_hw_cmdq.h"17#include "hinic_port.h"18#include "hinic_sriov.h"19 20static unsigned char set_vf_link_state;21module_param(set_vf_link_state, byte, 0444);22MODULE_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.");23 24#define HINIC_VLAN_PRIORITY_SHIFT 1325#define HINIC_ADD_VLAN_IN_MAC 0x800026#define HINIC_TX_RATE_TABLE_FULL 1227#define HINIC_MAX_QOS 728 29static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,30			 u16 vlan_id, u16 func_id)31{32	struct hinic_port_mac_cmd mac_info = {0};33	u16 out_size = sizeof(mac_info);34	int err;35 36	mac_info.func_idx = func_id;37	mac_info.vlan_id = vlan_id;38	memcpy(mac_info.mac, mac_addr, ETH_ALEN);39 40	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,41				 sizeof(mac_info), &mac_info, &out_size);42	if (err || out_size != sizeof(mac_info) ||43	    (mac_info.status && mac_info.status != HINIC_MGMT_STATUS_EXIST)) {44		dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",45			err, mac_info.status, out_size);46		return -EIO;47	}48 49	return 0;50}51 52static void hinic_notify_vf_link_status(struct hinic_hwdev *hwdev, u16 vf_id,53					u8 link_status)54{55	struct vf_data_storage *vf_infos = hwdev->func_to_io.vf_infos;56	struct hinic_port_link_status link = {0};57	u16 out_size = sizeof(link);58	int err;59 60	if (vf_infos[HW_VF_ID_TO_OS(vf_id)].registered) {61		link.link = link_status;62		link.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;63		err = hinic_mbox_to_vf(hwdev, HINIC_MOD_L2NIC,64				       vf_id, HINIC_PORT_CMD_LINK_STATUS_REPORT,65				       &link, sizeof(link),66				       &link, &out_size, 0);67		if (err || !out_size || link.status)68			dev_err(&hwdev->hwif->pdev->dev,69				"Send link change event to VF %d failed, err: %d, status: 0x%x, out_size: 0x%x\n",70				HW_VF_ID_TO_OS(vf_id), err,71				link.status, out_size);72	}73}74 75/* send link change event mbox msg to active vfs under the pf */76void hinic_notify_all_vfs_link_changed(struct hinic_hwdev *hwdev,77				       u8 link_status)78{79	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;80	u16 i;81 82	nic_io->link_status = link_status;83	for (i = 1; i <= nic_io->max_vfs; i++) {84		if (!nic_io->vf_infos[HW_VF_ID_TO_OS(i)].link_forced)85			hinic_notify_vf_link_status(hwdev, i,  link_status);86	}87}88 89static u16 hinic_vf_info_vlanprio(struct hinic_hwdev *hwdev, int vf_id)90{91	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;92	u16 pf_vlan, vlanprio;93	u8 pf_qos;94 95	pf_vlan = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan;96	pf_qos = nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos;97	vlanprio = pf_vlan | pf_qos << HINIC_VLAN_PRIORITY_SHIFT;98 99	return vlanprio;100}101 102static int hinic_set_vf_vlan(struct hinic_hwdev *hwdev, bool add, u16 vid,103			     u8 qos, int vf_id)104{105	struct hinic_vf_vlan_config vf_vlan = {0};106	u16 out_size = sizeof(vf_vlan);107	int err;108	u8 cmd;109 110	/* VLAN 0 is a special case, don't allow it to be removed */111	if (!vid && !add)112		return 0;113 114	vf_vlan.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;115	vf_vlan.vlan_id = vid;116	vf_vlan.qos = qos;117 118	if (add)119		cmd = HINIC_PORT_CMD_SET_VF_VLAN;120	else121		cmd = HINIC_PORT_CMD_CLR_VF_VLAN;122 123	err = hinic_port_msg_cmd(hwdev, cmd, &vf_vlan,124				 sizeof(vf_vlan), &vf_vlan, &out_size);125	if (err || !out_size || vf_vlan.status) {126		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d vlan, err: %d, status: 0x%x, out size: 0x%x\n",127			HW_VF_ID_TO_OS(vf_id), err, vf_vlan.status, out_size);128		return -EFAULT;129	}130 131	return 0;132}133 134static int hinic_set_vf_tx_rate_max_min(struct hinic_hwdev *hwdev, u16 vf_id,135					u32 max_rate, u32 min_rate)136{137	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;138	struct hinic_tx_rate_cfg_max_min rate_cfg = {0};139	u16 out_size = sizeof(rate_cfg);140	int err;141 142	rate_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;143	rate_cfg.max_rate = max_rate;144	rate_cfg.min_rate = min_rate;145	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE,146				 &rate_cfg, sizeof(rate_cfg), &rate_cfg,147				 &out_size);148	if ((rate_cfg.status != HINIC_MGMT_CMD_UNSUPPORTED &&149	     rate_cfg.status) || err || !out_size) {150		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",151			HW_VF_ID_TO_OS(vf_id), max_rate, min_rate, err,152			rate_cfg.status, out_size);153		return -EIO;154	}155 156	if (!rate_cfg.status) {157		nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate;158		nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = min_rate;159	}160 161	return rate_cfg.status;162}163 164static int hinic_set_vf_rate_limit(struct hinic_hwdev *hwdev, u16 vf_id,165				   u32 tx_rate)166{167	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;168	struct hinic_tx_rate_cfg rate_cfg = {0};169	u16 out_size = sizeof(rate_cfg);170	int err;171 172	rate_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;173	rate_cfg.tx_rate = tx_rate;174	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VF_RATE,175				 &rate_cfg, sizeof(rate_cfg), &rate_cfg,176				 &out_size);177	if (err || !out_size || rate_cfg.status) {178		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) rate(%d), err: %d, status: 0x%x, out size: 0x%x\n",179			HW_VF_ID_TO_OS(vf_id), tx_rate, err, rate_cfg.status,180			out_size);181		if (rate_cfg.status)182			return rate_cfg.status;183 184		return -EIO;185	}186 187	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = tx_rate;188	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = 0;189 190	return 0;191}192 193static int hinic_set_vf_tx_rate(struct hinic_hwdev *hwdev, u16 vf_id,194				u32 max_rate, u32 min_rate)195{196	int err;197 198	err = hinic_set_vf_tx_rate_max_min(hwdev, vf_id, max_rate, min_rate);199	if (err != HINIC_MGMT_CMD_UNSUPPORTED)200		return err;201 202	if (min_rate) {203		dev_err(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate\n");204		return -EOPNOTSUPP;205	}206 207	dev_info(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate, force min_tx_rate = max_tx_rate\n");208 209	return hinic_set_vf_rate_limit(hwdev, vf_id, max_rate);210}211 212static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id)213{214	struct vf_data_storage *vf_info;215	u16 func_id, vlan_id;216	int err = 0;217 218	vf_info = hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);219	if (vf_info->pf_set_mac) {220		func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;221 222		vlan_id = 0;223 224		err = hinic_set_mac(hwdev, vf_info->vf_mac_addr, vlan_id,225				    func_id);226		if (err) {227			dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set VF %d MAC\n",228				HW_VF_ID_TO_OS(vf_id));229			return err;230		}231	}232 233	if (hinic_vf_info_vlanprio(hwdev, vf_id)) {234		err = hinic_set_vf_vlan(hwdev, true, vf_info->pf_vlan,235					vf_info->pf_qos, vf_id);236		if (err) {237			dev_err(&hwdev->hwif->pdev->dev, "Failed to add VF %d VLAN_QOS\n",238				HW_VF_ID_TO_OS(vf_id));239			return err;240		}241	}242 243	if (vf_info->max_rate) {244		err = hinic_set_vf_tx_rate(hwdev, vf_id, vf_info->max_rate,245					   vf_info->min_rate);246		if (err) {247			dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d max rate: %d, min rate: %d\n",248				HW_VF_ID_TO_OS(vf_id), vf_info->max_rate,249				vf_info->min_rate);250			return err;251		}252	}253 254	return 0;255}256 257static int hinic_register_vf_msg_handler(void *hwdev, u16 vf_id,258					 void *buf_in, u16 in_size,259					 void *buf_out, u16 *out_size)260{261	struct hinic_register_vf *register_info = buf_out;262	struct hinic_hwdev *hw_dev = hwdev;263	struct hinic_func_to_io *nic_io;264	int err;265 266	nic_io = &hw_dev->func_to_io;267	if (vf_id > nic_io->max_vfs) {268		dev_err(&hw_dev->hwif->pdev->dev, "Register VF id %d exceed limit[0-%d]\n",269			HW_VF_ID_TO_OS(vf_id), HW_VF_ID_TO_OS(nic_io->max_vfs));270		register_info->status = EFAULT;271		return -EFAULT;272	}273 274	*out_size = sizeof(*register_info);275	err = hinic_init_vf_config(hw_dev, vf_id);276	if (err) {277		register_info->status = EFAULT;278		return err;279	}280 281	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = true;282 283	return 0;284}285 286static int hinic_unregister_vf_msg_handler(void *hwdev, u16 vf_id,287					   void *buf_in, u16 in_size,288					   void *buf_out, u16 *out_size)289{290	struct hinic_hwdev *hw_dev = hwdev;291	struct hinic_func_to_io *nic_io;292 293	nic_io = &hw_dev->func_to_io;294	*out_size = 0;295	if (vf_id > nic_io->max_vfs)296		return 0;297 298	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].registered = false;299 300	return 0;301}302 303static int hinic_change_vf_mtu_msg_handler(void *hwdev, u16 vf_id,304					   void *buf_in, u16 in_size,305					   void *buf_out, u16 *out_size)306{307	struct hinic_hwdev *hw_dev = hwdev;308	int err;309 310	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_CHANGE_MTU, buf_in,311				 in_size, buf_out, out_size);312	if (err) {313		dev_err(&hw_dev->hwif->pdev->dev, "Failed to set VF %u mtu\n",314			vf_id);315		return err;316	}317 318	return 0;319}320 321static int hinic_get_vf_mac_msg_handler(void *hwdev, u16 vf_id,322					void *buf_in, u16 in_size,323					void *buf_out, u16 *out_size)324{325	struct hinic_port_mac_cmd *mac_info = buf_out;326	struct hinic_hwdev *dev = hwdev;327	struct hinic_func_to_io *nic_io;328	struct vf_data_storage *vf_info;329 330	nic_io = &dev->func_to_io;331	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);332 333	memcpy(mac_info->mac, vf_info->vf_mac_addr, ETH_ALEN);334	mac_info->status = 0;335	*out_size = sizeof(*mac_info);336 337	return 0;338}339 340static int hinic_set_vf_mac_msg_handler(void *hwdev, u16 vf_id,341					void *buf_in, u16 in_size,342					void *buf_out, u16 *out_size)343{344	struct hinic_port_mac_cmd *mac_out = buf_out;345	struct hinic_port_mac_cmd *mac_in = buf_in;346	struct hinic_hwdev *hw_dev = hwdev;347	struct hinic_func_to_io *nic_io;348	struct vf_data_storage *vf_info;349	int err;350 351	nic_io =  &hw_dev->func_to_io;352	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);353	if (vf_info->pf_set_mac && !(vf_info->trust) &&354	    is_valid_ether_addr(mac_in->mac)) {355		dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF %d MAC address\n",356			 HW_VF_ID_TO_OS(vf_id));357		mac_out->status = HINIC_PF_SET_VF_ALREADY;358		*out_size = sizeof(*mac_out);359		return 0;360	}361 362	err = hinic_port_msg_cmd(hw_dev, HINIC_PORT_CMD_SET_MAC, buf_in,363				 in_size, buf_out, out_size);364	if ((err &&  err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) || !(*out_size)) {365		dev_err(&hw_dev->hwif->pdev->dev,366			"Failed to set VF %d MAC address, err: %d, status: 0x%x, out size: 0x%x\n",367			HW_VF_ID_TO_OS(vf_id), err, mac_out->status, *out_size);368		return -EFAULT;369	}370 371	return err;372}373 374static int hinic_del_vf_mac_msg_handler(void *hwdev, u16 vf_id,375					void *buf_in, u16 in_size,376					void *buf_out, u16 *out_size)377{378	struct hinic_port_mac_cmd *mac_out = buf_out;379	struct hinic_port_mac_cmd *mac_in = buf_in;380	struct hinic_hwdev *hw_dev = hwdev;381	struct hinic_func_to_io *nic_io;382	struct vf_data_storage *vf_info;383	int err;384 385	nic_io = &hw_dev->func_to_io;386	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);387	if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&388	    !memcmp(vf_info->vf_mac_addr, mac_in->mac, ETH_ALEN)) {389		dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF mac.\n");390		mac_out->status = HINIC_PF_SET_VF_ALREADY;391		*out_size = sizeof(*mac_out);392		return 0;393	}394 395	err = hinic_port_msg_cmd(hw_dev, HINIC_PORT_CMD_DEL_MAC, buf_in,396				 in_size, buf_out, out_size);397	if ((err && err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) || !(*out_size)) {398		dev_err(&hw_dev->hwif->pdev->dev, "Failed to delete VF %d MAC, err: %d, status: 0x%x, out size: 0x%x\n",399			HW_VF_ID_TO_OS(vf_id), err, mac_out->status, *out_size);400		return -EFAULT;401	}402 403	return err;404}405 406static int hinic_get_vf_link_status_msg_handler(void *hwdev, u16 vf_id,407						void *buf_in, u16 in_size,408						void *buf_out, u16 *out_size)409{410	struct hinic_port_link_cmd *get_link = buf_out;411	struct hinic_hwdev *hw_dev = hwdev;412	struct vf_data_storage *vf_infos;413	struct hinic_func_to_io *nic_io;414	bool link_forced, link_up;415 416	nic_io = &hw_dev->func_to_io;417	vf_infos = nic_io->vf_infos;418	link_forced = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced;419	link_up = vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up;420 421	if (link_forced)422		get_link->state = link_up ?423			HINIC_LINK_STATE_UP : HINIC_LINK_STATE_DOWN;424	else425		get_link->state = nic_io->link_status;426 427	get_link->status = 0;428	*out_size = sizeof(*get_link);429 430	return 0;431}432 433static bool check_func_table(struct hinic_hwdev *hwdev, u16 func_idx,434			     void *buf_in, u16 in_size)435{436	struct hinic_cmd_fw_ctxt *function_table = buf_in;437 438	if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size) ||439	    !function_table->rx_buf_sz)440		return false;441 442	return true;443}444 445static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = {446	{HINIC_PORT_CMD_VF_REGISTER, hinic_register_vf_msg_handler},447	{HINIC_PORT_CMD_VF_UNREGISTER, hinic_unregister_vf_msg_handler},448	{HINIC_PORT_CMD_CHANGE_MTU, hinic_change_vf_mtu_msg_handler},449	{HINIC_PORT_CMD_GET_MAC, hinic_get_vf_mac_msg_handler},450	{HINIC_PORT_CMD_SET_MAC, hinic_set_vf_mac_msg_handler},451	{HINIC_PORT_CMD_DEL_MAC, hinic_del_vf_mac_msg_handler},452	{HINIC_PORT_CMD_GET_LINK_STATE, hinic_get_vf_link_status_msg_handler},453};454 455static struct vf_cmd_check_handle nic_cmd_support_vf[] = {456	{HINIC_PORT_CMD_VF_REGISTER, NULL},457	{HINIC_PORT_CMD_VF_UNREGISTER, NULL},458	{HINIC_PORT_CMD_CHANGE_MTU, hinic_mbox_check_func_id_8B},459	{HINIC_PORT_CMD_ADD_VLAN, hinic_mbox_check_func_id_8B},460	{HINIC_PORT_CMD_DEL_VLAN, hinic_mbox_check_func_id_8B},461	{HINIC_PORT_CMD_SET_MAC, hinic_mbox_check_func_id_8B},462	{HINIC_PORT_CMD_GET_MAC, hinic_mbox_check_func_id_8B},463	{HINIC_PORT_CMD_DEL_MAC, hinic_mbox_check_func_id_8B},464	{HINIC_PORT_CMD_SET_RX_MODE, hinic_mbox_check_func_id_8B},465	{HINIC_PORT_CMD_GET_PAUSE_INFO, hinic_mbox_check_func_id_8B},466	{HINIC_PORT_CMD_GET_LINK_STATE, hinic_mbox_check_func_id_8B},467	{HINIC_PORT_CMD_SET_LRO, hinic_mbox_check_func_id_8B},468	{HINIC_PORT_CMD_SET_RX_CSUM, hinic_mbox_check_func_id_8B},469	{HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD, hinic_mbox_check_func_id_8B},470	{HINIC_PORT_CMD_GET_VPORT_STAT, hinic_mbox_check_func_id_8B},471	{HINIC_PORT_CMD_CLEAN_VPORT_STAT, hinic_mbox_check_func_id_8B},472	{HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,473	 hinic_mbox_check_func_id_8B},474	{HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},475	{HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},476	{HINIC_PORT_CMD_SET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},477	{HINIC_PORT_CMD_GET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},478	{HINIC_PORT_CMD_GET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},479	{HINIC_PORT_CMD_SET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},480	{HINIC_PORT_CMD_RSS_TEMP_MGR, hinic_mbox_check_func_id_8B},481	{HINIC_PORT_CMD_RSS_CFG, hinic_mbox_check_func_id_8B},482	{HINIC_PORT_CMD_FWCTXT_INIT, check_func_table},483	{HINIC_PORT_CMD_GET_MGMT_VERSION, NULL},484	{HINIC_PORT_CMD_SET_FUNC_STATE, hinic_mbox_check_func_id_8B},485	{HINIC_PORT_CMD_GET_GLOBAL_QPN, hinic_mbox_check_func_id_8B},486	{HINIC_PORT_CMD_SET_TSO, hinic_mbox_check_func_id_8B},487	{HINIC_PORT_CMD_SET_RQ_IQ_MAP, hinic_mbox_check_func_id_8B},488	{HINIC_PORT_CMD_LINK_STATUS_REPORT, hinic_mbox_check_func_id_8B},489	{HINIC_PORT_CMD_UPDATE_MAC, hinic_mbox_check_func_id_8B},490	{HINIC_PORT_CMD_GET_CAP, hinic_mbox_check_func_id_8B},491	{HINIC_PORT_CMD_GET_LINK_MODE, hinic_mbox_check_func_id_8B},492	{HINIC_PORT_CMD_GET_VF_COS, NULL},493	{HINIC_PORT_CMD_SET_VHD_CFG, hinic_mbox_check_func_id_8B},494	{HINIC_PORT_CMD_SET_VLAN_FILTER, hinic_mbox_check_func_id_8B},495	{HINIC_PORT_CMD_Q_FILTER, hinic_mbox_check_func_id_8B},496	{HINIC_PORT_CMD_TCAM_FILTER, NULL},497	{HINIC_PORT_CMD_UP_TC_ADD_FLOW, NULL},498	{HINIC_PORT_CMD_UP_TC_DEL_FLOW, NULL},499	{HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, hinic_mbox_check_func_id_8B},500	{HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, hinic_mbox_check_func_id_8B},501	{HINIC_PORT_CMD_UP_TC_ENABLE, hinic_mbox_check_func_id_8B},502	{HINIC_PORT_CMD_CABLE_PLUG_EVENT, NULL},503	{HINIC_PORT_CMD_LINK_ERR_EVENT, NULL},504	{HINIC_PORT_CMD_SET_PORT_STATE, hinic_mbox_check_func_id_8B},505	{HINIC_PORT_CMD_SET_ETS, NULL},506	{HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE, NULL},507	{HINIC_PORT_CMD_RESET_LINK_CFG, hinic_mbox_check_func_id_8B},508	{HINIC_PORT_CMD_SET_LINK_FOLLOW, NULL},509	{HINIC_PORT_CMD_CLEAR_QP_RES, NULL},510};511 512#define CHECK_IPSU_15BIT	0X8000513 514static515struct hinic_sriov_info *hinic_get_sriov_info_by_pcidev(struct pci_dev *pdev)516{517	struct net_device *netdev = pci_get_drvdata(pdev);518	struct hinic_dev *nic_dev = netdev_priv(netdev);519 520	return &nic_dev->sriov_info;521}522 523static int hinic_check_mac_info(u8 status, u16 vlan_id)524{525	if ((status && status != HINIC_MGMT_STATUS_EXIST) ||526	    (vlan_id & CHECK_IPSU_15BIT &&527	     status == HINIC_MGMT_STATUS_EXIST))528		return -EINVAL;529 530	return 0;531}532 533#define HINIC_VLAN_ID_MASK	0x7FFF534 535static int hinic_update_mac(struct hinic_hwdev *hwdev, u8 *old_mac,536			    u8 *new_mac, u16 vlan_id, u16 func_id)537{538	struct hinic_port_mac_update mac_info = {0};539	u16 out_size = sizeof(mac_info);540	int err;541 542	if (!hwdev || !old_mac || !new_mac)543		return -EINVAL;544 545	if ((vlan_id & HINIC_VLAN_ID_MASK) >= VLAN_N_VID) {546		dev_err(&hwdev->hwif->pdev->dev, "Invalid VLAN number: %d\n",547			(vlan_id & HINIC_VLAN_ID_MASK));548		return -EINVAL;549	}550 551	mac_info.func_id = func_id;552	mac_info.vlan_id = vlan_id;553	memcpy(mac_info.old_mac, old_mac, ETH_ALEN);554	memcpy(mac_info.new_mac, new_mac, ETH_ALEN);555 556	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_UPDATE_MAC, &mac_info,557				 sizeof(mac_info), &mac_info, &out_size);558 559	if (err || !out_size ||560	    hinic_check_mac_info(mac_info.status, mac_info.vlan_id)) {561		dev_err(&hwdev->hwif->pdev->dev,562			"Failed to update MAC, err: %d, status: 0x%x, out size: 0x%x\n",563			err, mac_info.status, out_size);564		return -EINVAL;565	}566 567	if (mac_info.status == HINIC_MGMT_STATUS_EXIST)568		dev_warn(&hwdev->hwif->pdev->dev, "MAC is repeated. Ignore update operation\n");569 570	return 0;571}572 573static void hinic_get_vf_config(struct hinic_hwdev *hwdev, u16 vf_id,574				struct ifla_vf_info *ivi)575{576	struct vf_data_storage *vfinfo;577 578	vfinfo = hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);579 580	ivi->vf = HW_VF_ID_TO_OS(vf_id);581	memcpy(ivi->mac, vfinfo->vf_mac_addr, ETH_ALEN);582	ivi->vlan = vfinfo->pf_vlan;583	ivi->qos = vfinfo->pf_qos;584	ivi->spoofchk = vfinfo->spoofchk;585	ivi->trusted = vfinfo->trust;586	ivi->max_tx_rate = vfinfo->max_rate;587	ivi->min_tx_rate = vfinfo->min_rate;588 589	if (!vfinfo->link_forced)590		ivi->linkstate = IFLA_VF_LINK_STATE_AUTO;591	else if (vfinfo->link_up)592		ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE;593	else594		ivi->linkstate = IFLA_VF_LINK_STATE_DISABLE;595}596 597int hinic_ndo_get_vf_config(struct net_device *netdev,598			    int vf, struct ifla_vf_info *ivi)599{600	struct hinic_dev *nic_dev = netdev_priv(netdev);601	struct hinic_sriov_info *sriov_info;602 603	sriov_info = &nic_dev->sriov_info;604	if (vf >= sriov_info->num_vfs)605		return -EINVAL;606 607	hinic_get_vf_config(sriov_info->hwdev, OS_VF_ID_TO_HW(vf), ivi);608 609	return 0;610}611 612static int hinic_set_vf_mac(struct hinic_hwdev *hwdev, int vf,613			    unsigned char *mac_addr)614{615	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;616	struct vf_data_storage *vf_info;617	u16 func_id;618	int err;619 620	vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf);621 622	/* duplicate request, so just return success */623	if (vf_info->pf_set_mac &&624	    !memcmp(vf_info->vf_mac_addr, mac_addr, ETH_ALEN))625		return 0;626 627	vf_info->pf_set_mac = true;628 629	func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf;630	err = hinic_update_mac(hwdev, vf_info->vf_mac_addr,631			       mac_addr, 0, func_id);632	if (err) {633		vf_info->pf_set_mac = false;634		return err;635	}636 637	memcpy(vf_info->vf_mac_addr, mac_addr, ETH_ALEN);638 639	return 0;640}641 642int hinic_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)643{644	struct hinic_dev *nic_dev = netdev_priv(netdev);645	struct hinic_sriov_info *sriov_info;646	int err;647 648	sriov_info = &nic_dev->sriov_info;649	if (!is_valid_ether_addr(mac) || vf >= sriov_info->num_vfs)650		return -EINVAL;651 652	err = hinic_set_vf_mac(sriov_info->hwdev, OS_VF_ID_TO_HW(vf), mac);653	if (err)654		return err;655 656	netif_info(nic_dev, drv, netdev, "Setting MAC %pM on VF %d\n", mac, vf);657	netif_info(nic_dev, drv, netdev, "Reload the VF driver to make this change effective.");658 659	return 0;660}661 662static int hinic_add_vf_vlan(struct hinic_hwdev *hwdev, int vf_id,663			     u16 vlan, u8 qos)664{665	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;666	int err;667 668	err = hinic_set_vf_vlan(hwdev, true, vlan, qos, vf_id);669	if (err)670		return err;671 672	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = vlan;673	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = qos;674 675	dev_info(&hwdev->hwif->pdev->dev, "Setting VLAN %d, QOS 0x%x on VF %d\n",676		 vlan, qos, HW_VF_ID_TO_OS(vf_id));677	return 0;678}679 680static int hinic_kill_vf_vlan(struct hinic_hwdev *hwdev, int vf_id)681{682	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;683	int err;684 685	err = hinic_set_vf_vlan(hwdev, false,686				nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,687				nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos,688				vf_id);689	if (err)690		return err;691 692	dev_info(&hwdev->hwif->pdev->dev, "Remove VLAN %d on VF %d\n",693		 nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan,694		 HW_VF_ID_TO_OS(vf_id));695 696	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_vlan = 0;697	nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].pf_qos = 0;698 699	return 0;700}701 702static int hinic_update_mac_vlan(struct hinic_dev *nic_dev, u16 old_vlan,703				 u16 new_vlan, int vf_id)704{705	struct vf_data_storage *vf_info;706	u16 vlan_id;707	int err;708 709	if (!nic_dev || old_vlan >= VLAN_N_VID || new_vlan >= VLAN_N_VID)710		return -EINVAL;711 712	vf_info = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);713	if (!vf_info->pf_set_mac)714		return 0;715 716	vlan_id = old_vlan;717	if (vlan_id)718		vlan_id |= HINIC_ADD_VLAN_IN_MAC;719 720	err = hinic_port_del_mac(nic_dev, vf_info->vf_mac_addr, vlan_id);721	if (err) {722		dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to delete VF %d MAC %pM vlan %d\n",723			HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, old_vlan);724		return err;725	}726 727	vlan_id = new_vlan;728	if (vlan_id)729		vlan_id |= HINIC_ADD_VLAN_IN_MAC;730 731	err = hinic_port_add_mac(nic_dev, vf_info->vf_mac_addr, vlan_id);732	if (err) {733		dev_err(&nic_dev->hwdev->hwif->pdev->dev, "Failed to add VF %d MAC %pM vlan %d\n",734			HW_VF_ID_TO_OS(vf_id), vf_info->vf_mac_addr, new_vlan);735		goto out;736	}737 738	return 0;739 740out:741	vlan_id = old_vlan;742	if (vlan_id)743		vlan_id |= HINIC_ADD_VLAN_IN_MAC;744	hinic_port_add_mac(nic_dev, vf_info->vf_mac_addr, vlan_id);745 746	return err;747}748 749static int set_hw_vf_vlan(struct hinic_dev *nic_dev,750			  u16 cur_vlanprio, int vf, u16 vlan, u8 qos)751{752	u16 old_vlan = cur_vlanprio & VLAN_VID_MASK;753	int err = 0;754 755	if (vlan || qos) {756		if (cur_vlanprio) {757			err = hinic_kill_vf_vlan(nic_dev->hwdev,758						 OS_VF_ID_TO_HW(vf));759			if (err) {760				dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to delete vf %d old vlan %d\n",761					vf, old_vlan);762				goto out;763			}764		}765		err = hinic_add_vf_vlan(nic_dev->hwdev,766					OS_VF_ID_TO_HW(vf), vlan, qos);767		if (err) {768			dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to add vf %d new vlan %d\n",769				vf, vlan);770			goto out;771		}772	} else {773		err = hinic_kill_vf_vlan(nic_dev->hwdev, OS_VF_ID_TO_HW(vf));774		if (err) {775			dev_err(&nic_dev->sriov_info.pdev->dev, "Failed to delete vf %d vlan %d\n",776				vf, old_vlan);777			goto out;778		}779	}780 781	err = hinic_update_mac_vlan(nic_dev, old_vlan, vlan,782				    OS_VF_ID_TO_HW(vf));783 784out:785	return err;786}787 788int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,789			  __be16 vlan_proto)790{791	struct hinic_dev *nic_dev = netdev_priv(netdev);792	struct hinic_sriov_info *sriov_info;793	u16 vlanprio, cur_vlanprio;794 795	sriov_info = &nic_dev->sriov_info;796	if (vf >= sriov_info->num_vfs || vlan >= VLAN_N_VID || qos > HINIC_MAX_QOS)797		return -EINVAL;798	if (vlan_proto != htons(ETH_P_8021Q))799		return -EPROTONOSUPPORT;800	vlanprio = vlan | qos << HINIC_VLAN_PRIORITY_SHIFT;801	cur_vlanprio = hinic_vf_info_vlanprio(nic_dev->hwdev,802					      OS_VF_ID_TO_HW(vf));803	/* duplicate request, so just return success */804	if (vlanprio == cur_vlanprio)805		return 0;806 807	return set_hw_vf_vlan(nic_dev, cur_vlanprio, vf, vlan, qos);808}809 810static int hinic_set_vf_trust(struct hinic_hwdev *hwdev, u16 vf_id,811			      bool trust)812{813	struct vf_data_storage *vf_infos;814	struct hinic_func_to_io *nic_io;815 816	if (!hwdev)817		return -EINVAL;818 819	nic_io = &hwdev->func_to_io;820	vf_infos = nic_io->vf_infos;821	vf_infos[vf_id].trust = trust;822 823	return 0;824}825 826int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)827{828	struct hinic_dev *adapter = netdev_priv(netdev);829	struct hinic_sriov_info *sriov_info;830	struct hinic_func_to_io *nic_io;831	bool cur_trust;832	int err;833 834	sriov_info = &adapter->sriov_info;835	nic_io = &adapter->hwdev->func_to_io;836 837	if (vf >= sriov_info->num_vfs)838		return -EINVAL;839 840	cur_trust = nic_io->vf_infos[vf].trust;841	/* same request, so just return success */842	if (setting == cur_trust)843		return 0;844 845	err = hinic_set_vf_trust(adapter->hwdev, vf, setting);846	if (!err)847		dev_info(&sriov_info->pdev->dev, "Set VF %d trusted %s succeed\n",848			 vf, setting ? "on" : "off");849	else850		dev_err(&sriov_info->pdev->dev, "Failed set VF %d trusted %s\n",851			vf, setting ? "on" : "off");852 853	return err;854}855 856int hinic_ndo_set_vf_bw(struct net_device *netdev,857			int vf, int min_tx_rate, int max_tx_rate)858{859	static const u32 speeds[] = {860		SPEED_10, SPEED_100, SPEED_1000, SPEED_10000,861		SPEED_25000, SPEED_40000, SPEED_100000862	};863	struct hinic_dev *nic_dev = netdev_priv(netdev);864	struct hinic_port_cap port_cap = { 0 };865	enum hinic_port_link_state link_state;866	int err;867 868	if (vf >= nic_dev->sriov_info.num_vfs) {869		netif_err(nic_dev, drv, netdev, "VF number must be less than %d\n",870			  nic_dev->sriov_info.num_vfs);871		return -EINVAL;872	}873 874	err = hinic_port_link_state(nic_dev, &link_state);875	if (err) {876		netif_err(nic_dev, drv, netdev,877			  "Get link status failed when setting vf tx rate\n");878		return -EIO;879	}880 881	if (link_state == HINIC_LINK_STATE_DOWN) {882		netif_err(nic_dev, drv, netdev,883			  "Link status must be up when setting vf tx rate\n");884		return -EPERM;885	}886 887	err = hinic_port_get_cap(nic_dev, &port_cap);888	if (err || port_cap.speed > LINK_SPEED_100GB)889		return -EIO;890 891	/* rate limit cannot be less than 0 and greater than link speed */892	if (max_tx_rate < 0 || max_tx_rate > speeds[port_cap.speed]) {893		netif_err(nic_dev, drv, netdev, "Max tx rate must be in [0 - %d]\n",894			  speeds[port_cap.speed]);895		return -EINVAL;896	}897 898	err = hinic_set_vf_tx_rate(nic_dev->hwdev, OS_VF_ID_TO_HW(vf),899				   max_tx_rate, min_tx_rate);900	if (err) {901		netif_err(nic_dev, drv, netdev,902			  "Unable to set VF %d max rate %d min rate %d%s\n",903			  vf, max_tx_rate, min_tx_rate,904			  err == HINIC_TX_RATE_TABLE_FULL ?905			  ", tx rate profile is full" : "");906		return -EIO;907	}908 909	netif_info(nic_dev, drv, netdev,910		   "Set VF %d max tx rate %d min tx rate %d successfully\n",911		   vf, max_tx_rate, min_tx_rate);912 913	return 0;914}915 916static int hinic_set_vf_spoofchk(struct hinic_hwdev *hwdev, u16 vf_id,917				 bool spoofchk)918{919	struct hinic_spoofchk_set spoofchk_cfg = {0};920	struct vf_data_storage *vf_infos = NULL;921	u16 out_size = sizeof(spoofchk_cfg);922	int err;923 924	if (!hwdev)925		return -EINVAL;926 927	vf_infos = hwdev->func_to_io.vf_infos;928 929	spoofchk_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;930	spoofchk_cfg.state = spoofchk ? 1 : 0;931	err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ENABLE_SPOOFCHK,932				 &spoofchk_cfg, sizeof(spoofchk_cfg),933				 &spoofchk_cfg, &out_size);934	if (spoofchk_cfg.status == HINIC_MGMT_CMD_UNSUPPORTED) {935		err = HINIC_MGMT_CMD_UNSUPPORTED;936	} else if (err || !out_size || spoofchk_cfg.status) {937		dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) spoofchk, err: %d, status: 0x%x, out size: 0x%x\n",938			HW_VF_ID_TO_OS(vf_id), err, spoofchk_cfg.status,939			out_size);940		err = -EIO;941	}942 943	vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk = spoofchk;944 945	return err;946}947 948int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)949{950	struct hinic_dev *nic_dev = netdev_priv(netdev);951	struct hinic_sriov_info *sriov_info;952	bool cur_spoofchk;953	int err;954 955	sriov_info = &nic_dev->sriov_info;956	if (vf >= sriov_info->num_vfs)957		return -EINVAL;958 959	cur_spoofchk = nic_dev->hwdev->func_to_io.vf_infos[vf].spoofchk;960 961	/* same request, so just return success */962	if (setting == cur_spoofchk)963		return 0;964 965	err = hinic_set_vf_spoofchk(sriov_info->hwdev,966				    OS_VF_ID_TO_HW(vf), setting);967	if (!err) {968		netif_info(nic_dev, drv, netdev, "Set VF %d spoofchk %s successfully\n",969			   vf, setting ? "on" : "off");970	} else if (err == HINIC_MGMT_CMD_UNSUPPORTED) {971		netif_err(nic_dev, drv, netdev,972			  "Current firmware doesn't support to set vf spoofchk, need to upgrade latest firmware version\n");973		err = -EOPNOTSUPP;974	}975 976	return err;977}978 979static int hinic_set_vf_link_state(struct hinic_hwdev *hwdev, u16 vf_id,980				   int link)981{982	struct hinic_func_to_io *nic_io = &hwdev->func_to_io;983	struct vf_data_storage *vf_infos = nic_io->vf_infos;984	u8 link_status = 0;985 986	switch (link) {987	case HINIC_IFLA_VF_LINK_STATE_AUTO:988		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false;989		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = nic_io->link_status ?990			true : false;991		link_status = nic_io->link_status;992		break;993	case HINIC_IFLA_VF_LINK_STATE_ENABLE:994		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true;995		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = true;996		link_status = HINIC_LINK_UP;997		break;998	case HINIC_IFLA_VF_LINK_STATE_DISABLE:999		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true;1000		vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = false;1001		link_status = HINIC_LINK_DOWN;1002		break;1003	default:1004		return -EINVAL;1005	}1006 1007	/* Notify the VF of its new link state */1008	hinic_notify_vf_link_status(hwdev, vf_id, link_status);1009 1010	return 0;1011}1012 1013int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)1014{1015	struct hinic_dev *nic_dev = netdev_priv(netdev);1016	struct hinic_sriov_info *sriov_info;1017 1018	sriov_info = &nic_dev->sriov_info;1019 1020	if (vf_id >= sriov_info->num_vfs) {1021		netif_err(nic_dev, drv, netdev,1022			  "Invalid VF Identifier %d\n", vf_id);1023		return -EINVAL;1024	}1025 1026	return hinic_set_vf_link_state(sriov_info->hwdev,1027				      OS_VF_ID_TO_HW(vf_id), link);1028}1029 1030/* pf receive message from vf */1031static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,1032			       u16 in_size, void *buf_out, u16 *out_size)1033{1034	u8 size = ARRAY_SIZE(nic_cmd_support_vf);1035	struct vf_cmd_msg_handle *vf_msg_handle;1036	struct hinic_hwdev *dev = hwdev;1037	struct hinic_func_to_io *nic_io;1038	struct hinic_pfhwdev *pfhwdev;1039	int err = 0;1040	u32 i;1041 1042	if (!hwdev)1043		return -EINVAL;1044 1045	if (!hinic_mbox_check_cmd_valid(hwdev, nic_cmd_support_vf, vf_id, cmd,1046					buf_in, in_size, size)) {1047		dev_err(&dev->hwif->pdev->dev,1048			"PF Receive VF nic cmd: 0x%x, mbox len: 0x%x is invalid\n",1049			cmd, in_size);1050		return HINIC_MBOX_VF_CMD_ERROR;1051	}1052 1053	pfhwdev = container_of(dev, struct hinic_pfhwdev, hwdev);1054	nic_io = &dev->func_to_io;1055	for (i = 0; i < ARRAY_SIZE(nic_vf_cmd_msg_handler); i++) {1056		vf_msg_handle = &nic_vf_cmd_msg_handler[i];1057		if (cmd == vf_msg_handle->cmd &&1058		    vf_msg_handle->cmd_msg_handler) {1059			err = vf_msg_handle->cmd_msg_handler(hwdev, vf_id,1060							     buf_in, in_size,1061							     buf_out,1062							     out_size);1063			break;1064		}1065	}1066	if (i == ARRAY_SIZE(nic_vf_cmd_msg_handler))1067		err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_L2NIC,1068					cmd, buf_in, in_size, buf_out,1069					out_size, HINIC_MGMT_MSG_SYNC);1070 1071	if (err &&  err != HINIC_MBOX_PF_BUSY_ACTIVE_FW)1072		dev_err(&nic_io->hwif->pdev->dev, "PF receive VF L2NIC cmd: %d process error, err:%d\n",1073			cmd, err);1074	return err;1075}1076 1077static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,1078				  u16 in_size, void *buf_out, u16 *out_size)1079{1080	struct hinic_dev_cap *dev_cap = buf_out;1081	struct hinic_hwdev *dev = hwdev;1082	struct hinic_cap *cap;1083 1084	cap = &dev->nic_cap;1085	memset(dev_cap, 0, sizeof(*dev_cap));1086 1087	dev_cap->max_vf = cap->max_vf;1088	dev_cap->max_sqs = cap->max_vf_qps;1089	dev_cap->max_rqs = cap->max_vf_qps;1090	dev_cap->port_id = dev->port_id;1091 1092	*out_size = sizeof(*dev_cap);1093 1094	return 0;1095}1096 1097static int hinic_init_vf_infos(struct hinic_func_to_io *nic_io, u16 vf_id)1098{1099	struct vf_data_storage *vf_infos = nic_io->vf_infos;1100 1101	if (set_vf_link_state > HINIC_IFLA_VF_LINK_STATE_DISABLE) {1102		dev_warn(&nic_io->hwif->pdev->dev, "Module Parameter set_vf_link_state value %d is out of range, resetting to %d\n",1103			 set_vf_link_state, HINIC_IFLA_VF_LINK_STATE_AUTO);1104		set_vf_link_state = HINIC_IFLA_VF_LINK_STATE_AUTO;1105	}1106 1107	switch (set_vf_link_state) {1108	case HINIC_IFLA_VF_LINK_STATE_AUTO:1109		vf_infos[vf_id].link_forced = false;1110		break;1111	case HINIC_IFLA_VF_LINK_STATE_ENABLE:1112		vf_infos[vf_id].link_forced = true;1113		vf_infos[vf_id].link_up = true;1114		break;1115	case HINIC_IFLA_VF_LINK_STATE_DISABLE:1116		vf_infos[vf_id].link_forced = true;1117		vf_infos[vf_id].link_up = false;1118		break;1119	default:1120		dev_err(&nic_io->hwif->pdev->dev, "Invalid input parameter set_vf_link_state: %d\n",1121			set_vf_link_state);1122		return -EINVAL;1123	}1124 1125	return 0;1126}1127 1128static void hinic_clear_vf_infos(struct hinic_dev *nic_dev, u16 vf_id)1129{1130	struct vf_data_storage *vf_infos;1131 1132	vf_infos = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);1133	if (vf_infos->pf_set_mac)1134		hinic_port_del_mac(nic_dev, vf_infos->vf_mac_addr, 0);1135 1136	if (hinic_vf_info_vlanprio(nic_dev->hwdev, vf_id))1137		hinic_kill_vf_vlan(nic_dev->hwdev, vf_id);1138 1139	if (vf_infos->max_rate)1140		hinic_set_vf_tx_rate(nic_dev->hwdev, vf_id, 0, 0);1141 1142	if (vf_infos->spoofchk)1143		hinic_set_vf_spoofchk(nic_dev->hwdev, vf_id, false);1144 1145	if (vf_infos->trust)1146		hinic_set_vf_trust(nic_dev->hwdev, vf_id, false);1147 1148	memset(vf_infos, 0, sizeof(*vf_infos));1149	/* set vf_infos to default */1150	hinic_init_vf_infos(&nic_dev->hwdev->func_to_io, HW_VF_ID_TO_OS(vf_id));1151}1152 1153static void hinic_deinit_vf_hw(struct hinic_sriov_info *sriov_info,1154			       u16 start_vf_id, u16 end_vf_id)1155{1156	struct hinic_dev *nic_dev;1157	u16 func_idx, idx;1158 1159	nic_dev = container_of(sriov_info, struct hinic_dev, sriov_info);1160 1161	for (idx = start_vf_id; idx <= end_vf_id; idx++) {1162		func_idx = hinic_glb_pf_vf_offset(nic_dev->hwdev->hwif) + idx;1163		hinic_set_wq_page_size(nic_dev->hwdev, func_idx,1164				       HINIC_HW_WQ_PAGE_SIZE);1165		hinic_clear_vf_infos(nic_dev, idx);1166	}1167}1168 1169int hinic_vf_func_init(struct hinic_hwdev *hwdev)1170{1171	struct hinic_register_vf register_info = {0};1172	u16 out_size = sizeof(register_info);1173	struct hinic_func_to_io *nic_io;1174	int err = 0;1175	u32 size, i;1176 1177	err = hinic_vf_mbox_random_id_init(hwdev);1178	if (err) {1179		dev_err(&hwdev->hwif->pdev->dev, "Failed to init vf mbox random id, err: %d\n",1180			err);1181		return err;1182	}1183 1184	nic_io = &hwdev->func_to_io;1185 1186	if (HINIC_IS_VF(hwdev->hwif)) {1187		err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,1188				       HINIC_PORT_CMD_VF_REGISTER,1189				       &register_info, sizeof(register_info),1190				       &register_info, &out_size, 0);1191		if (err || register_info.status || !out_size) {1192			dev_err(&hwdev->hwif->pdev->dev,1193				"Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",1194				err, register_info.status, out_size);1195			return -EIO;1196		}1197	} else {1198		err = hinic_register_pf_mbox_cb(hwdev, HINIC_MOD_CFGM,1199						cfg_mbx_pf_proc_vf_msg);1200		if (err) {1201			dev_err(&hwdev->hwif->pdev->dev,1202				"Register PF mailbox callback failed\n");1203			return err;1204		}1205		nic_io->max_vfs = hwdev->nic_cap.max_vf;1206		size = sizeof(*nic_io->vf_infos) * nic_io->max_vfs;1207		if (size != 0) {1208			nic_io->vf_infos = kzalloc(size, GFP_KERNEL);1209			if (!nic_io->vf_infos) {1210				err = -ENOMEM;1211				goto out_free_nic_io;1212			}1213 1214			for (i = 0; i < nic_io->max_vfs; i++) {1215				err = hinic_init_vf_infos(nic_io, i);1216				if (err)1217					goto err_init_vf_infos;1218			}1219 1220			err = hinic_register_pf_mbox_cb(hwdev, HINIC_MOD_L2NIC,1221							nic_pf_mbox_handler);1222			if (err)1223				goto err_register_pf_mbox_cb;1224		}1225	}1226 1227	return 0;1228 1229err_register_pf_mbox_cb:1230err_init_vf_infos:1231	kfree(nic_io->vf_infos);1232out_free_nic_io:1233	return err;1234}1235 1236void hinic_vf_func_free(struct hinic_hwdev *hwdev)1237{1238	struct hinic_register_vf unregister = {0};1239	u16 out_size = sizeof(unregister);1240	int err;1241 1242	if (HINIC_IS_VF(hwdev->hwif)) {1243		err = hinic_mbox_to_pf(hwdev, HINIC_MOD_L2NIC,1244				       HINIC_PORT_CMD_VF_UNREGISTER,1245				       &unregister, sizeof(unregister),1246				       &unregister, &out_size, 0);1247		if (err || !out_size || unregister.status)1248			dev_err(&hwdev->hwif->pdev->dev, "Failed to unregister VF, err: %d, status: 0x%x, out_size: 0x%x\n",1249				err, unregister.status, out_size);1250	} else {1251		if (hwdev->func_to_io.vf_infos) {1252			hinic_unregister_pf_mbox_cb(hwdev, HINIC_MOD_L2NIC);1253			kfree(hwdev->func_to_io.vf_infos);1254		}1255	}1256}1257 1258static int hinic_init_vf_hw(struct hinic_hwdev *hwdev, u16 start_vf_id,1259			    u16 end_vf_id)1260{1261	u16 i, func_idx;1262	int err;1263 1264	/* vf use 256K as default wq page size, and can't change it */1265	for (i = start_vf_id; i <= end_vf_id; i++) {1266		func_idx = hinic_glb_pf_vf_offset(hwdev->hwif) + i;1267		err = hinic_set_wq_page_size(hwdev, func_idx,1268					     HINIC_DEFAULT_WQ_PAGE_SIZE);1269		if (err)1270			return err;1271	}1272 1273	return 0;1274}1275 1276int hinic_pci_sriov_disable(struct pci_dev *pdev)1277{1278	struct hinic_sriov_info *sriov_info;1279	u16 tmp_vfs;1280 1281	sriov_info = hinic_get_sriov_info_by_pcidev(pdev);1282	/* if SR-IOV is already disabled then nothing will be done */1283	if (!sriov_info->sriov_enabled)1284		return 0;1285 1286	set_bit(HINIC_SRIOV_DISABLE, &sriov_info->state);1287 1288	/* If our VFs are assigned we cannot shut down SR-IOV1289	 * without causing issues, so just leave the hardware1290	 * available but disabled1291	 */1292	if (pci_vfs_assigned(sriov_info->pdev)) {1293		clear_bit(HINIC_SRIOV_DISABLE, &sriov_info->state);1294		dev_warn(&pdev->dev, "Unloading driver while VFs are assigned - VFs will not be deallocated\n");1295		return -EPERM;1296	}1297	sriov_info->sriov_enabled = false;1298 1299	/* disable iov and allow time for transactions to clear */1300	pci_disable_sriov(sriov_info->pdev);1301 1302	tmp_vfs = (u16)sriov_info->num_vfs;1303	sriov_info->num_vfs = 0;1304	hinic_deinit_vf_hw(sriov_info, OS_VF_ID_TO_HW(0),1305			   OS_VF_ID_TO_HW(tmp_vfs - 1));1306 1307	clear_bit(HINIC_SRIOV_DISABLE, &sriov_info->state);1308 1309	return 0;1310}1311 1312static int hinic_pci_sriov_enable(struct pci_dev *pdev, int num_vfs)1313{1314	struct hinic_sriov_info *sriov_info;1315	int err;1316 1317	sriov_info = hinic_get_sriov_info_by_pcidev(pdev);1318 1319	if (test_and_set_bit(HINIC_SRIOV_ENABLE, &sriov_info->state)) {1320		dev_err(&pdev->dev,1321			"SR-IOV enable in process, please wait, num_vfs %d\n",1322			num_vfs);1323		return -EPERM;1324	}1325 1326	err = hinic_init_vf_hw(sriov_info->hwdev, OS_VF_ID_TO_HW(0),1327			       OS_VF_ID_TO_HW((u16)num_vfs - 1));1328	if (err) {1329		dev_err(&sriov_info->pdev->dev,1330			"Failed to init vf in hardware before enable sriov, error %d\n",1331			err);1332		clear_bit(HINIC_SRIOV_ENABLE, &sriov_info->state);1333		return err;1334	}1335 1336	err = pci_enable_sriov(sriov_info->pdev, num_vfs);1337	if (err) {1338		dev_err(&pdev->dev,1339			"Failed to enable SR-IOV, error %d\n", err);1340		clear_bit(HINIC_SRIOV_ENABLE, &sriov_info->state);1341		return err;1342	}1343 1344	sriov_info->sriov_enabled = true;1345	sriov_info->num_vfs = num_vfs;1346	clear_bit(HINIC_SRIOV_ENABLE, &sriov_info->state);1347 1348	return num_vfs;1349}1350 1351int 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	else1363		return hinic_pci_sriov_enable(dev, num_vfs);1364}1365