Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ed6f9dc6 authored by Vladimir Kondratiev's avatar Vladimir Kondratiev Committed by John W. Linville
Browse files

wil6210: fw error recovery



upon fw error interrupt - in STA mode, disconnect/cancel scan and
then reset FW/HW
added module param - no_fw_recovery which is false by default

Signed-off-by: default avatarVladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 0fef1818
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -265,6 +265,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
		u16 chnl[4];
	} __packed cmd;
	uint i, n;
	int rc;

	if (wil->scan_request) {
		wil_err(wil, "Already scanning\n");
@@ -305,8 +306,13 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
			     request->channels[i]->center_freq);
	}

	return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
	rc = wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
			cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));

	if (rc)
		wil->scan_request = NULL;

	return rc;
}

static int wil_cfg80211_connect(struct wiphy *wiphy,
+1 −0
Original line number Diff line number Diff line
@@ -328,6 +328,7 @@ static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
	if (isr & ISR_MISC_FW_ERROR) {
		wil_notify_fw_error(wil);
		isr &= ~ISR_MISC_FW_ERROR;
		wil_fw_error_recovery(wil);
	}

	if (isr & ISR_MISC_MBOX_EVT) {
+48 −0
Original line number Diff line number Diff line
@@ -21,6 +21,10 @@
#include "wil6210.h"
#include "txrx.h"

static bool no_fw_recovery;
module_param(no_fw_recovery, bool, S_IRUGO | S_IWUSR);
MODULE_PARM_DESC(no_fw_recovery, " disable FW error recovery");

/*
 * Due to a hardware issue,
 * one has to read/write to/from NIC in 32-bit chunks;
@@ -144,6 +148,36 @@ static void wil_connect_timer_fn(ulong x)
	schedule_work(&wil->disconnect_worker);
}

static void wil_fw_error_worker(struct work_struct *work)
{
	struct wil6210_priv *wil = container_of(work,
			struct wil6210_priv, fw_error_worker);
	struct wireless_dev *wdev = wil->wdev;

	wil_dbg_misc(wil, "fw error worker\n");

	if (no_fw_recovery)
		return;

	switch (wdev->iftype) {
	case NL80211_IFTYPE_STATION:
	case NL80211_IFTYPE_P2P_CLIENT:
	case NL80211_IFTYPE_MONITOR:
		wil_info(wil, "fw error recovery started...\n");
		wil_reset(wil);

		/* need to re-allocate Rx ring after reset */
		wil_rx_init(wil);
		break;
	case NL80211_IFTYPE_AP:
	case NL80211_IFTYPE_P2P_GO:
		/* recovery in these modes is done by upper layers */
		break;
	default:
		break;
	}
}

static int wil_find_free_vring(struct wil6210_priv *wil)
{
	int i;
@@ -196,6 +230,7 @@ int wil_priv_init(struct wil6210_priv *wil)
	INIT_WORK(&wil->connect_worker, wil_connect_worker);
	INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
	INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
	INIT_WORK(&wil->fw_error_worker, wil_fw_error_worker);

	INIT_LIST_HEAD(&wil->pending_wmi_ev);
	spin_lock_init(&wil->wmi_ev_lock);
@@ -222,6 +257,7 @@ void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
void wil_priv_deinit(struct wil6210_priv *wil)
{
	cancel_work_sync(&wil->disconnect_worker);
	cancel_work_sync(&wil->fw_error_worker);
	wil6210_disconnect(wil, NULL);
	wmi_event_flush(wil);
	destroy_workqueue(wil->wmi_wq_conn);
@@ -335,6 +371,13 @@ int wil_reset(struct wil6210_priv *wil)
		napi_synchronize(&wil->napi_tx);
	}

	if (wil->scan_request) {
		wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
			     wil->scan_request);
		cfg80211_scan_done(wil->scan_request, true);
		wil->scan_request = NULL;
	}

	cancel_work_sync(&wil->disconnect_worker);
	wil6210_disconnect(wil, NULL);

@@ -363,6 +406,11 @@ int wil_reset(struct wil6210_priv *wil)
	return rc;
}

void wil_fw_error_recovery(struct wil6210_priv *wil)
{
	wil_dbg_misc(wil, "starting fw error recovery\n");
	schedule_work(&wil->fw_error_worker);
}

void wil_link_on(struct wil6210_priv *wil)
{
+2 −0
Original line number Diff line number Diff line
@@ -370,6 +370,7 @@ struct wil6210_priv {
	struct workqueue_struct *wmi_wq_conn; /* for connect worker */
	struct work_struct connect_worker;
	struct work_struct disconnect_worker;
	struct work_struct fw_error_worker;	/* for FW error recovery */
	struct timer_list connect_timer;
	int pending_connect_cid;
	struct list_head pending_wmi_ev;
@@ -447,6 +448,7 @@ void wil_if_remove(struct wil6210_priv *wil);
int wil_priv_init(struct wil6210_priv *wil);
void wil_priv_deinit(struct wil6210_priv *wil);
int wil_reset(struct wil6210_priv *wil);
void wil_fw_error_recovery(struct wil6210_priv *wil);
void wil_link_on(struct wil6210_priv *wil);
void wil_link_off(struct wil6210_priv *wil);
int wil_up(struct wil6210_priv *wil);