diff options
9 files changed, 52 insertions, 8 deletions
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c index 946e699cbe10..1b0ba244a68f 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c @@ -353,7 +353,8 @@ static int wait_cmdqs_enable(struct hinic3_cmdqs *cmdqs) if (cmdqs->status & HINIC3_CMDQ_ENABLE) return 0; usleep_range(1000, 2000); - } while (time_before(jiffies, end) && !cmdqs->disable_flag); + } while (time_before(jiffies, end) && !cmdqs->disable_flag && + cmdqs->hwdev->chip_present_flag); cmdqs->disable_flag = 1; @@ -681,6 +682,10 @@ int hinic3_cmdq_direct_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, { struct hinic3_cmdqs *cmdqs; int err; + + if (!hwdev->chip_present_flag) + return -ETIMEDOUT; + err = cmdq_params_valid(hwdev, buf_in); if (err) { dev_err(hwdev->dev, "Invalid CMDQ parameters\n"); @@ -712,6 +717,9 @@ int hinic3_cmdq_detail_resp(struct hinic3_hwdev *hwdev, u8 mod, u8 cmd, struct hinic3_cmdqs *cmdqs; int err; + if (!hwdev->chip_present_flag) + return -ETIMEDOUT; + err = cmdq_params_valid(hwdev, buf_in); if (err) goto err_out; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.c b/drivers/net/ethernet/huawei/hinic3/hinic3_common.c index fe4778d152cf..b28576debdc8 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_common.c @@ -59,10 +59,14 @@ int hinic3_wait_for_timeout(void *priv_data, wait_cpl_handler handler, enum hinic3_wait_return ret; int err; - err = read_poll_timeout(handler, ret, ret == HINIC3_WAIT_PROCESS_CPL, + err = read_poll_timeout(handler, ret, + !(ret & HINIC3_WAIT_PROCESS_WAITING), wait_once_us, wait_total_ms * USEC_PER_MSEC, false, priv_data); + if (ret == HINIC3_WAIT_PROCESS_ERR) + return -EIO; + return err; } diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h index a8fabfae90fb..c892439fa3cd 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_common.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_common.h @@ -21,6 +21,7 @@ struct hinic3_dma_addr_align { enum hinic3_wait_return { HINIC3_WAIT_PROCESS_CPL = 0, HINIC3_WAIT_PROCESS_WAITING = 1, + HINIC3_WAIT_PROCESS_ERR = 2, }; struct hinic3_sge { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c index ecfe6265954e..1defd6800790 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c @@ -300,6 +300,10 @@ static enum hinic3_wait_return check_cmdq_stop_handler(void *priv_data) enum hinic3_cmdq_type cmdq_type; struct hinic3_cmdqs *cmdqs; + /* Stop waiting when card unpresent */ + if (!hwdev->chip_present_flag) + return HINIC3_WAIT_PROCESS_ERR; + cmdqs = hwdev->cmdqs; for (cmdq_type = 0; cmdq_type < cmdqs->cmdq_num; cmdq_type++) { if (!hinic3_cmdq_idle(&cmdqs->cmdq[cmdq_type])) @@ -347,6 +351,9 @@ int hinic3_func_rx_tx_flush(struct hinic3_hwdev *hwdev) int ret = 0; int err; + if (!hwdev->chip_present_flag) + return 0; + err = wait_cmdq_stop(hwdev); if (err) { dev_warn(hwdev->dev, "CMDQ is still working, CMDQ timeout value is unreasonable\n"); diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c index 0074d0c6dbaf..04c0385b3344 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c @@ -32,6 +32,9 @@ #define HINIC3_PCIE_PH_DISABLE 0 #define HINIC3_PCIE_MSIX_ATTR_ENTRY 0 +#define HINIC3_CHIP_PRESENT 1 +#define HINIC3_CHIP_ABSENT 0 + #define HINIC3_DEFAULT_EQ_MSIX_PENDING_LIMIT 0 #define HINIC3_DEFAULT_EQ_MSIX_COALESC_TIMER_CFG 0xFF #define HINIC3_DEFAULT_EQ_MSIX_RESEND_TIMER_CFG 7 @@ -545,6 +548,7 @@ int hinic3_init_hwdev(struct pci_dev *pdev) dev_err(hwdev->dev, "Failed to init hwif\n"); goto err_free_hwdev; } + hwdev->chip_present_flag = HINIC3_CHIP_PRESENT; hwdev->workq = alloc_workqueue(HINIC3_HWDEV_WQ_NAME, WQ_MEM_RECLAIM | WQ_PERCPU, HINIC3_WQ_MAX_REQ); @@ -621,6 +625,7 @@ void hinic3_set_api_stop(struct hinic3_hwdev *hwdev) struct hinic3_recv_msg *recv_resp_msg; struct hinic3_mbox *mbox; + hwdev->chip_present_flag = HINIC3_CHIP_ABSENT; spin_lock_bh(&hwdev->channel_lock); if (HINIC3_IS_PF(hwdev) && test_bit(HINIC3_HWDEV_MGMT_INITED, &hwdev->func_state)) { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h index 9686c2600b46..4276ac136464 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h @@ -76,6 +76,7 @@ struct hinic3_hwdev { u32 wq_page_size; u8 max_cmdq; ulong func_state; + int chip_present_flag; }; struct hinic3_event_info { diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c index 771883174b3b..70d70556dca6 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c @@ -97,6 +97,8 @@ static enum hinic3_wait_return check_hwif_ready_handler(void *priv_data) u32 attr1; attr1 = hinic3_hwif_read_reg(hwdev->hwif, HINIC3_CSR_FUNC_ATTR1_ADDR); + if (attr1 == HINIC3_PCIE_LINK_DOWN) + return HINIC3_WAIT_PROCESS_ERR; return HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS) ? HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c index 7d31e215b14f..c82370cf401d 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c @@ -646,6 +646,9 @@ static enum hinic3_wait_return check_mbox_wb_status(void *priv_data) struct hinic3_mbox *mbox = priv_data; u16 wb_status; + if (!mbox->hwdev->chip_present_flag) + return HINIC3_WAIT_PROCESS_ERR; + wb_status = get_mbox_status(&mbox->send_mbox); return MBOX_STATUS_FINISHED(wb_status) ? @@ -788,6 +791,9 @@ static enum hinic3_wait_return check_mbox_msg_finish(void *priv_data) { struct hinic3_mbox *mbox = priv_data; + if (!mbox->hwdev->chip_present_flag) + return HINIC3_WAIT_PROCESS_ERR; + return (mbox->event_flag == MBOX_EVENT_SUCCESS) ? HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING; } @@ -819,6 +825,9 @@ int hinic3_send_mbox_to_mgmt(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd, u32 msg_len; int err; + if (!hwdev->chip_present_flag) + return -EPERM; + /* expect response message */ msg_desc = get_mbox_msg_desc(mbox, MBOX_MSG_RESP, MBOX_MGMT_FUNC_ID); mutex_lock(&mbox->mbox_send_lock); @@ -897,6 +906,9 @@ int hinic3_send_mbox_to_mgmt_no_ack(struct hinic3_hwdev *hwdev, u8 mod, u16 cmd, struct mbox_msg_info msg_info = {}; int err; + if (!hwdev->chip_present_flag) + return -EPERM; + mutex_lock(&mbox->mbox_send_lock); err = send_mbox_msg(mbox, mod, cmd, msg_params->buf_in, msg_params->in_size, MBOX_MGMT_FUNC_ID, diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c index cabb8523f246..da73811641a9 100644 --- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c +++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c @@ -415,13 +415,17 @@ static void hinic3_vport_down(struct net_device *netdev) netif_carrier_off(netdev); netif_tx_disable(netdev); - glb_func_id = hinic3_global_func_id(nic_dev->hwdev); - hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); + if (nic_dev->hwdev->chip_present_flag) { + hinic3_maybe_set_port_state(netdev, false); - hinic3_flush_txqs(netdev); - /* wait to guarantee that no packets will be sent to host */ - msleep(100); - hinic3_flush_qps_res(nic_dev->hwdev); + glb_func_id = hinic3_global_func_id(nic_dev->hwdev); + hinic3_set_vport_enable(nic_dev->hwdev, glb_func_id, false); + + hinic3_flush_txqs(netdev); + /* wait to guarantee that no packets will be sent to host */ + msleep(100); + hinic3_flush_qps_res(nic_dev->hwdev); + } } static int hinic3_open(struct net_device *netdev) |
