From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
2.3.0.1 and later drivers and firmware add MAC reuse feature, when the driver is compatible with firmware version 2.3.0.0 and before, if the ip link command is used to configure the MAC and VLAN for the VF, it will cause the VF network anomaly.
To solve this problem, the driver obtains the function capability from the firmware when loading, and determines whether to support MAC reuse for different processing.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_hwdev.h | 1 + .../ethernet/huawei/hinic/hinic_mgmt_interface.h | 11 ++++ drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c | 45 +++++++++++++++-- drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h | 4 ++ drivers/net/ethernet/huawei/hinic/hinic_nic_io.c | 10 +++- drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h | 2 + drivers/net/ethernet/huawei/hinic/hinic_sriov.c | 59 ++++++++++++++-------- 7 files changed, 106 insertions(+), 26 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h index a096f91..2a81867 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h @@ -319,6 +319,7 @@ struct hinic_hwdev { struct hinic_board_info board_info; #define MGMT_VERSION_MAX_LEN 32 u8 mgmt_ver[MGMT_VERSION_MAX_LEN]; + u64 fw_support_func_flag; };
int hinic_init_comm_ch(struct hinic_hwdev *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h b/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h index 3c3be6e..8673cf5 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_mgmt_interface.h @@ -690,6 +690,15 @@ struct hinic_port_rt_cmd { u8 rsvd1[6]; };
+struct fw_support_func { + u8 status; + u8 version; + u8 rsvd0[6]; + + u64 flag; + u64 rsvd; +}; + struct hinic_vf_dcb_state { u8 status; u8 version; @@ -741,6 +750,8 @@ struct hinic_set_link_follow {
int hinic_get_base_qpn(void *hwdev, u16 *global_qpn);
+int hinic_get_fw_support_func(void *hwdev); + int hinic_vf_func_init(struct hinic_hwdev *hwdev);
void hinic_vf_func_free(struct hinic_hwdev *hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c index f9e16ec..7dfedbd 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.c @@ -201,6 +201,34 @@ int hinic_get_base_qpn(void *hwdev, u16 *global_qpn) return 0; }
+int hinic_get_fw_support_func(void *hwdev) +{ + struct fw_support_func support_flag = {0}; + struct hinic_hwdev *dev = hwdev; + u16 out_size = sizeof(support_flag); + int err; + + if (!hwdev) + return -EINVAL; + + err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_L2NIC, + HINIC_PORT_CMD_GET_FW_SUPPORT_FLAG, + &support_flag, sizeof(support_flag), + &support_flag, &out_size, 0); + if (support_flag.status == HINIC_MGMT_CMD_UNSUPPORTED) { + nic_info(dev->dev_hdl, "Current firmware doesn't support to get function capability\n"); + support_flag.flag = 0; + } else if (support_flag.status || err || !out_size) { + nic_err(dev->dev_hdl, "Failed to get function capability, err: %d, status: 0x%x, out size: 0x%x\n", + err, support_flag.status, out_size); + return -EFAULT; + } + + dev->fw_support_func_flag = support_flag.flag; + + return 0; +} + #define HINIC_ADD_VLAN_IN_MAC 0x8000 #define HINIC_VLAN_ID_MASK 0x7FFF
@@ -352,6 +380,11 @@ int hinic_update_mac_vlan(void *hwdev, u16 old_vlan, u16 new_vlan, int vf_id) if (!vf_info->pf_set_mac) return 0;
+ if (!FW_SUPPORT_MAC_REUSE_FUNC(dev)) { + nic_info(dev->dev_hdl, "Current firmware doesn't support mac reuse\n"); + return 0; + } + func_id = hinic_glb_pf_vf_offset(dev) + (u16)vf_id; vlan_id = old_vlan; if (vlan_id) @@ -2562,9 +2595,14 @@ static int hinic_init_vf_config(struct hinic_hwdev *hwdev, u16 vf_id) vf_info = hwdev->nic_io->vf_infos + HW_VF_ID_TO_OS(vf_id); if (vf_info->pf_set_mac) { func_id = hinic_glb_pf_vf_offset(hwdev) + vf_id; - vlan_id = vf_info->pf_vlan; - if (vlan_id) - vlan_id |= HINIC_ADD_VLAN_IN_MAC; + if (FW_SUPPORT_MAC_REUSE_FUNC(hwdev)) { + vlan_id = vf_info->pf_vlan; + if (vlan_id) + vlan_id |= HINIC_ADD_VLAN_IN_MAC; + } else { + vlan_id = 0; + } + err = hinic_set_mac(hwdev, vf_info->vf_mac_addr, vlan_id, func_id); if (err) { @@ -4065,3 +4103,4 @@ int hinic_get_sfp_type(void *hwdev, u8 *data0, u8 *data1)
return 0; } + diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h index 427d469..e0979df 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_cfg.h @@ -19,6 +19,10 @@ #define OS_VF_ID_TO_HW(os_vf_id) ((os_vf_id) + 1) #define HW_VF_ID_TO_OS(hw_vf_id) ((hw_vf_id) - 1)
+#define FW_SUPPORT_MAC_REUSE 0x1 +#define FW_SUPPORT_MAC_REUSE_FUNC(hwdev) \ + ((hwdev)->fw_support_func_flag & FW_SUPPORT_MAC_REUSE) + #define HINIC_VLAN_PRIORITY_SHIFT 13
#define HINIC_RSS_INDIR_SIZE 256 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c b/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c index 1cb4e26..f2fb0bc 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_io.c @@ -831,9 +831,17 @@ int hinic_init_nic_hwdev(void *hwdev, u16 rx_buff_len) }
/* VFs don't set port routine command report */ - if (hinic_func_type(dev) != TYPE_VF) + if (hinic_func_type(dev) != TYPE_VF) { + /* Get the fw support mac reuse flag */ + err = hinic_get_fw_support_func(hwdev); + if (err) { + nic_err(dev->dev_hdl, "Failed to get function capability\n"); + return err; + } + /* Inform mgmt to send sfp's information to driver */ err = hinic_set_port_routine_cmd_report(hwdev, true); + }
return err; } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h index 46464b1f..d428f48 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_port_cmd.h @@ -146,6 +146,8 @@ enum hinic_port_cmd { HINIC_PORT_CMD_SET_PORT_LINK_STATUS = 0x76, HINIC_PORT_CMD_SET_CGE_PAUSE_TIME_CFG = 0x77,
+ HINIC_PORT_CMD_GET_FW_SUPPORT_FLAG = 0x79, + HINIC_PORT_CMD_SET_PORT_REPORT = 0x7B,
HINIC_PORT_CMD_LINK_STATUS_REPORT = 0xa0, diff --git a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c index 37d0116..73ab2d7 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_sriov.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_sriov.c @@ -266,6 +266,42 @@ int hinic_ndo_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
/*lint -save -e574 -e734*/ #ifdef IFLA_VF_MAX +static int set_hw_vf_vlan(struct hinic_sriov_info *sriov_info, + u16 cur_vlanprio, int vf, u16 vlan, u8 qos) +{ + int err = 0; + u16 old_vlan = cur_vlanprio & VLAN_VID_MASK; + + if (vlan || qos) { + if (cur_vlanprio) { + err = hinic_kill_vf_vlan(sriov_info->hwdev, + OS_VF_ID_TO_HW(vf)); + if (err) { + nic_err(&sriov_info->pdev->dev, "Failed to delete vf %d old vlan %d\n", + vf, old_vlan); + return err; + } + } + err = hinic_add_vf_vlan(sriov_info->hwdev, + OS_VF_ID_TO_HW(vf), vlan, qos); + if (err) { + nic_err(&sriov_info->pdev->dev, "Failed to add vf %d new vlan %d\n", + vf, vlan); + return err; + } + } else { + err = hinic_kill_vf_vlan(sriov_info->hwdev, OS_VF_ID_TO_HW(vf)); + if (err) { + nic_err(&sriov_info->pdev->dev, "Failed to delete vf %d vlan %d\n", + vf, old_vlan); + return err; + } + } + + return hinic_update_mac_vlan(sriov_info->hwdev, old_vlan, vlan, + OS_VF_ID_TO_HW(vf)); +} + #ifdef IFLA_VF_VLAN_INFO_MAX int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos, __be16 vlan_proto) @@ -276,7 +312,6 @@ int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) struct hinic_nic_dev *adapter = netdev_priv(netdev); struct hinic_sriov_info *sriov_info; u16 vlanprio, cur_vlanprio; - int err = 0;
if (!FUNC_SUPPORT_SET_VF_MAC_VLAN(adapter->hwdev)) { nicif_err(adapter, drv, netdev, @@ -298,27 +333,7 @@ int hinic_ndo_set_vf_vlan(struct net_device *netdev, int vf, u16 vlan, u8 qos) if (vlanprio == cur_vlanprio) return 0;
- if (vlan || qos) { - if (cur_vlanprio) - err = hinic_kill_vf_vlan(sriov_info->hwdev, - OS_VF_ID_TO_HW(vf)); - if (err) - goto out; - err = hinic_add_vf_vlan(sriov_info->hwdev, OS_VF_ID_TO_HW(vf), - vlan, qos); - } else { - err = hinic_kill_vf_vlan(sriov_info->hwdev, OS_VF_ID_TO_HW(vf)); - } - - if (err) - return err; - - err = hinic_update_mac_vlan(sriov_info->hwdev, - cur_vlanprio & VLAN_VID_MASK, vlan, - OS_VF_ID_TO_HW(vf)); - -out: - return err; + return set_hw_vf_vlan(sriov_info, cur_vlanprio, vf, vlan, qos); } #endif
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
VF does not switch interrupts on the virtual machine. If the hardware sends the entire tx queue packets between tx_poll processed all the packets and calling napi_complete, it will cause the hardware to no longer report the interrupt, napi will not be called again, and driver unable free up tx resources. Eventually, the queue is full and packets cannot be sent.
By calling tx_poll again before napi_complete, to ensure that the queue resources can be released in time.
When clearing queue resources during ifconfig down processing, determine whether the packet has been sent more accurately by judging hardware CI and software PI.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 3 ++- drivers/net/ethernet/huawei/hinic/hinic_tx.c | 26 +++++++++++++++----------- 2 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 910fed9..f367dfb 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -468,7 +468,8 @@ static int hinic_poll(struct napi_struct *napi, int budget)
set_bit(HINIC_RESEND_ON, &irq_cfg->intr_flag); rx_pkts += hinic_rx_poll(irq_cfg->rxq, budget - rx_pkts); - if (rx_pkts >= budget) { + tx_pkts += hinic_tx_poll(irq_cfg->txq, budget - tx_pkts); + if (rx_pkts >= budget || tx_pkts >= budget) { clear_bit(HINIC_RESEND_ON, &irq_cfg->intr_flag); return budget; } diff --git a/drivers/net/ethernet/huawei/hinic/hinic_tx.c b/drivers/net/ethernet/huawei/hinic/hinic_tx.c index c8492ae..3d9d9d0 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_tx.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_tx.c @@ -39,6 +39,7 @@ #include "hinic_nic_dev.h" #include "hinic_qp.h" #include "hinic_tx.h" +#include "hinic_dbg.h"
#define MIN_SKB_LEN 32 #define MAX_PAYLOAD_OFFSET 221 @@ -1291,17 +1292,25 @@ void hinic_free_txqs(struct net_device *netdev) /* should stop transmit any packets before calling this function */ #define HINIC_FLUSH_QUEUE_TIMEOUT 1000
+static bool hinic_get_hw_handle_status(void *hwdev, u16 q_id) +{ + u16 sw_pi = 0, hw_ci = 0; + + sw_pi = hinic_dbg_get_sq_pi(hwdev, q_id); + hw_ci = hinic_get_sq_hw_ci(hwdev, q_id); + + return sw_pi == hw_ci; +} + int hinic_stop_sq(struct hinic_txq *txq) { struct hinic_nic_dev *nic_dev = netdev_priv(txq->netdev); unsigned long timeout; - int free_wqebbs, err; + int err;
timeout = msecs_to_jiffies(HINIC_FLUSH_QUEUE_TIMEOUT) + jiffies; do { - free_wqebbs = hinic_get_sq_free_wqebbs(nic_dev->hwdev, - txq->q_id) + 1; - if (free_wqebbs == txq->q_depth) + if (hinic_get_hw_handle_status(nic_dev->hwdev, txq->q_id)) return 0;
usleep_range(900, 1000); @@ -1310,9 +1319,7 @@ int hinic_stop_sq(struct hinic_txq *txq) /* force hardware to drop packets */ timeout = msecs_to_jiffies(HINIC_FLUSH_QUEUE_TIMEOUT) + jiffies; do { - free_wqebbs = hinic_get_sq_free_wqebbs(nic_dev->hwdev, - txq->q_id) + 1; - if (free_wqebbs == txq->q_depth) + if (hinic_get_hw_handle_status(nic_dev->hwdev, txq->q_id)) return 0;
err = hinic_force_drop_tx_pkt(nic_dev->hwdev); @@ -1323,8 +1330,7 @@ int hinic_stop_sq(struct hinic_txq *txq) } while (time_before(jiffies, timeout));
/* Avoid msleep takes too long and get a fake result */ - free_wqebbs = hinic_get_sq_free_wqebbs(nic_dev->hwdev, txq->q_id) + 1; - if (free_wqebbs == txq->q_depth) + if (hinic_get_hw_handle_status(nic_dev->hwdev, txq->q_id)) return 0;
return -EFAULT; @@ -1342,6 +1348,4 @@ void hinic_flush_txqs(struct net_device *netdev) nicif_err(nic_dev, drv, netdev, "Failed to stop sq%d\n", qid); } - - return; } /*lint -e766*/
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
When multiple functions execute probe/remove in parallel, it may cause repeated registration or unregistration of netdevice notifier, resulting in system oops. The driver adds a lock to ensure all registration and unregistration serial processing.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 6 ++++++ 1 file changed, 6 insertions(+)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index f367dfb..46a7800 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -183,6 +183,8 @@ enum hinic_rx_buff_len { int hinic_netdev_event(struct notifier_block *notifier, unsigned long event, void *ptr);
+/* used for netdev notifier register/unregister */ +DEFINE_MUTEX(g_hinic_netdev_notifiers_mutex); static int hinic_netdev_notifiers_ref_cnt; static struct notifier_block hinic_netdev_notifier = { .notifier_call = hinic_netdev_event, @@ -192,6 +194,7 @@ static void hinic_register_notifier(struct hinic_nic_dev *nic_dev) { int err;
+ mutex_lock(&g_hinic_netdev_notifiers_mutex); hinic_netdev_notifiers_ref_cnt++; if (hinic_netdev_notifiers_ref_cnt == 1) { err = register_netdevice_notifier(&hinic_netdev_notifier); @@ -201,15 +204,18 @@ static void hinic_register_notifier(struct hinic_nic_dev *nic_dev) hinic_netdev_notifiers_ref_cnt--; } } + mutex_unlock(&g_hinic_netdev_notifiers_mutex); }
static void hinic_unregister_notifier(struct hinic_nic_dev *nic_dev) { + mutex_lock(&g_hinic_netdev_notifiers_mutex); if (hinic_netdev_notifiers_ref_cnt == 1) unregister_netdevice_notifier(&hinic_netdev_notifier);
if (hinic_netdev_notifiers_ref_cnt) hinic_netdev_notifiers_ref_cnt--; + mutex_unlock(&g_hinic_netdev_notifiers_mutex); }
#define HINIC_MAX_VLAN_DEPTH_OFFLOAD_SUPPORT 2
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
Print the PI/CI information of the tx queue in the tx timeout interface, which is used to debug whether it is a chip problem or a software problem.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 46a7800..55717e8 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -34,6 +34,7 @@ #include "ossl_knl.h" #include "hinic_hw_mgmt.h" #include "hinic_hw.h" +#include "hinic_dbg.h" #include "hinic_nic_cfg.h" #include "hinic_nic_dev.h" #include "hinic_tx.h" @@ -1298,9 +1299,22 @@ static struct net_device_stats *hinic_get_stats(struct net_device *netdev) static void hinic_tx_timeout(struct net_device *netdev) { struct hinic_nic_dev *nic_dev = netdev_priv(netdev); + u8 q_id;
HINIC_NIC_STATS_INC(nic_dev, netdev_tx_timeout); nicif_err(nic_dev, drv, netdev, "Tx timeout\n"); + + for (q_id = 0; q_id < nic_dev->num_qps; q_id++) { + if (!netif_xmit_stopped(netdev_get_tx_queue(netdev, q_id))) + continue; + + nicif_info(nic_dev, drv, netdev, + "txq%d: sw_pi: %d, hw_ci: %d, sw_ci: %d, napi->state: 0x%lx\n", + q_id, hinic_dbg_get_sq_pi(nic_dev->hwdev, q_id), + hinic_get_sq_hw_ci(nic_dev->hwdev, q_id), + hinic_get_sq_local_ci(nic_dev->hwdev, q_id), + nic_dev->irq_cfg[q_id].napi.state); + } }
static int hinic_change_mtu(struct net_device *netdev, int new_mtu)
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
After the user executes the reboot -f command, the kernel restart process is followed. One of the steps is device shutdown. The main process of reboot is stuck in the hns3 NIC shutdown callback process and stuck in the kernel's rtnl lock. The reason why the card is locked in the rtnl is that the system sar, ip, ethtool and other commands are acquiring the information on the network card through the sys fs interface. Rtnl lock is required before accessing the device. When accessing the hinic network card, first lock the rtnl, and then transfer to the hinic callback hinic_get_link_ksettings to get the data. The network card sends a request to the chip through the assembly command and waits for the chip to respond. When the device is shut down, the chip has been shut down and cannot respond. The driver can only wait for a timeout (synchronously wait for 10s), then the rtnl lock will be held for 10 seconds before releasing.
The hinic driver sets the card to the absent state in the shutdown interface, forcing all commands not to be sent to the chip to avoid the command being stuck for a long time.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_cfg.c | 13 +++++++++++++ drivers/net/ethernet/huawei/hinic/hinic_hw.h | 1 + drivers/net/ethernet/huawei/hinic/hinic_hwdev.c | 3 --- drivers/net/ethernet/huawei/hinic/hinic_hwdev.h | 3 +++ drivers/net/ethernet/huawei/hinic/hinic_lld.c | 3 +++ 5 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c index 341637e..7e09634 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c @@ -2409,6 +2409,19 @@ void hinic_free_hwdev(void *hwdev) kfree(dev); }
+void hinic_set_api_stop(void *hwdev) +{ + struct hinic_hwdev *dev = hwdev; + + if (!hwdev) + return; + + dev->chip_present_flag = HINIC_CHIP_ABSENT; + sdk_info(dev->dev_hdl, "Set card absent\n"); + hinic_force_complete_all(dev); + sdk_info(dev->dev_hdl, "All messages interacting with the chip will stop\n"); +} + void hinic_shutdown_hwdev(void *hwdev) { struct hinic_hwdev *dev = hwdev; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw.h b/drivers/net/ethernet/huawei/hinic/hinic_hw.h index d4becb6..6e8a277 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw.h @@ -428,6 +428,7 @@ enum hinic_func_cap { int hinic_set_vf_dev_cap(void *hwdev); void hinic_free_hwdev(void *hwdev); void hinic_shutdown_hwdev(void *hwdev); +void hinic_set_api_stop(void *hwdev);
void hinic_ppf_hwdev_unreg(void *hwdev); void hinic_ppf_hwdev_reg(void *hwdev, void *ppf_hwdev); diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c index 172be6c..7a6b1f6 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c @@ -477,9 +477,6 @@ struct hinic_reg_info {
#define PCIE_MSIX_ATTR_ENTRY 0
-#define HINIC_CHIP_PRESENT 1 -#define HINIC_CHIP_ABSENT 0 - struct hinic_cmd_fault_event { u8 status; u8 version; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h index 2a81867..876bba9 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.h @@ -48,6 +48,9 @@ #define HINIC_MGMT_STATUS_ERR_LEN 32 /* Length too short or too long */ #define HINIC_MGMT_STATUS_ERR_UNSUPPORT 0xFF /* Feature not supported */
+#define HINIC_CHIP_PRESENT 1 +#define HINIC_CHIP_ABSENT 0 + struct cfg_mgmt_info; struct rdma_comp_resource;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c index 3bf47ac..2240a39 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c @@ -2729,6 +2729,9 @@ static void hinic_shutdown(struct pci_dev *pdev) hinic_shutdown_hwdev(pci_adapter->hwdev);
pci_disable_device(pdev); + + if (pci_adapter) + hinic_set_api_stop(pci_adapter->hwdev); }
#ifdef HAVE_RHEL6_SRIOV_CONFIGURE
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
When there are multiple priority packets in a tx queue in 1822, the out-of-sequence of the sent packets will cause data inconsistency. When DCB is enabled and Layer 2 forwarding is configured, when the receiving vlan device is configured with ingress_map, the priority of skb may be mapped to a non-zero value. The hinic driver first selects the queue through skb-> priority, but the priority is fixed to use vlan priority. As a result, there may be multiple priorities for the same tx queue. Therefore, the driver is modified to only select the queue through the VLAN priority.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c index 55717e8..dd67d90 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_main.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c @@ -1193,8 +1193,7 @@ static u16 hinic_select_queue(struct net_device *netdev, struct sk_buff *skb) { struct hinic_nic_dev *nic_dev = netdev_priv(netdev);
- if (skb->vlan_tci && !skb->priority) - skb->priority = skb->vlan_tci >> VLAN_PRIO_SHIFT; + skb->priority = skb->vlan_tci >> VLAN_PRIO_SHIFT;
if (netdev_get_num_tc(netdev) || !nic_dev->rss_hkey_user_be) goto fallback;
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
It is not allowed to send commands to the firmware during the firmware upgrade process, and some commands are not retried during the VF loading process, causing the loading to fail. Troubleshoot and modify commands that have not been retried to ensure that the driver can continue to load after the hot upgrade is complete.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_cfg.c | 20 +++++++++++--------- drivers/net/ethernet/huawei/hinic/hinic_cfg.h | 2 -- drivers/net/ethernet/huawei/hinic/hinic_hwdev.c | 3 ++- 3 files changed, 13 insertions(+), 12 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c index 7e09634..6814902 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_cfg.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_cfg.c @@ -604,16 +604,15 @@ static int get_cap_from_fw(struct hinic_hwdev *dev, enum func_type type)
static int get_cap_from_pf(struct hinic_hwdev *dev, enum func_type type) { - int err; - u16 in_len, out_len; struct hinic_dev_cap dev_cap = {0}; + u16 in_len, out_len; + int err;
in_len = sizeof(dev_cap); out_len = in_len;
- err = hinic_mbox_to_pf(dev, HINIC_MOD_CFGM, HINIC_CFG_MBOX_CAP, - &dev_cap, in_len, &dev_cap, &out_len, - CFG_MAX_CMD_TIMEOUT); + err = hinic_msg_to_mgmt_sync(dev, HINIC_MOD_CFGM, HINIC_CFG_MBOX_CAP, + &dev_cap, in_len, &dev_cap, &out_len, 0); if (err || dev_cap.status || !out_len) { sdk_err(dev->dev_hdl, "Failed to get capability from PF, err: %d, status: 0x%x, out size: 0x%x\n", err, dev_cap.status, out_len); @@ -1346,14 +1345,17 @@ static int cfg_mbx_pf_proc_vf_msg(void *hwdev, u16 vf_id, u8 cmd, void *buf_in, /* fixed qnum in ovs mode */ func_id = vf_id + hinic_glb_pf_vf_offset(hwdev); dev_cap_tmp.func_id = func_id; - err = hinic_msg_to_mgmt_sync(dev, HINIC_MOD_CFGM, HINIC_CFG_FUNC_CAP, - &dev_cap_tmp, sizeof(dev_cap_tmp), - &dev_cap_tmp, &out_len, 0); - if (err || !out_len || dev_cap_tmp.status) { + err = hinic_pf_msg_to_mgmt_sync(dev, HINIC_MOD_CFGM, HINIC_CFG_FUNC_CAP, + &dev_cap_tmp, sizeof(dev_cap_tmp), + &dev_cap_tmp, &out_len, 0); + if (err && err != HINIC_DEV_BUSY_ACTIVE_FW && + err != HINIC_MBOX_PF_BUSY_ACTIVE_FW) { sdk_err(dev->dev_hdl, "Get func_id: %u capability from FW failed, err: %d, status: 0x%x, out_size: 0x%x\n", func_id, err, dev_cap_tmp.status, out_len); return -EFAULT; + } else if (err) { + return err; }
dev_cap->nic_max_sq = dev_cap_tmp.nic_max_sq + 1; diff --git a/drivers/net/ethernet/huawei/hinic/hinic_cfg.h b/drivers/net/ethernet/huawei/hinic/hinic_cfg.h index f6596e9..212a9946 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_cfg.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_cfg.h @@ -18,8 +18,6 @@
#include "hinic_ctx_def.h"
-#define CFG_MAX_CMD_TIMEOUT 1000 /* ms */ - enum { CFG_FREE = 0, CFG_BUSY = 1 diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c index 7a6b1f6..3ae6e21 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c @@ -839,7 +839,8 @@ static int __pf_to_mgmt_pre_handle(struct hinic_hwdev *hwdev, enum hinic_mod_type mod, u8 cmd) { if (hinic_get_mgmt_channel_status(hwdev)) { - if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC) + if (mod == HINIC_MOD_COMM || mod == HINIC_MOD_L2NIC || + mod == HINIC_MOD_CFGM || mod == HINIC_MOD_HILINK) return HINIC_DEV_BUSY_ACTIVE_FW; else return -EBUSY;
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
If create_singlethread_workqueue() fails, we forget unmapping BAR resource.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_lld.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_lld.c b/drivers/net/ethernet/huawei/hinic/hinic_lld.c index 2240a39..2ad6d2d 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_lld.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_lld.c @@ -2658,8 +2658,10 @@ static int hinic_probe(struct pci_dev *pdev, const struct pci_device_id *id)
alloc_chip_node_fail: lld_unlock_chip_node(); - unmapping_bar(pci_adapter); + ceate_nic_delay_work_fail: + unmapping_bar(pci_adapter); + map_bar_failed: hinic_pci_deinit(pdev);
From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
Update hinic version to 2.3.2.14
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Zengweiliang zengweiliang.zengweiliang@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h index e466f12..1e050c3 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_nic_dev.h @@ -30,7 +30,7 @@ #define HINIC_DRV_NAME "hinic" #define HINIC_CHIP_NAME "hinic"
-#define HINIC_DRV_VERSION "2.3.2.11" +#define HINIC_DRV_VERSION "2.3.2.14" struct vf_data_storage;
#define HINIC_FUNC_IS_VF(hwdev) (hinic_func_type(hwdev) == TYPE_VF)