diff mbox series

[23/38] ra6w: add recovery.c

Message ID 20250417135236.52410-24-oleksandr.savchenko.dn@bp.renesas.com
State New
Headers show
Series wireless: ra6w driver for Renesas IEEE 802.11ax devices | expand

Commit Message

Alexander Savchenko April 17, 2025, 1:52 p.m. UTC
Part of the split. Please, take a look at the cover letter for more details

Reviewed-by: Viktor Barna <viktor.barna.rj@bp.renesas.com>
Reviewed-by: Gal Gur <gal.gur.jx@renesas.com>
Signed-off-by: Alexander Savchenko <oleksandr.savchenko.dn@bp.renesas.com>
---
 drivers/net/wireless/renesas/ra6w/recovery.c | 87 ++++++++++++++++++++
 1 file changed, 87 insertions(+)
 create mode 100644 drivers/net/wireless/renesas/ra6w/recovery.c
diff mbox series

Patch

diff --git a/drivers/net/wireless/renesas/ra6w/recovery.c b/drivers/net/wireless/renesas/ra6w/recovery.c
new file mode 100644
index 000000000000..5fc9a8cf42e5
--- /dev/null
+++ b/drivers/net/wireless/renesas/ra6w/recovery.c
@@ -0,0 +1,87 @@ 
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * This file contains recovery handler.
+ *
+ * Copyright (C) [2022-2025] Renesas Electronics Corporation and/or its affiliates.
+ */
+
+#include "core.h"
+#include "if.h"
+#include "params.h"
+#include "dbg.h"
+#include "recovery.h"
+
+#define RA6W_RECOVERY_WQ_NAME	"ra6w_recovery_wq"
+
+static bool ra6w_recovery_reprobe;
+
+void ra6w_recovery_reprobe_set(bool set)
+{
+	ra6w_recovery_reprobe = set;
+}
+
+bool ra6w_recovery_reprobe_get(void)
+{
+	return ra6w_recovery_reprobe;
+}
+
+void ra6w_recovery_event_post(struct ra6w_recovery *recovery)
+{
+	struct ra6w_core *core = container_of(recovery, struct ra6w_core, recovery);
+
+	if (!recovery->wq)
+		return;
+
+	if (recovery->in_recovery)
+		return;
+
+	ra6w_ctrl_dev_hw_reset(&core->ctrl);
+	recovery->in_recovery = true;
+
+	queue_work(recovery->wq, &recovery->work);
+}
+
+static void ra6w_recovery_process(struct ra6w_recovery *recovery)
+{
+	struct ra6w_core *core = container_of(recovery, struct ra6w_core, recovery);
+	struct ra6w_if *ifp = container_of(core, struct ra6w_if, core);
+
+	ra6w_info("recovery start\n");
+
+	ra6w_sdio_reprobe(ifp->dev.func);
+
+	ra6w_recovery_reprobe_set(true);
+}
+
+static void ra6w_recovery_handler(struct work_struct *work)
+{
+	struct ra6w_recovery *recovery = container_of(work, struct ra6w_recovery, work);
+
+	ra6w_recovery_process(recovery);
+}
+
+int ra6w_recovery_init(struct ra6w_recovery *recovery)
+{
+	struct workqueue_struct *wq;
+
+	wq = create_singlethread_workqueue(RA6W_RECOVERY_WQ_NAME);
+	if (!wq) {
+		ra6w_err("[%s] create workqueue %s failed\n", __func__, RA6W_RECOVERY_WQ_NAME);
+		return -ENOENT;
+	}
+
+	INIT_WORK(&recovery->work, ra6w_recovery_handler);
+	recovery->wq = wq;
+
+	return 0;
+}
+
+void ra6w_recovery_deinit(struct ra6w_recovery *recovery)
+{
+	cancel_work_sync(&recovery->work);
+
+	if (recovery->wq)
+		destroy_workqueue(recovery->wq);
+
+	recovery->wq = NULL;
+}