hinic3: Add chip_present_flag checks to prevent errors when card is absent

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>
This commit is contained in:
Fan Gong 2026-03-10 09:04:51 +08:00 committed by Paolo Abeni
parent 678c5b3b6b
commit d69ee992fb
9 changed files with 52 additions and 8 deletions

View 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;

View 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;
}

View 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 {

View 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");

View 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)) {

View 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 {

View 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;

View 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,

View 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)