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

Commit 74b6ac58 authored by Maya Erez's avatar Maya Erez Committed by Kalle Valo
Browse files

wil6210: support rx key setting for all TIDs



According to the spec the PN should be calculated per TID.
In the current implementation, the PN and key_set were set
only for TID 0, therefore only traffic for TID 0 was supported.
In order to support all TIDs, the key_set and PN should be set
for all the TIDs.

Signed-off-by: default avatarMaya Erez <qca_merez@qca.qualcomm.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent f1b7764f
Loading
Loading
Loading
Loading
+81 −35
Original line number Original line Diff line number Diff line
@@ -760,14 +760,11 @@ static enum wmi_key_usage wil_detect_key_usage(struct wil6210_priv *wil,
	return rc;
	return rc;
}
}


static struct wil_tid_crypto_rx_single *
static struct wil_sta_info *
wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
wil_find_sta_by_key_usage(struct wil6210_priv *wil,
			  enum wmi_key_usage key_usage, const u8 *mac_addr)
			  enum wmi_key_usage key_usage, const u8 *mac_addr)
{
{
	int cid = -EINVAL;
	int cid = -EINVAL;
	int tid = 0;
	struct wil_sta_info *s;
	struct wil_tid_crypto_rx *c;


	if (key_usage == WMI_KEY_USE_TX_GROUP)
	if (key_usage == WMI_KEY_USE_TX_GROUP)
		return NULL; /* not needed */
		return NULL; /* not needed */
@@ -778,18 +775,72 @@ wil_find_crypto_ctx(struct wil6210_priv *wil, u8 key_index,
	else if (key_usage == WMI_KEY_USE_RX_GROUP)
	else if (key_usage == WMI_KEY_USE_RX_GROUP)
		cid = wil_find_cid_by_idx(wil, 0);
		cid = wil_find_cid_by_idx(wil, 0);
	if (cid < 0) {
	if (cid < 0) {
		wil_err(wil, "No CID for %pM %s[%d]\n", mac_addr,
		wil_err(wil, "No CID for %pM %s\n", mac_addr,
			key_usage_str[key_usage], key_index);
			key_usage_str[key_usage]);
		return ERR_PTR(cid);
		return ERR_PTR(cid);
	}
	}


	s = &wil->sta[cid];
	return &wil->sta[cid];
	if (key_usage == WMI_KEY_USE_PAIRWISE)
}
		c = &s->tid_crypto_rx[tid];

static void wil_set_crypto_rx(u8 key_index, enum wmi_key_usage key_usage,
			      struct wil_sta_info *cs,
			      struct key_params *params)
{
	struct wil_tid_crypto_rx_single *cc;
	int tid;

	if (!cs)
		return;

	switch (key_usage) {
	case WMI_KEY_USE_PAIRWISE:
		for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
			cc = &cs->tid_crypto_rx[tid].key_id[key_index];
			if (params->seq)
				memcpy(cc->pn, params->seq,
				       IEEE80211_GCMP_PN_LEN);
			else
			else
		c = &s->group_crypto_rx;
				memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
			cc->key_set = true;
		}
		break;
	case WMI_KEY_USE_RX_GROUP:
		cc = &cs->group_crypto_rx.key_id[key_index];
		if (params->seq)
			memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
		else
			memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
		cc->key_set = true;
		break;
	default:
		break;
	}
}


	return &c->key_id[key_index];
static void wil_del_rx_key(u8 key_index, enum wmi_key_usage key_usage,
			   struct wil_sta_info *cs)
{
	struct wil_tid_crypto_rx_single *cc;
	int tid;

	if (!cs)
		return;

	switch (key_usage) {
	case WMI_KEY_USE_PAIRWISE:
		for (tid = 0; tid < WIL_STA_TID_NUM; tid++) {
			cc = &cs->tid_crypto_rx[tid].key_id[key_index];
			cc->key_set = false;
		}
		break;
	case WMI_KEY_USE_RX_GROUP:
		cc = &cs->group_crypto_rx.key_id[key_index];
		cc->key_set = false;
		break;
	default:
		break;
	}
}
}


static int wil_cfg80211_add_key(struct wiphy *wiphy,
static int wil_cfg80211_add_key(struct wiphy *wiphy,
@@ -801,24 +852,26 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,
	int rc;
	int rc;
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
	struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
	struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
								  key_index,
								  key_usage,
							    mac_addr);
							    mac_addr);


	if (!params) {
		wil_err(wil, "NULL params\n");
		return -EINVAL;
	}

	wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__,
	wil_dbg_misc(wil, "%s(%pM %s[%d] PN %*phN)\n", __func__,
		     mac_addr, key_usage_str[key_usage], key_index,
		     mac_addr, key_usage_str[key_usage], key_index,
		     params->seq_len, params->seq);
		     params->seq_len, params->seq);


	if (IS_ERR(cc)) {
	if (IS_ERR(cs)) {
		wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n",
		wil_err(wil, "Not connected, %s(%pM %s[%d] PN %*phN)\n",
			__func__, mac_addr, key_usage_str[key_usage], key_index,
			__func__, mac_addr, key_usage_str[key_usage], key_index,
			params->seq_len, params->seq);
			params->seq_len, params->seq);
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (cc)
	wil_del_rx_key(key_index, key_usage, cs);
		cc->key_set = false;


	if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
	if (params->seq && params->seq_len != IEEE80211_GCMP_PN_LEN) {
		wil_err(wil,
		wil_err(wil,
@@ -831,13 +884,8 @@ static int wil_cfg80211_add_key(struct wiphy *wiphy,


	rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
	rc = wmi_add_cipher_key(wil, key_index, mac_addr, params->key_len,
				params->key, key_usage);
				params->key, key_usage);
	if ((rc == 0) && cc) {
	if (!rc)
		if (params->seq)
		wil_set_crypto_rx(key_index, key_usage, cs, params);
			memcpy(cc->pn, params->seq, IEEE80211_GCMP_PN_LEN);
		else
			memset(cc->pn, 0, IEEE80211_GCMP_PN_LEN);
		cc->key_set = true;
	}


	return rc;
	return rc;
}
}
@@ -849,20 +897,18 @@ static int wil_cfg80211_del_key(struct wiphy *wiphy,
{
{
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
	enum wmi_key_usage key_usage = wil_detect_key_usage(wil, pairwise);
	struct wil_tid_crypto_rx_single *cc = wil_find_crypto_ctx(wil,
	struct wil_sta_info *cs = wil_find_sta_by_key_usage(wil, key_usage,
								  key_index,
								  key_usage,
							    mac_addr);
							    mac_addr);


	wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr,
	wil_dbg_misc(wil, "%s(%pM %s[%d])\n", __func__, mac_addr,
		     key_usage_str[key_usage], key_index);
		     key_usage_str[key_usage], key_index);


	if (IS_ERR(cc))
	if (IS_ERR(cs))
		wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__,
		wil_info(wil, "Not connected, %s(%pM %s[%d])\n", __func__,
			 mac_addr, key_usage_str[key_usage], key_index);
			 mac_addr, key_usage_str[key_usage], key_index);


	if (!IS_ERR_OR_NULL(cc))
	if (!IS_ERR_OR_NULL(cs))
		cc->key_set = false;
		wil_del_rx_key(key_index, key_usage, cs);


	return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
	return wmi_del_cipher_key(wil, key_index, mac_addr, key_usage);
}
}