Thread (20 messages) 20 messages, 3 authors, 2026-02-26
STALE112d
Revisions (3)
  1. v02 [diff vs current]
  2. v03 [diff vs current]
  3. v01 current

[PATCH net-next v01 03/15] hinic3: Add chip_present_flag checks to prevent errors when card is absent

From: Fan Gong <gongfan1@huawei.com>
Date: 2026-02-24 13:16:13
Also in: linux-doc, lkml
Subsystem: huawei 3rd gen ethernet driver, networking drivers, the rest · Maintainers: Fan Gong, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds

Co-developed-by: Zhu Yikai <redacted>
Signed-off-by: Zhu Yikai <redacted>
Signed-off-by: Fan Gong <gongfan1@huawei.com>
---
 drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c | 10 +++++++++-
 .../net/ethernet/huawei/hinic3/hinic3_common.h   |  1 +
 .../net/ethernet/huawei/hinic3/hinic3_hw_comm.c  |  7 +++++++
 .../net/ethernet/huawei/hinic3/hinic3_hwdev.c    |  5 +++++
 .../net/ethernet/huawei/hinic3/hinic3_hwdev.h    |  1 +
 drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c | 10 +++++++---
 drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c | 12 ++++++++++++
 .../ethernet/huawei/hinic3/hinic3_netdev_ops.c   | 16 ++++++++++------
 8 files changed, 52 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c b/drivers/net/ethernet/huawei/hinic3/hinic3_cmdq.c
index 928bcd857751..a1189751e2a8 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;
 
@@ -733,6 +734,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");
@@ -762,6 +767,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.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..dc2f236a88b8 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_CPL;
+
 	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 7906d4057cf2..c02a0a4a5771 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 801f48e241f8..e4dd4c717eec 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_hwif.c
@@ -94,12 +94,16 @@ void hinic3_hwif_write_reg(struct hinic3_hwif *hwif, u32 reg, u32 val)
 static enum hinic3_wait_return check_hwif_ready_handler(void *priv_data)
 {
 	struct hinic3_hwdev *hwdev = priv_data;
-	u32 attr1;
+	u32 attr1, status;
 
 	attr1 = hinic3_hwif_read_reg(hwdev->hwif, HINIC3_CSR_FUNC_ATTR1_ADDR);
+	status = !HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS);
+	if (status == HINIC3_PCIE_LINK_DOWN)
+		return HINIC3_WAIT_PROCESS_ERR;
+	else if (!status)
+		return HINIC3_WAIT_PROCESS_CPL;
 
-	return HINIC3_AF1_GET(attr1, MGMT_INIT_STATUS) ?
-	       HINIC3_WAIT_PROCESS_CPL : HINIC3_WAIT_PROCESS_WAITING;
+	return HINIC3_WAIT_PROCESS_WAITING;
 }
 
 static int wait_hwif_ready(struct hinic3_hwdev *hwdev)
diff --git a/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c b/drivers/net/ethernet/huawei/hinic3/hinic3_mbox.c
index 1bfaff9ba253..63cc70bce8b0 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 75adfe897e81..75b6abdf1024 100644
--- a/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
+++ b/drivers/net/ethernet/huawei/hinic3/hinic3_netdev_ops.c
@@ -417,13 +417,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)
-- 
2.43.0
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help