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