]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
hinic3: Add chip_present_flag checks to prevent errors when card is absent
authorFan Gong <gongfan1@huawei.com>
Tue, 10 Mar 2026 01:04:51 +0000 (09:04 +0800)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 12 Mar 2026 11:13:48 +0000 (12:13 +0100)
chip_present_flag is added for driver to prevent errors when card does
not exist. It has been added to multiple critical functions, including
command queue, mailbox and network device operations, ensuring that the
existence of the network card is verified before performing operations.

Co-developed-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Zhu Yikai <zhuyikai1@h-partners.com>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
Link: https://patch.msgid.link/3954f22df125f5e843aaa62953d7506eb66922ac.1773062356.git.zhuyikai1@h-partners.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c
drivers/net/ethernet/huawei/hinic3/hinic3_common.c
drivers/net/ethernet/huawei/hinic3/hinic3_common.h
drivers/net/ethernet/huawei/hinic3/hinic3_hw_comm.c
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.c
drivers/net/ethernet/huawei/hinic3/hinic3_hwdev.h
drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c
drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c

index 946e699cbe1015b3e5e9749e1a3ffd0823b915dc..1b0ba244a68f3a72b75d0b886340db4afaec8ded 100644 (file)
@@ -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;
index fe4778d152cff2b115f126e41b7b5e168a4c93e3..b28576debdc8145784c0533a96baa0bfff4e783d 100644 (file)
@@ -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;
 }
 
index a8fabfae90fb5ddde452799e8eb55986a10b8a78..c892439fa3cd4bf48b6f686d61723d1666a9f0d1 100644 (file)
@@ -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 {
index ecfe6265954e7a1eb604a743b1e47fc4e6e33063..1defd6800790989e915ca4fa5b5182dff1d59893 100644 (file)
@@ -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");
index 0074d0c6dbaf514aff7870861c23d2e348983602..04c0385b3344eac484b2326d2008687eb2ebf06a 100644 (file)
@@ -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)) {
index 9686c2600b4677ed23718dd04bfcbf543571796b..4276ac136464b805e7b466632e4874af50ad9593 100644 (file)
@@ -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 {
index 771883174b3be29cfbbfd81300304484ed417266..70d70556dca6b586321bc520b6cdd9118ed3b57a 100644 (file)
@@ -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;
index 7d31e215b14fb1cd878efd196e9f906dd264694a..c82370cf401ddce23416c910c46200450812f701 100644 (file)
@@ -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,
index cabb8523f246cb9abc6a97489c724c24fd20576f..da73811641a9dea5e0841f15bd44146afed8d1f8 100644 (file)
@@ -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)