driver inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I98HQV
--------------------------------------------------------------------------
Currently, the driver notifies user mode whether a reset has occurred through setting a shared variable to non-zero value. However, if the user fails to obtain this variable in time, the notification will be lost because this variable will be clear after completes the reset.
This patch adds a new reset variable to ensure that the user mode can obtain whether the driver has been reset at any time. A non-zero value will be assigned to this variable, which will permanently become 0 once a reset occurs. During reset, the driver will assign 0 to this variable. After reset, this variable will be remapped to a page of all zeros. The userspace driver can judge whether the driver has been reset by whether this variable is 0.
Fixes: e8b1fec497a0 ("RDMA/hns: Kernel notify usr space to stop ring db") Signed-off-by: Chengchang Tang tangchengchang@huawei.com --- drivers/infiniband/hw/hns/hns_roce_hw_v2.c | 6 ++++++ drivers/infiniband/hw/hns/hns_roce_hw_v2.h | 1 + 2 files changed, 7 insertions(+)
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index 4936ba287..57ded25df 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -2609,6 +2609,8 @@ static void free_dip_list(struct hns_roce_dev *hr_dev)
static int hns_roce_v2_get_reset_page(struct hns_roce_dev *hr_dev) { + struct hns_roce_v2_reset_state *state; + hr_dev->reset_page = alloc_page(GFP_KERNEL | __GFP_ZERO); if (!hr_dev->reset_page) return -ENOMEM; @@ -2617,6 +2619,9 @@ static int hns_roce_v2_get_reset_page(struct hns_roce_dev *hr_dev) if (!hr_dev->reset_kaddr) goto err_with_vmap;
+ state = hr_dev->reset_kaddr; + state->hw_ready = ~state->hw_ready; + return 0;
err_with_vmap: @@ -7210,6 +7215,7 @@ static void hns_roce_v2_reset_notify_user(struct hns_roce_dev *hr_dev) state = (struct hns_roce_v2_reset_state *)hr_dev->reset_kaddr;
state->reset_state = HNS_ROCE_IS_RESETTING; + state->hw_ready = 0; /* Ensure reset state was flushed in memory */ wmb(); } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h index 81a21d96e..2b4a1f788 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.h +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.h @@ -1315,6 +1315,7 @@ struct hns_roce_link_table {
struct hns_roce_v2_reset_state { u32 reset_state; /* stored to use in user space */ + u32 hw_ready; };
struct hns_roce_v2_free_mr {