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 ®ister_info, sizeof(register_info),
11907dd29ee1SLuo bin ®ister_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