From: Chiqijun chiqijun@huawei.com
driver inclusion category: bugfix bugzilla: 4472
-----------------------------------------------------------------------
The communication between the VF driver and the firmware depends on the AEQ channel. During the hot migration process, interruption may be lost. If the interrupt retransmission is not configured, polling is used, and the AEQ interrupt retransmission is preferentially configured.
Signed-off-by: Chiqijun chiqijun@huawei.com Reviewed-by: Luoshaokai luoshaokai@huawei.com Signed-off-by: Yang Yingliang yangyingliang@huawei.com --- drivers/net/ethernet/huawei/hinic/hinic_hw.h | 3 +- drivers/net/ethernet/huawei/hinic/hinic_hwdev.c | 104 ++++++++++++------------ drivers/net/ethernet/huawei/hinic/hinic_mbox.c | 18 ++-- drivers/net/ethernet/huawei/hinic/hinic_mbox.h | 9 ++ 4 files changed, 78 insertions(+), 56 deletions(-)
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hw.h b/drivers/net/ethernet/huawei/hinic/hinic_hw.h index 0947201..e489a00 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hw.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_hw.h @@ -199,7 +199,8 @@ struct nic_interrupt_info {
int hinic_get_interrupt_cfg(void *hwdev, struct nic_interrupt_info *interrupt_info); - +int hinic_set_interrupt_cfg_direct(void *hwdev, + struct nic_interrupt_info *interrupt_info); int hinic_set_interrupt_cfg(void *hwdev, struct nic_interrupt_info interrupt_info);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c index 8d6675c..101b671 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_hwdev.c @@ -1572,45 +1572,27 @@ int hinic_get_interrupt_cfg(void *hwdev, } EXPORT_SYMBOL(hinic_get_interrupt_cfg);
-int hinic_set_interrupt_cfg(void *hwdev, - struct nic_interrupt_info interrupt_info) +int hinic_set_interrupt_cfg_direct(void *hwdev, + struct nic_interrupt_info *interrupt_info) { struct hinic_hwdev *nic_hwdev = hwdev; struct hinic_msix_config msix_cfg = {0}; - struct nic_interrupt_info temp_info; u16 out_size = sizeof(msix_cfg); int err;
if (!hwdev) return -EINVAL;
- temp_info.msix_index = interrupt_info.msix_index; - - err = hinic_get_interrupt_cfg(hwdev, &temp_info); - if (err) - return -EINVAL; - err = hinic_global_func_id_get(hwdev, &msix_cfg.func_id); if (err) return err;
- msix_cfg.msix_index = (u16)interrupt_info.msix_index; - msix_cfg.lli_credit_cnt = temp_info.lli_credit_limit; - msix_cfg.lli_tmier_cnt = temp_info.lli_timer_cfg; - msix_cfg.pending_cnt = temp_info.pending_limt; - msix_cfg.coalesct_timer_cnt = temp_info.coalesc_timer_cfg; - msix_cfg.resend_timer_cnt = temp_info.resend_timer_cfg; - - if (interrupt_info.lli_set) { - msix_cfg.lli_credit_cnt = interrupt_info.lli_credit_limit; - msix_cfg.lli_tmier_cnt = interrupt_info.lli_timer_cfg; - } - - if (interrupt_info.interrupt_coalesc_set) { - msix_cfg.pending_cnt = interrupt_info.pending_limt; - msix_cfg.coalesct_timer_cnt = interrupt_info.coalesc_timer_cfg; - msix_cfg.resend_timer_cnt = interrupt_info.resend_timer_cfg; - } + msix_cfg.msix_index = (u16)interrupt_info->msix_index; + msix_cfg.lli_credit_cnt = interrupt_info->lli_credit_limit; + msix_cfg.lli_tmier_cnt = interrupt_info->lli_timer_cfg; + msix_cfg.pending_cnt = interrupt_info->pending_limt; + msix_cfg.coalesct_timer_cnt = interrupt_info->coalesc_timer_cfg; + msix_cfg.resend_timer_cnt = interrupt_info->resend_timer_cfg;
err = hinic_msg_to_mgmt_sync(hwdev, HINIC_MOD_COMM, HINIC_MGMT_CMD_MSI_CTRL_REG_WR_BY_UP, @@ -1619,11 +1601,40 @@ int hinic_set_interrupt_cfg(void *hwdev, if (err || !out_size || msix_cfg.status) { sdk_err(nic_hwdev->dev_hdl, "Failed to set interrupt config, err: %d, status: 0x%x, out size: 0x%x\n", err, msix_cfg.status, out_size); - return -EINVAL; + return -EFAULT; }
return 0; } + +int hinic_set_interrupt_cfg(void *hwdev, + struct nic_interrupt_info interrupt_info) +{ + struct nic_interrupt_info temp_info; + int err; + + if (!hwdev) + return -EINVAL; + + temp_info.msix_index = interrupt_info.msix_index; + + err = hinic_get_interrupt_cfg(hwdev, &temp_info); + if (err) + return -EINVAL; + + if (!interrupt_info.lli_set) { + interrupt_info.lli_credit_limit = temp_info.lli_credit_limit; + interrupt_info.lli_timer_cfg = temp_info.lli_timer_cfg; + } + + if (!interrupt_info.interrupt_coalesc_set) { + interrupt_info.pending_limt = temp_info.pending_limt; + interrupt_info.coalesc_timer_cfg = temp_info.coalesc_timer_cfg; + interrupt_info.resend_timer_cfg = temp_info.resend_timer_cfg; + } + + return hinic_set_interrupt_cfg_direct(hwdev, &interrupt_info); +} EXPORT_SYMBOL(hinic_set_interrupt_cfg);
void hinic_misx_intr_clear_resend_bit(void *hwdev, u16 msix_idx, @@ -1650,7 +1661,7 @@ static int init_aeqs_msix_attr(struct hinic_hwdev *hwdev) struct hinic_aeqs *aeqs = hwdev->aeqs; struct nic_interrupt_info info = {0}; struct hinic_eq *eq; - u16 q_id; + int q_id; int err;
info.lli_set = 0; @@ -1659,10 +1670,10 @@ static int init_aeqs_msix_attr(struct hinic_hwdev *hwdev) info.coalesc_timer_cfg = HINIC_DEAULT_EQ_MSIX_COALESC_TIMER_CFG; info.resend_timer_cfg = HINIC_DEAULT_EQ_MSIX_RESEND_TIMER_CFG;
- for (q_id = 0; q_id < aeqs->num_aeqs; q_id++) { + for (q_id = aeqs->num_aeqs - 1; q_id >= 0; q_id--) { eq = &aeqs->aeq[q_id]; info.msix_index = eq->eq_irq.msix_entry_idx; - err = hinic_set_interrupt_cfg(hwdev, info); + err = hinic_set_interrupt_cfg_direct(hwdev, &info); if (err) { sdk_err(hwdev->dev_hdl, "Set msix attr for aeq %d failed\n", q_id); @@ -1670,6 +1681,8 @@ static int init_aeqs_msix_attr(struct hinic_hwdev *hwdev) } }
+ hinic_set_mbox_seg_ack_mod(hwdev, HINIC_MBOX_SEND_MSG_INT); + return 0; }
@@ -2320,24 +2333,6 @@ static int __get_func_misc_info(struct hinic_hwdev *hwdev) return 0; }
-static int __init_eqs_msix_attr(struct hinic_hwdev *hwdev) -{ - int err; - - err = init_aeqs_msix_attr(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init aeqs msix attr\n"); - return err; - } - - err = init_ceqs_msix_attr(hwdev); - if (err) { - sdk_err(hwdev->dev_hdl, "Failed to init ceqs msix attr\n"); - return err; - } - - return 0; -}
/* initialize communication channel */ int hinic_init_comm_ch(struct hinic_hwdev *hwdev) @@ -2375,6 +2370,12 @@ int hinic_init_comm_ch(struct hinic_hwdev *hwdev) goto func_to_func_init_err; }
+ err = init_aeqs_msix_attr(hwdev); + if (err) { + sdk_err(hwdev->dev_hdl, "Failed to init aeqs msix attr\n"); + goto aeqs_msix_attr_init_err; + } + err = __get_func_misc_info(hwdev); if (err) { sdk_err(hwdev->dev_hdl, "Failed to get function msic information\n"); @@ -2406,9 +2407,11 @@ int hinic_init_comm_ch(struct hinic_hwdev *hwdev) goto ceqs_init_err; }
- err = __init_eqs_msix_attr(hwdev); - if (err) + err = init_ceqs_msix_attr(hwdev); + if (err) { + sdk_err(hwdev->dev_hdl, "Failed to init ceqs msix attr\n"); goto init_eqs_msix_err; + }
/* set default wq page_size */ hwdev->wq_page_size = HINIC_DEFAULT_WQ_PAGE_SIZE; @@ -2469,6 +2472,7 @@ int hinic_init_comm_ch(struct hinic_hwdev *hwdev) l2nic_reset_err: rectify_mode_err: get_func_info_err: +aeqs_msix_attr_init_err: func_to_func_init_err: return err;
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mbox.c b/drivers/net/ethernet/huawei/hinic/hinic_mbox.c index ce6aa36..32c27a1 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_mbox.c +++ b/drivers/net/ethernet/huawei/hinic/hinic_mbox.c @@ -173,10 +173,6 @@ enum hinic_hwif_direction_type { HINIC_HWIF_RESPONSE = 1, };
-enum mbox_send_mod { - MBOX_SEND_MSG_INT, -}; - enum mbox_seg_type { NOT_LAST_SEG, LAST_SEG, @@ -1146,7 +1142,8 @@ static int send_mbox_to_func(struct hinic_mbox_func_to_func *func_to_func, }
err = send_mbox_seg(func_to_func, header, dst_func, msg_seg, - seg_len, MBOX_SEND_MSG_INT, msg_info); + seg_len, func_to_func->send_ack_mod, + msg_info); if (err) { sdk_err(hwdev->dev_hdl, "Failed to send mbox seg, seq_id=0x%llx\n", HINIC_MBOX_HEADER_GET(header, SEQID)); @@ -1601,6 +1598,15 @@ int hinic_vf_mbox_random_id_init(struct hinic_hwdev *hwdev) return err; }
+void hinic_set_mbox_seg_ack_mod(struct hinic_hwdev *hwdev, + enum hinic_mbox_send_mod mod) +{ + if (!hwdev || !hwdev->func_to_func) + return; + + hwdev->func_to_func->send_ack_mod = mod; +} + int hinic_func_to_func_init(struct hinic_hwdev *hwdev) { struct hinic_mbox_func_to_func *func_to_func; @@ -1646,6 +1652,8 @@ int hinic_func_to_func_init(struct hinic_hwdev *hwdev)
prepare_send_mbox(func_to_func);
+ func_to_func->send_ack_mod = HINIC_MBOX_SEND_MSG_POLL; + return 0;
alloc_wb_status_err: diff --git a/drivers/net/ethernet/huawei/hinic/hinic_mbox.h b/drivers/net/ethernet/huawei/hinic/hinic_mbox.h index cfb118a..b76b960 100644 --- a/drivers/net/ethernet/huawei/hinic/hinic_mbox.h +++ b/drivers/net/ethernet/huawei/hinic/hinic_mbox.h @@ -101,6 +101,11 @@ enum hinic_mbox_cb_state { HINIC_PPF_TO_PF_MBOX_CB_RUNNIG, };
+enum hinic_mbox_send_mod { + HINIC_MBOX_SEND_MSG_INT, + HINIC_MBOX_SEND_MSG_POLL, +}; + struct hinic_mbox_func_to_func { struct hinic_hwdev *hwdev;
@@ -130,6 +135,7 @@ struct hinic_mbox_func_to_func { u32 *vf_mbx_old_rand_id; u32 *vf_mbx_rand_id; bool support_vf_random; + enum hinic_mbox_send_mod send_ack_mod; };
struct hinic_mbox_work { @@ -229,4 +235,7 @@ int __hinic_mbox_to_vf(void *hwdev, int vf_to_pf_handler(void *handle, u16 vf_id, u8 cmd, void *buf_in, u16 in_size, void *buf_out, u16 *out_size);
+void hinic_set_mbox_seg_ack_mod(struct hinic_hwdev *hwdev, + enum hinic_mbox_send_mod mod); + #endif