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

Commit f47e2000 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "wil6210: protect synchronous wmi commands handling"

parents 036be762 645dc2b1
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -535,7 +535,18 @@ static int wil_cfg80211_disconnect(struct wiphy *wiphy,

	wil_dbg_misc(wil, "%s(reason=%d)\n", __func__, reason_code);

	rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
	if (!(test_bit(wil_status_fwconnecting, wil->status) ||
	      test_bit(wil_status_fwconnected, wil->status))) {
		wil_err(wil, "%s: Disconnect was called while disconnected\n",
			__func__);
		return 0;
	}

	rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
		      WMI_DISCONNECT_EVENTID, NULL, 0,
		      WIL6210_DISCONNECT_TO_MS);
	if (rc)
		wil_err(wil, "%s: disconnect error %d\n", __func__, rc);

	return rc;
}
+12 −19
Original line number Diff line number Diff line
@@ -23,9 +23,6 @@
#include "wmi.h"
#include "boot_loader.h"

#define WAIT_FOR_DISCONNECT_TIMEOUT_MS 2000
#define WAIT_FOR_DISCONNECT_INTERVAL_MS 10

bool debug_fw; /* = false; */
module_param(debug_fw, bool, S_IRUGO);
MODULE_PARM_DESC(debug_fw, " do not perform card reset. For FW debug");
@@ -438,6 +435,9 @@ int wil_priv_init(struct wil6210_priv *wil)
	for (i = 0; i < WIL6210_MAX_CID; i++)
		spin_lock_init(&wil->sta[i].tid_rx_lock);

	for (i = 0; i < WIL6210_MAX_TX_RINGS; i++)
		spin_lock_init(&wil->vring_tx_data[i].lock);

	mutex_init(&wil->mutex);
	mutex_init(&wil->wmi_mutex);
	mutex_init(&wil->back_rx_mutex);
@@ -939,8 +939,7 @@ int wil_up(struct wil6210_priv *wil)

int __wil_down(struct wil6210_priv *wil)
{
	int iter = WAIT_FOR_DISCONNECT_TIMEOUT_MS /
			WAIT_FOR_DISCONNECT_INTERVAL_MS;
	int rc;

	WARN_ON(!mutex_is_locked(&wil->mutex));

@@ -964,22 +963,16 @@ int __wil_down(struct wil6210_priv *wil)
	}

	if (test_bit(wil_status_fwconnected, wil->status) ||
	    test_bit(wil_status_fwconnecting, wil->status))
		wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
	    test_bit(wil_status_fwconnecting, wil->status)) {

	/* make sure wil is idle (not connected) */
		mutex_unlock(&wil->mutex);
	while (iter--) {
		int idle = !test_bit(wil_status_fwconnected, wil->status) &&
			   !test_bit(wil_status_fwconnecting, wil->status);
		if (idle)
			break;
		msleep(WAIT_FOR_DISCONNECT_INTERVAL_MS);
	}
		rc = wmi_call(wil, WMI_DISCONNECT_CMDID, NULL, 0,
			      WMI_DISCONNECT_EVENTID, NULL, 0,
			      WIL6210_DISCONNECT_TO_MS);
		mutex_lock(&wil->mutex);

	if (iter < 0)
		wil_err(wil, "timeout waiting for idle FW/HW\n");
		if (rc)
			wil_err(wil, "timeout waiting for disconnect\n");
	}

	wil_reset(wil, false);

+21 −5
Original line number Diff line number Diff line
@@ -717,6 +717,21 @@ void wil_rx_fini(struct wil6210_priv *wil)
		wil_vring_free(wil, vring, 0);
}

static inline void wil_tx_data_init(struct vring_tx_data *txdata)
{
	spin_lock_bh(&txdata->lock);
	txdata->dot1x_open = 0;
	txdata->enabled = 0;
	txdata->idle = 0;
	txdata->last_idle = 0;
	txdata->begin = 0;
	txdata->agg_wsize = 0;
	txdata->agg_timeout = 0;
	txdata->agg_amsdu = 0;
	txdata->addba_in_progress = false;
	spin_unlock_bh(&txdata->lock);
}

int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
		      int cid, int tid)
{
@@ -758,8 +773,7 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
		goto out;
	}

	memset(txdata, 0, sizeof(*txdata));
	spin_lock_init(&txdata->lock);
	wil_tx_data_init(txdata);
	vring->size = size;
	rc = wil_vring_alloc(wil, vring);
	if (rc)
@@ -791,8 +805,10 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,

	return 0;
 out_free:
	spin_lock_bh(&txdata->lock);
	txdata->dot1x_open = false;
	txdata->enabled = 0;
	spin_unlock_bh(&txdata->lock);
	wil_vring_free(wil, vring, 1);
	wil->vring2cid_tid[id][0] = WIL6210_MAX_CID;
	wil->vring2cid_tid[id][1] = 0;
@@ -834,8 +850,7 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)
		goto out;
	}

	memset(txdata, 0, sizeof(*txdata));
	spin_lock_init(&txdata->lock);
	wil_tx_data_init(txdata);
	vring->size = size;
	rc = wil_vring_alloc(wil, vring);
	if (rc)
@@ -865,8 +880,10 @@ int wil_vring_init_bcast(struct wil6210_priv *wil, int id, int size)

	return 0;
 out_free:
	spin_lock_bh(&txdata->lock);
	txdata->enabled = 0;
	txdata->dot1x_open = false;
	spin_unlock_bh(&txdata->lock);
	wil_vring_free(wil, vring, 1);
 out:

@@ -894,7 +911,6 @@ void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
		napi_synchronize(&wil->napi_tx);

	wil_vring_free(wil, vring, 1);
	memset(txdata, 0, sizeof(*txdata));
}

static struct vring *wil_find_tx_ucast(struct wil6210_priv *wil,
+1 −0
Original line number Diff line number Diff line
@@ -92,6 +92,7 @@ static inline u32 wil_mtu2macbuf(u32 mtu)
#define WIL6210_FW_RECOVERY_RETRIES	(5) /* try to recover this many times */
#define WIL6210_FW_RECOVERY_TO	msecs_to_jiffies(5000)
#define WIL6210_SCAN_TO		msecs_to_jiffies(10000)
#define WIL6210_DISCONNECT_TO_MS (2000)
#define WIL6210_RX_HIGH_TRSH_INIT		(0)
#define WIL6210_RX_HIGH_TRSH_DEFAULT \
				(1 << (WIL_RX_RING_SIZE_ORDER_DEFAULT - 3))
+13 −4
Original line number Diff line number Diff line
@@ -839,6 +839,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
			struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
			u16 id = le16_to_cpu(wmi->id);
			u32 tstamp = le32_to_cpu(wmi->timestamp);
			spin_lock_irqsave(&wil->wmi_ev_lock, flags);
			if (wil->reply_id && wil->reply_id == id) {
				if (wil->reply_buf) {
					memcpy(wil->reply_buf, wmi,
@@ -846,6 +847,7 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
					immed_reply = true;
				}
			}
			spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);

			wil_dbg_wmi(wil, "WMI event 0x%04x MID %d @%d msec\n",
				    id, wmi->mid, tstamp);
@@ -889,13 +891,16 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,

	mutex_lock(&wil->wmi_mutex);

	spin_lock(&wil->wmi_ev_lock);
	wil->reply_id = reply_id;
	wil->reply_buf = reply;
	wil->reply_size = reply_size;
	spin_unlock(&wil->wmi_ev_lock);

	rc = __wmi_send(wil, cmdid, buf, len);
	if (rc)
		goto out;

	wil->reply_id = reply_id;
	wil->reply_buf = reply;
	wil->reply_size = reply_size;
	remain = wait_for_completion_timeout(&wil->wmi_call,
					     msecs_to_jiffies(to_msec));
	if (0 == remain) {
@@ -908,10 +913,14 @@ int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
			    cmdid, reply_id,
			    to_msec - jiffies_to_msecs(remain));
	}

out:
	spin_lock(&wil->wmi_ev_lock);
	wil->reply_id = 0;
	wil->reply_buf = NULL;
	wil->reply_size = 0;
 out:
	spin_unlock(&wil->wmi_ev_lock);

	mutex_unlock(&wil->wmi_mutex);

	return rc;