summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c18
1 files changed, 17 insertions, 1 deletions
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 45a7520491a6..591fb4191d90 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -3987,7 +3987,8 @@ static void mana_rdma_service_handle(struct work_struct *work)
struct device *dev = gd->gdma_context->dev;
int ret;
- if (READ_ONCE(gd->rdma_teardown))
+ /* Pairs with the smp_store_release() in mana_rdma_probe(). */
+ if (smp_load_acquire(&gd->rdma_teardown))
goto out;
switch (serv_work->event) {
@@ -4283,6 +4284,21 @@ int mana_rdma_probe(struct gdma_dev *gd)
if (err)
return err;
+ /* Clear the state left by a previous mana_rdma_remove() so servicing
+ * events are handled again after a reset cycle.
+ */
+ gd->is_suspended = false;
+
+ /* Publish is_suspended before re-opening the gate, so the handler
+ * cannot observe an open gate with a stale is_suspended. Pairs
+ * with the smp_load_acquire() in mana_rdma_service_handle(). This
+ * matters on the reset path, where mana_rdma_remove() closed the
+ * gate and drained the workqueue; on the initial probe path the
+ * gate was never closed and both flags are already clear. It does
+ * not order gd->adev, which add_adev() publishes below.
+ */
+ smp_store_release(&gd->rdma_teardown, false);
+
err = add_adev(gd, "rdma");
if (err)
mana_gd_deregister_device(gd);