Commit 72ef908b authored by Luo bin's avatar Luo bin Committed by Jakub Kicinski

hinic: add three net_device_ops of vf

adds ndo_set_vf_rate/ndo_set_vf_spoofchk/ndo_set_vf_link_state
to configure netdev of virtual function
Signed-off-by: default avatarLuo bin <luobin9@huawei.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 0d5c56a2
......@@ -849,6 +849,25 @@ static int init_cmdqs_ctxt(struct hinic_hwdev *hwdev,
return err;
}
static int hinic_set_cmdq_depth(struct hinic_hwdev *hwdev, u16 cmdq_depth)
{
struct hinic_cmd_hw_ioctxt hw_ioctxt = { 0 };
struct hinic_pfhwdev *pfhwdev;
pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
hw_ioctxt.func_idx = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
hw_ioctxt.ppf_idx = HINIC_HWIF_PPF_IDX(hwdev->hwif);
hw_ioctxt.set_cmdq_depth = HW_IOCTXT_SET_CMDQ_DEPTH_ENABLE;
hw_ioctxt.cmdq_depth = (u8)ilog2(cmdq_depth);
return hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
HINIC_COMM_CMD_HWCTXT_SET,
&hw_ioctxt, sizeof(hw_ioctxt), NULL,
NULL, HINIC_MGMT_MSG_SYNC);
}
/**
* hinic_init_cmdqs - init all cmdqs
* @cmdqs: cmdqs to init
......@@ -899,8 +918,18 @@ int hinic_init_cmdqs(struct hinic_cmdqs *cmdqs, struct hinic_hwif *hwif,
hinic_ceq_register_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ, cmdqs,
cmdq_ceq_handler);
err = hinic_set_cmdq_depth(hwdev, CMDQ_DEPTH);
if (err) {
dev_err(&hwif->pdev->dev, "Failed to set cmdq depth\n");
goto err_set_cmdq_depth;
}
return 0;
err_set_cmdq_depth:
hinic_ceq_unregister_cb(&func_to_io->ceqs, HINIC_CEQ_CMDQ);
err_cmdq_ctxt:
hinic_wqs_cmdq_free(&cmdqs->cmdq_pages, cmdqs->saved_wqs,
HINIC_MAX_CMDQ_TYPES);
......
......@@ -44,10 +44,6 @@ enum io_status {
IO_RUNNING = 1,
};
enum hw_ioctxt_set_cmdq_depth {
HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT,
};
/**
* get_capability - convert device capabilities to NIC capabilities
* @hwdev: the HW device to set and convert device capabilities for
......@@ -667,6 +663,32 @@ static void free_pfhwdev(struct hinic_pfhwdev *pfhwdev)
hinic_pf_to_mgmt_free(&pfhwdev->pf_to_mgmt);
}
static int hinic_l2nic_reset(struct hinic_hwdev *hwdev)
{
struct hinic_cmd_l2nic_reset l2nic_reset = {0};
u16 out_size = sizeof(l2nic_reset);
struct hinic_pfhwdev *pfhwdev;
int err;
pfhwdev = container_of(hwdev, struct hinic_pfhwdev, hwdev);
l2nic_reset.func_id = HINIC_HWIF_FUNC_IDX(hwdev->hwif);
/* 0 represents standard l2nic reset flow */
l2nic_reset.reset_flag = 0;
err = hinic_msg_to_mgmt(&pfhwdev->pf_to_mgmt, HINIC_MOD_COMM,
HINIC_COMM_CMD_L2NIC_RESET, &l2nic_reset,
sizeof(l2nic_reset), &l2nic_reset,
&out_size, HINIC_MGMT_MSG_SYNC);
if (err || !out_size || l2nic_reset.status) {
dev_err(&hwdev->hwif->pdev->dev, "Failed to reset L2NIC resources, err: %d, status: 0x%x, out_size: 0x%x\n",
err, l2nic_reset.status, out_size);
return -EIO;
}
return 0;
}
/**
* hinic_init_hwdev - Initialize the NIC HW
* @pdev: the NIC pci device
......@@ -729,6 +751,10 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
goto err_init_pfhwdev;
}
err = hinic_l2nic_reset(hwdev);
if (err)
goto err_l2nic_reset;
err = get_dev_cap(hwdev);
if (err) {
dev_err(&pdev->dev, "Failed to get device capabilities\n");
......@@ -759,6 +785,7 @@ struct hinic_hwdev *hinic_init_hwdev(struct pci_dev *pdev)
err_init_fw_ctxt:
hinic_vf_func_free(hwdev);
err_vf_func_init:
err_l2nic_reset:
err_dev_cap:
free_pfhwdev(pfhwdev);
......
......@@ -25,6 +25,7 @@
#define HINIC_PF_SET_VF_ALREADY 0x4
#define HINIC_MGMT_STATUS_EXIST 0x6
#define HINIC_MGMT_CMD_UNSUPPORTED 0xFF
struct hinic_cap {
u16 max_qps;
......@@ -33,6 +34,11 @@ struct hinic_cap {
u16 max_vf_qps;
};
enum hw_ioctxt_set_cmdq_depth {
HW_IOCTXT_SET_CMDQ_DEPTH_DEFAULT,
HW_IOCTXT_SET_CMDQ_DEPTH_ENABLE,
};
enum hinic_port_cmd {
HINIC_PORT_CMD_VF_REGISTER = 0x0,
HINIC_PORT_CMD_VF_UNREGISTER = 0x1,
......@@ -86,12 +92,16 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_FWCTXT_INIT = 69,
HINIC_PORT_CMD_ENABLE_SPOOFCHK = 78,
HINIC_PORT_CMD_GET_MGMT_VERSION = 88,
HINIC_PORT_CMD_SET_FUNC_STATE = 93,
HINIC_PORT_CMD_GET_GLOBAL_QPN = 102,
HINIC_PORT_CMD_SET_VF_RATE = 105,
HINIC_PORT_CMD_SET_VF_VLAN = 106,
HINIC_PORT_CMD_CLR_VF_VLAN,
......@@ -107,6 +117,8 @@ enum hinic_port_cmd {
HINIC_PORT_CMD_GET_CAP = 170,
HINIC_PORT_CMD_SET_LRO_TIMER = 244,
HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE = 249,
};
enum hinic_ucode_cmd {
......@@ -247,6 +259,15 @@ struct hinic_cmd_hw_ci {
u64 ci_addr;
};
struct hinic_cmd_l2nic_reset {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 reset_flag;
};
struct hinic_hwdev {
struct hinic_hwif *hwif;
struct msix_entry *msix_entries;
......
......@@ -10,6 +10,7 @@
#include <linux/io.h>
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/delay.h>
#include "hinic_hw_csr.h"
#include "hinic_hw_if.h"
......@@ -18,6 +19,8 @@
#define VALID_MSIX_IDX(attr, msix_index) ((msix_index) < (attr)->num_irqs)
#define WAIT_HWIF_READY_TIMEOUT 10000
/**
* hinic_msix_attr_set - set message attribute for msix entry
* @hwif: the HW interface of a pci function device
......@@ -187,20 +190,39 @@ void hinic_set_msix_state(struct hinic_hwif *hwif, u16 msix_idx,
**/
static int hwif_ready(struct hinic_hwif *hwif)
{
struct pci_dev *pdev = hwif->pdev;
u32 addr, attr1;
addr = HINIC_CSR_FUNC_ATTR1_ADDR;
attr1 = hinic_hwif_read_reg(hwif, addr);
if (!HINIC_FA1_GET(attr1, INIT_STATUS)) {
dev_err(&pdev->dev, "hwif status is not ready\n");
return -EFAULT;
if (!HINIC_FA1_GET(attr1, MGMT_INIT_STATUS))
return -EBUSY;
if (HINIC_IS_VF(hwif)) {
if (!HINIC_FA1_GET(attr1, PF_INIT_STATUS))
return -EBUSY;
}
return 0;
}
static int wait_hwif_ready(struct hinic_hwif *hwif)
{
unsigned long timeout = 0;
do {
if (!hwif_ready(hwif))
return 0;
usleep_range(999, 1000);
timeout++;
} while (timeout <= WAIT_HWIF_READY_TIMEOUT);
dev_err(&hwif->pdev->dev, "Wait for hwif timeout\n");
return -EBUSY;
}
/**
* set_hwif_attr - set the attributes in the relevant members in hwif
* @hwif: the HW interface of a pci function device
......@@ -373,7 +395,7 @@ int hinic_init_hwif(struct hinic_hwif *hwif, struct pci_dev *pdev)
goto err_map_intr_bar;
}
err = hwif_ready(hwif);
err = wait_hwif_ready(hwif);
if (err) {
dev_err(&pdev->dev, "HW interface is not ready\n");
goto err_hwif_ready;
......
......@@ -55,13 +55,15 @@
#define HINIC_FA1_IRQS_PER_FUNC_SHIFT 20
#define HINIC_FA1_DMA_ATTR_PER_FUNC_SHIFT 24
/* reserved members - off 27 */
#define HINIC_FA1_INIT_STATUS_SHIFT 30
#define HINIC_FA1_MGMT_INIT_STATUS_SHIFT 30
#define HINIC_FA1_PF_INIT_STATUS_SHIFT 31
#define HINIC_FA1_AEQS_PER_FUNC_MASK 0x3
#define HINIC_FA1_CEQS_PER_FUNC_MASK 0x7
#define HINIC_FA1_IRQS_PER_FUNC_MASK 0xF
#define HINIC_FA1_DMA_ATTR_PER_FUNC_MASK 0x7
#define HINIC_FA1_INIT_STATUS_MASK 0x1
#define HINIC_FA1_MGMT_INIT_STATUS_MASK 0x1
#define HINIC_FA1_PF_INIT_STATUS_MASK 0x1
#define HINIC_FA1_GET(val, member) \
(((val) >> HINIC_FA1_##member##_SHIFT) & HINIC_FA1_##member##_MASK)
......
......@@ -627,7 +627,7 @@ wait_for_mbox_seg_completion(struct hinic_mbox_func_to_func *func_to_func,
struct hinic_hwdev *hwdev = func_to_func->hwdev;
struct completion *done = &send_mbox->send_done;
u32 cnt = 0;
ulong jif;
unsigned long jif;
if (poll) {
while (cnt < MBOX_MSG_POLLING_TIMEOUT) {
......@@ -869,7 +869,7 @@ int hinic_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func,
{
struct hinic_recv_mbox *mbox_for_resp;
struct mbox_msg_info msg_info = {0};
ulong timeo;
unsigned long timeo;
int err;
mbox_for_resp = &func_to_func->mbox_resp[dst_func];
......
......@@ -427,10 +427,6 @@ static int hinic_open(struct net_device *netdev)
goto err_func_port_state;
}
if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
/* Wait up to 3 sec between port enable to link state */
msleep(3000);
down(&nic_dev->mgmt_lock);
err = hinic_port_link_state(nic_dev, &link_state);
......@@ -766,10 +762,12 @@ static void hinic_set_rx_mode(struct net_device *netdev)
HINIC_RX_MODE_MC |
HINIC_RX_MODE_BC;
if (netdev->flags & IFF_PROMISC)
rx_mode |= HINIC_RX_MODE_PROMISC;
else if (netdev->flags & IFF_ALLMULTI)
if (netdev->flags & IFF_PROMISC) {
if (!HINIC_IS_VF(nic_dev->hwdev->hwif))
rx_mode |= HINIC_RX_MODE_PROMISC;
} else if (netdev->flags & IFF_ALLMULTI) {
rx_mode |= HINIC_RX_MODE_MC_ALL;
}
rx_mode_work->rx_mode = rx_mode;
......@@ -868,6 +866,9 @@ static const struct net_device_ops hinic_netdev_ops = {
.ndo_set_vf_vlan = hinic_ndo_set_vf_vlan,
.ndo_get_vf_config = hinic_ndo_get_vf_config,
.ndo_set_vf_trust = hinic_ndo_set_vf_trust,
.ndo_set_vf_rate = hinic_ndo_set_vf_bw,
.ndo_set_vf_spoofchk = hinic_ndo_set_vf_spoofchk,
.ndo_set_vf_link_state = hinic_ndo_set_vf_link_state,
};
static const struct net_device_ops hinicvf_netdev_ops = {
......@@ -1232,6 +1233,8 @@ static void hinic_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
hinic_port_del_mac(nic_dev, netdev->dev_addr, 0);
hinic_hwdev_cb_unregister(nic_dev->hwdev,
HINIC_MGMT_MSG_CMD_LINK_STATUS);
......
......@@ -66,15 +66,15 @@ static int change_mac(struct hinic_dev *nic_dev, const u8 *addr,
return -EFAULT;
}
if (cmd == HINIC_PORT_CMD_SET_MAC && port_mac_cmd.status ==
HINIC_PF_SET_VF_ALREADY) {
dev_warn(&pdev->dev, "PF has already set VF mac, Ignore set operation\n");
if (port_mac_cmd.status == HINIC_PF_SET_VF_ALREADY) {
dev_warn(&pdev->dev, "PF has already set VF mac, ignore %s operation\n",
(op == MAC_SET) ? "set" : "del");
return HINIC_PF_SET_VF_ALREADY;
}
if (cmd == HINIC_PORT_CMD_SET_MAC && port_mac_cmd.status ==
HINIC_MGMT_STATUS_EXIST)
dev_warn(&pdev->dev, "MAC is repeated. Ignore set operation\n");
dev_warn(&pdev->dev, "MAC is repeated, ignore set operation\n");
return 0;
}
......
......@@ -506,6 +506,49 @@ struct hinic_cmd_vport_stats {
struct hinic_vport_stats stats;
};
struct hinic_tx_rate_cfg_max_min {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 rsvd1;
u32 min_rate;
u32 max_rate;
u8 rsvd2[8];
};
struct hinic_tx_rate_cfg {
u8 status;
u8 version;
u8 rsvd0[6];
u16 func_id;
u16 rsvd1;
u32 tx_rate;
};
enum nic_speed_level {
LINK_SPEED_10MB = 0,
LINK_SPEED_100MB,
LINK_SPEED_1GB,
LINK_SPEED_10GB,
LINK_SPEED_25GB,
LINK_SPEED_40GB,
LINK_SPEED_100GB,
LINK_SPEED_LEVELS,
};
struct hinic_spoofchk_set {
u8 status;
u8 version;
u8 rsvd0[6];
u8 state;
u8 rsvd1;
u16 func_id;
};
int hinic_port_add_mac(struct hinic_dev *nic_dev, const u8 *addr,
u16 vlan_id);
......
......@@ -22,6 +22,7 @@ MODULE_PARM_DESC(set_vf_link_state, "Set vf link state, 0 represents link auto,
#define HINIC_VLAN_PRIORITY_SHIFT 13
#define HINIC_ADD_VLAN_IN_MAC 0x8000
#define HINIC_TX_RATE_TABLE_FULL 12
static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
u16 vlan_id, u16 func_id)
......@@ -129,6 +130,84 @@ static int hinic_set_vf_vlan(struct hinic_hwdev *hwdev, bool add, u16 vid,
return 0;
}
static int hinic_set_vf_tx_rate_max_min(struct hinic_hwdev *hwdev, u16 vf_id,
u32 max_rate, u32 min_rate)
{
struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
struct hinic_tx_rate_cfg_max_min rate_cfg = {0};
u16 out_size = sizeof(rate_cfg);
int err;
rate_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
rate_cfg.max_rate = max_rate;
rate_cfg.min_rate = min_rate;
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VF_MAX_MIN_RATE,
&rate_cfg, sizeof(rate_cfg), &rate_cfg,
&out_size);
if ((rate_cfg.status != HINIC_MGMT_CMD_UNSUPPORTED &&
rate_cfg.status) || err || !out_size) {
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",
HW_VF_ID_TO_OS(vf_id), max_rate, min_rate, err,
rate_cfg.status, out_size);
return -EIO;
}
if (!rate_cfg.status) {
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = max_rate;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = min_rate;
}
return rate_cfg.status;
}
static int hinic_set_vf_rate_limit(struct hinic_hwdev *hwdev, u16 vf_id,
u32 tx_rate)
{
struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
struct hinic_tx_rate_cfg rate_cfg = {0};
u16 out_size = sizeof(rate_cfg);
int err;
rate_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
rate_cfg.tx_rate = tx_rate;
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_VF_RATE,
&rate_cfg, sizeof(rate_cfg), &rate_cfg,
&out_size);
if (err || !out_size || rate_cfg.status) {
dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) rate(%d), err: %d, status: 0x%x, out size: 0x%x\n",
HW_VF_ID_TO_OS(vf_id), tx_rate, err, rate_cfg.status,
out_size);
if (rate_cfg.status)
return rate_cfg.status;
return -EIO;
}
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].max_rate = tx_rate;
nic_io->vf_infos[HW_VF_ID_TO_OS(vf_id)].min_rate = 0;
return 0;
}
static int hinic_set_vf_tx_rate(struct hinic_hwdev *hwdev, u16 vf_id,
u32 max_rate, u32 min_rate)
{
int err;
err = hinic_set_vf_tx_rate_max_min(hwdev, vf_id, max_rate, min_rate);
if (err != HINIC_MGMT_CMD_UNSUPPORTED)
return err;
if (min_rate) {
dev_err(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate\n");
return -EOPNOTSUPP;
}
dev_info(&hwdev->hwif->pdev->dev, "Current firmware doesn't support to set min tx rate, force min_tx_rate = max_tx_rate\n");
return hinic_set_vf_rate_limit(hwdev, vf_id, max_rate);
}
static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id)
{
struct vf_data_storage *vf_info;
......@@ -160,6 +239,17 @@ static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id)
}
}
if (vf_info->max_rate) {
err = hinic_set_vf_tx_rate(hwdev, vf_id, vf_info->max_rate,
vf_info->min_rate);
if (err) {
dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF %d max rate: %d, min rate: %d\n",
HW_VF_ID_TO_OS(vf_id), vf_info->max_rate,
vf_info->min_rate);
return err;
}
}
return 0;
}
......@@ -700,6 +790,185 @@ int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
return err;
}
int hinic_ndo_set_vf_bw(struct net_device *netdev,
int vf, int min_tx_rate, int max_tx_rate)
{
u32 speeds[] = {SPEED_10, SPEED_100, SPEED_1000, SPEED_10000,
SPEED_25000, SPEED_40000, SPEED_100000};
struct hinic_dev *nic_dev = netdev_priv(netdev);
struct hinic_port_cap port_cap = { 0 };
enum hinic_port_link_state link_state;
int err;
if (vf >= nic_dev->sriov_info.num_vfs) {
netif_err(nic_dev, drv, netdev, "VF number must be less than %d\n",
nic_dev->sriov_info.num_vfs);
return -EINVAL;
}
if (max_tx_rate < min_tx_rate) {
netif_err(nic_dev, drv, netdev, "Max rate %d must be greater than or equal to min rate %d\n",
max_tx_rate, min_tx_rate);
return -EINVAL;
}
err = hinic_port_link_state(nic_dev, &link_state);
if (err) {
netif_err(nic_dev, drv, netdev,
"Get link status failed when setting vf tx rate\n");
return -EIO;
}
if (link_state == HINIC_LINK_STATE_DOWN) {
netif_err(nic_dev, drv, netdev,
"Link status must be up when setting vf tx rate\n");
return -EPERM;
}
err = hinic_port_get_cap(nic_dev, &port_cap);
if (err || port_cap.speed > LINK_SPEED_100GB)
return -EIO;
/* rate limit cannot be less than 0 and greater than link speed */
if (max_tx_rate < 0 || max_tx_rate > speeds[port_cap.speed]) {
netif_err(nic_dev, drv, netdev, "Max tx rate must be in [0 - %d]\n",
speeds[port_cap.speed]);
return -EINVAL;
}
err = hinic_set_vf_tx_rate(nic_dev->hwdev, OS_VF_ID_TO_HW(vf),
max_tx_rate, min_tx_rate);
if (err) {
netif_err(nic_dev, drv, netdev,
"Unable to set VF %d max rate %d min rate %d%s\n",
vf, max_tx_rate, min_tx_rate,
err == HINIC_TX_RATE_TABLE_FULL ?
", tx rate profile is full" : "");
return -EIO;
}
netif_info(nic_dev, drv, netdev,
"Set VF %d max tx rate %d min tx rate %d successfully\n",
vf, max_tx_rate, min_tx_rate);
return 0;
}
static int hinic_set_vf_spoofchk(struct hinic_hwdev *hwdev, u16 vf_id,
bool spoofchk)
{
struct hinic_spoofchk_set spoofchk_cfg = {0};
struct vf_data_storage *vf_infos = NULL;
u16 out_size = sizeof(spoofchk_cfg);
int err;
if (!hwdev)
return -EINVAL;
vf_infos = hwdev->func_to_io.vf_infos;
spoofchk_cfg.func_id = hinic_glb_pf_vf_offset(hwdev->hwif) + vf_id;
spoofchk_cfg.state = spoofchk ? 1 : 0;
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_ENABLE_SPOOFCHK,
&spoofchk_cfg, sizeof(spoofchk_cfg),
&spoofchk_cfg, &out_size);
if (spoofchk_cfg.status == HINIC_MGMT_CMD_UNSUPPORTED) {
err = HINIC_MGMT_CMD_UNSUPPORTED;
} else if (err || !out_size || spoofchk_cfg.status) {
dev_err(&hwdev->hwif->pdev->dev, "Failed to set VF(%d) spoofchk, err: %d, status: 0x%x, out size: 0x%x\n",
HW_VF_ID_TO_OS(vf_id), err, spoofchk_cfg.status,
out_size);
err = -EIO;
}
vf_infos[HW_VF_ID_TO_OS(vf_id)].spoofchk = spoofchk;
return err;
}
int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
{
struct hinic_dev *nic_dev = netdev_priv(netdev);
struct hinic_sriov_info *sriov_info;
bool cur_spoofchk;
int err;
sriov_info = &nic_dev->sriov_info;
if (vf >= sriov_info->num_vfs)
return -EINVAL;
cur_spoofchk = nic_dev->hwdev->func_to_io.vf_infos[vf].spoofchk;
/* same request, so just return success */
if ((setting && cur_spoofchk) || (!setting && !cur_spoofchk))
return 0;
err = hinic_set_vf_spoofchk(sriov_info->hwdev,
OS_VF_ID_TO_HW(vf), setting);
if (!err) {
netif_info(nic_dev, drv, netdev, "Set VF %d spoofchk %s successfully\n",
vf, setting ? "on" : "off");
} else if (err == HINIC_MGMT_CMD_UNSUPPORTED) {
netif_err(nic_dev, drv, netdev,
"Current firmware doesn't support to set vf spoofchk, need to upgrade latest firmware version\n");
err = -EOPNOTSUPP;
}
return err;
}
static int hinic_set_vf_link_state(struct hinic_hwdev *hwdev, u16 vf_id,
int link)
{
struct hinic_func_to_io *nic_io = &hwdev->func_to_io;
struct vf_data_storage *vf_infos = nic_io->vf_infos;
u8 link_status = 0;
switch (link) {
case HINIC_IFLA_VF_LINK_STATE_AUTO:
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = false;
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = nic_io->link_status ?
true : false;
link_status = nic_io->link_status;
break;
case HINIC_IFLA_VF_LINK_STATE_ENABLE:
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true;
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = true;
link_status = HINIC_LINK_UP;
break;
case HINIC_IFLA_VF_LINK_STATE_DISABLE:
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_forced = true;
vf_infos[HW_VF_ID_TO_OS(vf_id)].link_up = false;
link_status = HINIC_LINK_DOWN;
break;
default:
return -EINVAL;
}
/* Notify the VF of its new link state */
hinic_notify_vf_link_status(hwdev, vf_id, link_status);
return 0;
}
int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
{
struct hinic_dev *nic_dev = netdev_priv(netdev);
struct hinic_sriov_info *sriov_info;
sriov_info = &nic_dev->sriov_info;
if (vf_id >= sriov_info->num_vfs) {
netif_err(nic_dev, drv, netdev,
"Invalid VF Identifier %d\n", vf_id);
return -EINVAL;
}
return hinic_set_vf_link_state(sriov_info->hwdev,
OS_VF_ID_TO_HW(vf_id), link);
}
/* pf receive message from vf */
static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
u16 in_size, void *buf_out, u16 *out_size)
......@@ -801,6 +1070,12 @@ static void hinic_clear_vf_infos(struct hinic_dev *nic_dev, u16 vf_id)
if (hinic_vf_info_vlanprio(nic_dev->hwdev, vf_id))
hinic_kill_vf_vlan(nic_dev->hwdev, vf_id);
if (vf_infos->max_rate)
hinic_set_vf_tx_rate(nic_dev->hwdev, vf_id, 0, 0);
if (vf_infos->spoofchk)
hinic_set_vf_spoofchk(nic_dev->hwdev, vf_id, false);
if (vf_infos->trust)
hinic_set_vf_trust(nic_dev->hwdev, vf_id, false);
......
......@@ -86,6 +86,13 @@ int hinic_ndo_get_vf_config(struct net_device *netdev,
int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting);
int hinic_ndo_set_vf_bw(struct net_device *netdev,
int vf, int min_tx_rate, int max_tx_rate);
int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting);
int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link);
void hinic_notify_all_vfs_link_changed(struct hinic_hwdev *hwdev,
u8 link_status);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment