Skip to content

Commit 614eaa9

Browse files
Luo bindavem330
authored andcommitted
hinic: fix the bug of clearing event queue
should disable eq irq before freeing it, must clear event queue depth in hw before freeing relevant memory to avoid illegal memory access and update consumer idx to avoid invalid interrupt Signed-off-by: Luo bin <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 9675811 commit 614eaa9

File tree

1 file changed

+17
-7
lines changed

1 file changed

+17
-7
lines changed

drivers/net/ethernet/huawei/hinic/hinic_hw_eqs.c

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,7 @@ static u8 eq_cons_idx_checksum_set(u32 val)
188188
* eq_update_ci - update the HW cons idx of event queue
189189
* @eq: the event queue to update the cons idx for
190190
**/
191-
static void eq_update_ci(struct hinic_eq *eq)
191+
static void eq_update_ci(struct hinic_eq *eq, u32 arm_state)
192192
{
193193
u32 val, addr = EQ_CONS_IDX_REG_ADDR(eq);
194194

@@ -202,7 +202,7 @@ static void eq_update_ci(struct hinic_eq *eq)
202202

203203
val |= HINIC_EQ_CI_SET(eq->cons_idx, IDX) |
204204
HINIC_EQ_CI_SET(eq->wrapped, WRAPPED) |
205-
HINIC_EQ_CI_SET(EQ_ARMED, INT_ARMED);
205+
HINIC_EQ_CI_SET(arm_state, INT_ARMED);
206206

207207
val |= HINIC_EQ_CI_SET(eq_cons_idx_checksum_set(val), XOR_CHKSUM);
208208

@@ -347,7 +347,7 @@ static void eq_irq_handler(void *data)
347347
else if (eq->type == HINIC_CEQ)
348348
ceq_irq_handler(eq);
349349

350-
eq_update_ci(eq);
350+
eq_update_ci(eq, EQ_ARMED);
351351
}
352352

353353
/**
@@ -702,7 +702,7 @@ static int init_eq(struct hinic_eq *eq, struct hinic_hwif *hwif,
702702
}
703703

704704
set_eq_ctrls(eq);
705-
eq_update_ci(eq);
705+
eq_update_ci(eq, EQ_ARMED);
706706

707707
err = alloc_eq_pages(eq);
708708
if (err) {
@@ -752,18 +752,28 @@ static int init_eq(struct hinic_eq *eq, struct hinic_hwif *hwif,
752752
**/
753753
static void remove_eq(struct hinic_eq *eq)
754754
{
755-
struct msix_entry *entry = &eq->msix_entry;
756-
757-
free_irq(entry->vector, eq);
755+
hinic_set_msix_state(eq->hwif, eq->msix_entry.entry,
756+
HINIC_MSIX_DISABLE);
757+
free_irq(eq->msix_entry.vector, eq);
758758

759759
if (eq->type == HINIC_AEQ) {
760760
struct hinic_eq_work *aeq_work = &eq->aeq_work;
761761

762762
cancel_work_sync(&aeq_work->work);
763+
/* clear aeq_len to avoid hw access host memory */
764+
hinic_hwif_write_reg(eq->hwif,
765+
HINIC_CSR_AEQ_CTRL_1_ADDR(eq->q_id), 0);
763766
} else if (eq->type == HINIC_CEQ) {
764767
tasklet_kill(&eq->ceq_tasklet);
768+
/* clear ceq_len to avoid hw access host memory */
769+
hinic_hwif_write_reg(eq->hwif,
770+
HINIC_CSR_CEQ_CTRL_1_ADDR(eq->q_id), 0);
765771
}
766772

773+
/* update cons_idx to avoid invalid interrupt */
774+
eq->cons_idx = hinic_hwif_read_reg(eq->hwif, EQ_PROD_IDX_REG_ADDR(eq));
775+
eq_update_ci(eq, EQ_NOT_ARMED);
776+
767777
free_eq_pages(eq);
768778
}
769779

0 commit comments

Comments
 (0)