summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/huawei/hinic/hinic_sriov.c')
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_sriov.c140
1 files changed, 105 insertions, 35 deletions
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
index efab2dd2c889..ee357088d021 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c
@@ -8,6 +8,7 @@
#include <linux/interrupt.h>
#include <linux/etherdevice.h>
#include <linux/netdevice.h>
+#include <linux/module.h>
#include "hinic_hw_dev.h"
#include "hinic_dev.h"
@@ -23,6 +24,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
+#define HINIC_MAX_QOS 7
static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
u16 vlan_id, u16 func_id)
@@ -38,11 +40,10 @@ static int hinic_set_mac(struct hinic_hwdev *hwdev, const u8 *mac_addr,
err = hinic_port_msg_cmd(hwdev, HINIC_PORT_CMD_SET_MAC, &mac_info,
sizeof(mac_info), &mac_info, &out_size);
if (err || out_size != sizeof(mac_info) ||
- (mac_info.status && mac_info.status != HINIC_PF_SET_VF_ALREADY &&
- mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
- dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to change MAC, ret = %d\n",
- mac_info.status);
- return -EFAULT;
+ (mac_info.status && mac_info.status != HINIC_MGMT_STATUS_EXIST)) {
+ dev_err(&hwdev->func_to_io.hwif->pdev->dev, "Failed to set MAC, err: %d, status: 0x%x, out size: 0x%x\n",
+ err, mac_info.status, out_size);
+ return -EIO;
}
return 0;
@@ -383,7 +384,7 @@ static int hinic_del_vf_mac_msg_handler(void *hwdev, u16 vf_id,
nic_io = &hw_dev->func_to_io;
vf_info = nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id);
- if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
+ if (vf_info->pf_set_mac && is_valid_ether_addr(mac_in->mac) &&
!memcmp(vf_info->vf_mac_addr, mac_in->mac, ETH_ALEN)) {
dev_warn(&hw_dev->hwif->pdev->dev, "PF has already set VF mac.\n");
mac_out->status = HINIC_PF_SET_VF_ALREADY;
@@ -429,6 +430,18 @@ static int hinic_get_vf_link_status_msg_handler(void *hwdev, u16 vf_id,
return 0;
}
+static bool check_func_table(struct hinic_hwdev *hwdev, u16 func_idx,
+ void *buf_in, u16 in_size)
+{
+ struct hinic_cmd_fw_ctxt *function_table = buf_in;
+
+ if (!hinic_mbox_check_func_id_8B(hwdev, func_idx, buf_in, in_size) ||
+ !function_table->rx_buf_sz)
+ return false;
+
+ return true;
+}
+
static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = {
{HINIC_PORT_CMD_VF_REGISTER, hinic_register_vf_msg_handler},
{HINIC_PORT_CMD_VF_UNREGISTER, hinic_unregister_vf_msg_handler},
@@ -439,6 +452,63 @@ static struct vf_cmd_msg_handle nic_vf_cmd_msg_handler[] = {
{HINIC_PORT_CMD_GET_LINK_STATE, hinic_get_vf_link_status_msg_handler},
};
+static struct vf_cmd_check_handle nic_cmd_support_vf[] = {
+ {HINIC_PORT_CMD_VF_REGISTER, NULL},
+ {HINIC_PORT_CMD_VF_UNREGISTER, NULL},
+ {HINIC_PORT_CMD_CHANGE_MTU, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_ADD_VLAN, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_DEL_VLAN, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_MAC, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_MAC, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_DEL_MAC, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RX_MODE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_PAUSE_INFO, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_LINK_STATE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_LRO, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RX_CSUM, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RX_VLAN_OFFLOAD, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_VPORT_STAT, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_CLEAN_VPORT_STAT, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_RSS_TEMPLATE_INDIR_TBL,
+ hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_RSS_TEMPLATE_TBL, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_RSS_HASH_ENGINE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RSS_CTX_TBL, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_RSS_TEMP_MGR, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_RSS_CFG, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_FWCTXT_INIT, check_func_table},
+ {HINIC_PORT_CMD_GET_MGMT_VERSION, NULL},
+ {HINIC_PORT_CMD_SET_FUNC_STATE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_GLOBAL_QPN, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_TSO, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_RQ_IQ_MAP, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_LINK_STATUS_REPORT, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_UPDATE_MAC, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_CAP, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_LINK_MODE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_GET_VF_COS, NULL},
+ {HINIC_PORT_CMD_SET_VHD_CFG, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_VLAN_FILTER, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_Q_FILTER, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_TCAM_FILTER, NULL},
+ {HINIC_PORT_CMD_UP_TC_ADD_FLOW, NULL},
+ {HINIC_PORT_CMD_UP_TC_DEL_FLOW, NULL},
+ {HINIC_PORT_CMD_UP_TC_FLUSH_TCAM, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_UP_TC_CTRL_TCAM_BLOCK, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_UP_TC_ENABLE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_CABLE_PLUG_EVENT, NULL},
+ {HINIC_PORT_CMD_LINK_ERR_EVENT, NULL},
+ {HINIC_PORT_CMD_SET_PORT_STATE, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_ETS, NULL},
+ {HINIC_PORT_CMD_SET_ANTI_ATTACK_RATE, NULL},
+ {HINIC_PORT_CMD_RESET_LINK_CFG, hinic_mbox_check_func_id_8B},
+ {HINIC_PORT_CMD_SET_LINK_FOLLOW, NULL},
+ {HINIC_PORT_CMD_CLEAR_QP_RES, NULL},
+};
+
#define CHECK_IPSU_15BIT 0X8000
static
@@ -452,8 +522,7 @@ struct hinic_sriov_info *hinic_get_sriov_info_by_pcidev(struct pci_dev *pdev)
static int hinic_check_mac_info(u8 status, u16 vlan_id)
{
- if ((status && status != HINIC_MGMT_STATUS_EXIST &&
- status != HINIC_PF_SET_VF_ALREADY) ||
+ if ((status && status != HINIC_MGMT_STATUS_EXIST) ||
(vlan_id & CHECK_IPSU_15BIT &&
status == HINIC_MGMT_STATUS_EXIST))
return -EINVAL;
@@ -495,12 +564,6 @@ static int hinic_update_mac(struct hinic_hwdev *hwdev, u8 *old_mac,
return -EINVAL;
}
- if (mac_info.status == HINIC_PF_SET_VF_ALREADY) {
- dev_warn(&hwdev->hwif->pdev->dev,
- "PF has already set VF MAC. Ignore update operation\n");
- return HINIC_PF_SET_VF_ALREADY;
- }
-
if (mac_info.status == HINIC_MGMT_STATUS_EXIST)
dev_warn(&hwdev->hwif->pdev->dev, "MAC is repeated. Ignore update operation\n");
@@ -730,7 +793,7 @@ int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos,
u16 vlanprio, cur_vlanprio;
sriov_info = &nic_dev->sriov_info;
- if (vf >= sriov_info->num_vfs || vlan > 4095 || qos > 7)
+ if (vf >= sriov_info->num_vfs || vlan >= VLAN_N_VID || qos > HINIC_MAX_QOS)
return -EINVAL;
if (vlan_proto != htons(ETH_P_8021Q))
return -EPROTONOSUPPORT;
@@ -776,7 +839,7 @@ int hinic_ndo_set_vf_trust(struct net_device *netdev, int vf, bool setting)
cur_trust = nic_io->vf_infos[vf].trust;
/* same request, so just return success */
- if ((setting && cur_trust) || (!setting && !cur_trust))
+ if (setting == cur_trust)
return 0;
err = hinic_set_vf_trust(adapter->hwdev, vf, setting);
@@ -793,8 +856,10 @@ 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)
{
- u32 speeds[] = {SPEED_10, SPEED_100, SPEED_1000, SPEED_10000,
- SPEED_25000, SPEED_40000, SPEED_100000};
+ static const 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;
@@ -806,12 +871,6 @@ int hinic_ndo_set_vf_bw(struct net_device *netdev,
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,
@@ -900,12 +959,11 @@ int hinic_ndo_set_vf_spoofchk(struct net_device *netdev, int vf, bool setting)
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))
+ if (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");
@@ -973,6 +1031,7 @@ int hinic_ndo_set_vf_link_state(struct net_device *netdev, int vf_id, int link)
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)
{
+ u8 size = ARRAY_SIZE(nic_cmd_support_vf);
struct vf_cmd_msg_handle *vf_msg_handle;
struct hinic_hwdev *dev = hwdev;
struct hinic_func_to_io *nic_io;
@@ -981,7 +1040,15 @@ static int nic_pf_mbox_handler(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
u32 i;
if (!hwdev)
- return -EFAULT;
+ return -EINVAL;
+
+ if (!hinic_mbox_check_cmd_valid(hwdev, nic_cmd_support_vf, vf_id, cmd,
+ buf_in, in_size, size)) {
+ dev_err(&dev->hwif->pdev->dev,
+ "PF Receive VF nic cmd: 0x%x, mbox len: 0x%x is invalid\n",
+ cmd, in_size);
+ return HINIC_MBOX_VF_CMD_ERROR;
+ }
pfhwdev = container_of(dev, struct hinic_pfhwdev, hwdev);
nic_io = &dev->func_to_io;
@@ -1020,6 +1087,7 @@ static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in,
dev_cap->max_vf = cap->max_vf;
dev_cap->max_sqs = cap->max_vf_qps;
dev_cap->max_rqs = cap->max_vf_qps;
+ dev_cap->port_id = dev->port_id;
*out_size = sizeof(*dev_cap);
@@ -1060,9 +1128,7 @@ static int hinic_init_vf_infos(struct hinic_func_to_io *nic_io, u16 vf_id)
static void hinic_clear_vf_infos(struct hinic_dev *nic_dev, u16 vf_id)
{
struct vf_data_storage *vf_infos;
- u16 func_id;
- func_id = hinic_glb_pf_vf_offset(nic_dev->hwdev->hwif) + vf_id;
vf_infos = nic_dev->hwdev->func_to_io.vf_infos + HW_VF_ID_TO_OS(vf_id);
if (vf_infos->pf_set_mac)
hinic_port_del_mac(nic_dev, vf_infos->vf_mac_addr, 0);
@@ -1084,8 +1150,8 @@ static void hinic_clear_vf_infos(struct hinic_dev *nic_dev, u16 vf_id)
hinic_init_vf_infos(&nic_dev->hwdev->func_to_io, HW_VF_ID_TO_OS(vf_id));
}
-static int hinic_deinit_vf_hw(struct hinic_sriov_info *sriov_info,
- u16 start_vf_id, u16 end_vf_id)
+static void hinic_deinit_vf_hw(struct hinic_sriov_info *sriov_info,
+ u16 start_vf_id, u16 end_vf_id)
{
struct hinic_dev *nic_dev;
u16 func_idx, idx;
@@ -1098,8 +1164,6 @@ static int hinic_deinit_vf_hw(struct hinic_sriov_info *sriov_info,
HINIC_HW_WQ_PAGE_SIZE);
hinic_clear_vf_infos(nic_dev, idx);
}
-
- return 0;
}
int hinic_vf_func_init(struct hinic_hwdev *hwdev)
@@ -1110,6 +1174,13 @@ int hinic_vf_func_init(struct hinic_hwdev *hwdev)
int err = 0;
u32 size, i;
+ err = hinic_vf_mbox_random_id_init(hwdev);
+ if (err) {
+ dev_err(&hwdev->hwif->pdev->dev, "Failed to init vf mbox random id, err: %d\n",
+ err);
+ return err;
+ }
+
nic_io = &hwdev->func_to_io;
if (HINIC_IS_VF(hwdev->hwif)) {
@@ -1121,7 +1192,6 @@ int hinic_vf_func_init(struct hinic_hwdev *hwdev)
dev_err(&hwdev->hwif->pdev->dev,
"Failed to register VF, err: %d, status: 0x%x, out size: 0x%x\n",
err, register_info.status, out_size);
- hinic_unregister_vf_mbox_cb(hwdev, HINIC_MOD_L2NIC);
return -EIO;
}
} else {
@@ -1239,7 +1309,7 @@ int hinic_pci_sriov_disable(struct pci_dev *pdev)
return 0;
}
-int hinic_pci_sriov_enable(struct pci_dev *pdev, int num_vfs)
+static int hinic_pci_sriov_enable(struct pci_dev *pdev, int num_vfs)
{
struct hinic_sriov_info *sriov_info;
int err;