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

Commit 78abd320 authored by Juuso Oikarinen's avatar Juuso Oikarinen Committed by Luciano Coelho
Browse files

wl1271: Add handling for failing hardware scan command



Currently, the driver does not handle a failing hardware command to scan in
any way - effectively, the scan machine will jam until the driver is shut down,
and future scan requests will just return -EBUSY to user space, resulting in
a type of busy-loop. The same problem occurs if the firmware fails to deliver
the scan completion event - add timeout for this.

Signed-off-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: default avatarTeemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
parent 52b0e7a6
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -296,6 +296,7 @@ struct wl1271_rx_mem_pool_addr {
struct wl1271_scan {
	struct cfg80211_scan_request *req;
	bool *scanned_ch;
	bool failed;
	u8 state;
	u8 ssid[IW_ESSID_MAX_SIZE+1];
	size_t ssid_len;
@@ -419,7 +420,7 @@ struct wl1271 {

	/* Are we currently scanning */
	struct wl1271_scan scan;
	struct work_struct scan_complete_work;
	struct delayed_work scan_complete_work;

	/* Our association ID */
	u16 aid;
+2 −2
Original line number Diff line number Diff line
@@ -657,8 +657,8 @@ static int wl1271_setup(struct wl1271 *wl)

	INIT_WORK(&wl->irq_work, wl1271_irq_work);
	INIT_WORK(&wl->tx_work, wl1271_tx_work);
	INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);

	return 0;
}
@@ -1013,7 +1013,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)

	mutex_unlock(&wl->mutex);

	cancel_work_sync(&wl->scan_complete_work);
	cancel_delayed_work_sync(&wl->scan_complete_work);
	cancel_work_sync(&wl->irq_work);
	cancel_work_sync(&wl->tx_work);
	cancel_delayed_work_sync(&wl->pspoll_work);
+26 −4
Original line number Diff line number Diff line
@@ -30,8 +30,11 @@

void wl1271_scan_complete_work(struct work_struct *work)
{
	struct wl1271 *wl =
		container_of(work, struct wl1271, scan_complete_work);
	struct delayed_work *dwork;
	struct wl1271 *wl;

	dwork = container_of(work, struct delayed_work, work);
	wl = container_of(dwork, struct wl1271, scan_complete_work);

	wl1271_debug(DEBUG_SCAN, "Scanning complete");

@@ -48,6 +51,11 @@ void wl1271_scan_complete_work(struct work_struct *work)
	mutex_unlock(&wl->mutex);

	ieee80211_scan_completed(wl->hw, false);

	if (wl->scan.failed) {
		wl1271_info("Scan completed due to error.");
		ieee80211_queue_work(wl->hw, &wl->recovery_work);
	}
}


@@ -191,7 +199,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,

void wl1271_scan_stm(struct wl1271 *wl)
{
	int ret;
	int ret = 0;

	switch (wl->scan.state) {
	case WL1271_SCAN_STATE_IDLE:
@@ -241,13 +249,22 @@ void wl1271_scan_stm(struct wl1271 *wl)
		break;

	case WL1271_SCAN_STATE_DONE:
		ieee80211_queue_work(wl->hw, &wl->scan_complete_work);
		wl->scan.failed = false;
		cancel_delayed_work(&wl->scan_complete_work);
		ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
					     msecs_to_jiffies(0));
		break;

	default:
		wl1271_error("invalid scan state");
		break;
	}

	if (ret < 0) {
		cancel_delayed_work(&wl->scan_complete_work);
		ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
					     msecs_to_jiffies(0));
	}
}

int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
@@ -270,6 +287,11 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
	wl->scan.scanned_ch = kzalloc(req->n_channels *
				      sizeof(*wl->scan.scanned_ch),
				      GFP_KERNEL);
	/* we assume failure so that timeout scenarios are handled correctly */
	wl->scan.failed = true;
	ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
				     msecs_to_jiffies(WL1271_SCAN_TIMEOUT));

	wl1271_scan_stm(wl);

	return 0;
+2 −0
Original line number Diff line number Diff line
@@ -46,6 +46,8 @@ void wl1271_scan_complete_work(struct work_struct *work);
#define WL1271_SCAN_BAND_5_GHZ 1
#define WL1271_SCAN_PROBE_REQS 3

#define WL1271_SCAN_TIMEOUT    10000 /* msec */

enum {
	WL1271_SCAN_STATE_IDLE,
	WL1271_SCAN_STATE_2GHZ_ACTIVE,