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

Commit 948cca9f authored by Kalle Valo's avatar Kalle Valo
Browse files

Merge tag 'iwlwifi-for-kalle-2015-11-15' of...

Merge tag 'iwlwifi-for-kalle-2015-11-15' of https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-fixes

* bump API to firmware 19 - not released yet.
* fix D3 flows (Luca)
* new device IDs (Oren)
* fix NULL pointer dereference (Avri)
parents f1a454a3 9513c5e1
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@
#include "iwl-agn-hw.h"

/* Highest firmware API version supported */
#define IWL7260_UCODE_API_MAX	17
#define IWL7260_UCODE_API_MAX	19

/* Oldest version we won't warn about */
#define IWL7260_UCODE_API_OK	13
+1 −1
Original line number Diff line number Diff line
@@ -69,7 +69,7 @@
#include "iwl-agn-hw.h"

/* Highest firmware API version supported */
#define IWL8000_UCODE_API_MAX	17
#define IWL8000_UCODE_API_MAX	19

/* Oldest version we won't warn about */
#define IWL8000_UCODE_API_OK	13
+2 −6
Original line number Diff line number Diff line
@@ -309,9 +309,9 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
	 * to transmit packets to the AP, i.e. the PTK.
	 */
	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
		key->hw_key_idx = 0;
		mvm->ptk_ivlen = key->iv_len;
		mvm->ptk_icvlen = key->icv_len;
		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 0);
	} else {
		/*
		 * firmware only supports TSC/RSC for a single key,
@@ -319,12 +319,11 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
		 * with new ones -- this relies on mac80211 doing
		 * list_add_tail().
		 */
		key->hw_key_idx = 1;
		mvm->gtk_ivlen = key->iv_len;
		mvm->gtk_icvlen = key->icv_len;
		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, 1);
	}

	ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, true);
	data->error = ret != 0;
out_unlock:
	mutex_unlock(&mvm->mutex);
@@ -772,9 +771,6 @@ static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm)
	 */
	set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status);

	/* We reprogram keys and shouldn't allocate new key indices */
	memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table));

	mvm->ptk_ivlen = 0;
	mvm->ptk_icvlen = 0;
	mvm->ptk_ivlen = 0;
+8 −3
Original line number Diff line number Diff line
@@ -2941,6 +2941,7 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
{
	struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
	int ret;
	u8 key_offset;

	if (iwlwifi_mod_params.sw_crypto) {
		IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n");
@@ -3006,10 +3007,14 @@ static int iwl_mvm_mac_set_key(struct ieee80211_hw *hw,
			break;
		}

		/* in HW restart reuse the index, otherwise request a new one */
		if (test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status))
			key_offset = key->hw_key_idx;
		else
			key_offset = STA_KEY_IDX_INVALID;

		IWL_DEBUG_MAC80211(mvm, "set hwcrypto key\n");
		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key,
					  test_bit(IWL_MVM_STATUS_IN_HW_RESTART,
						   &mvm->status));
		ret = iwl_mvm_set_sta_key(mvm, vif, sta, key, key_offset);
		if (ret) {
			IWL_WARN(mvm, "set key failed\n");
			/*
+47 −41
Original line number Diff line number Diff line
@@ -1201,7 +1201,8 @@ static int iwl_mvm_set_fw_key_idx(struct iwl_mvm *mvm)
	return max_offs;
}

static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
static u8 iwl_mvm_get_key_sta_id(struct iwl_mvm *mvm,
				 struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta)
{
	struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -1218,8 +1219,21 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
	 * station ID, then use AP's station ID.
	 */
	if (vif->type == NL80211_IFTYPE_STATION &&
	    mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT)
		return mvmvif->ap_sta_id;
	    mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) {
		u8 sta_id = mvmvif->ap_sta_id;

		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
						lockdep_is_held(&mvm->mutex));
		/*
		 * It is possible that the 'sta' parameter is NULL,
		 * for example when a GTK is removed - the sta_id will then
		 * be the AP ID, and no station was passed by mac80211.
		 */
		if (IS_ERR_OR_NULL(sta))
			return IWL_MVM_STATION_COUNT;

		return sta_id;
	}

	return IWL_MVM_STATION_COUNT;
}
@@ -1227,7 +1241,8 @@ static u8 iwl_mvm_get_key_sta_id(struct ieee80211_vif *vif,
static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
				struct iwl_mvm_sta *mvm_sta,
				struct ieee80211_key_conf *keyconf, bool mcast,
				u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags)
				u32 tkip_iv32, u16 *tkip_p1k, u32 cmd_flags,
				u8 key_offset)
{
	struct iwl_mvm_add_sta_key_cmd cmd = {};
	__le16 key_flags;
@@ -1269,7 +1284,7 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
	if (mcast)
		key_flags |= cpu_to_le16(STA_KEY_MULTICAST);

	cmd.key_offset = keyconf->hw_key_idx;
	cmd.key_offset = key_offset;
	cmd.key_flags = key_flags;
	cmd.sta_id = sta_id;

@@ -1360,6 +1375,7 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
				 struct ieee80211_vif *vif,
				 struct ieee80211_sta *sta,
				 struct ieee80211_key_conf *keyconf,
				 u8 key_offset,
				 bool mcast)
{
	struct iwl_mvm_sta *mvm_sta = iwl_mvm_sta_from_mac80211(sta);
@@ -1375,17 +1391,17 @@ static int __iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
		ieee80211_get_key_rx_seq(keyconf, 0, &seq);
		ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
					   seq.tkip.iv32, p1k, 0);
					   seq.tkip.iv32, p1k, 0, key_offset);
		break;
	case WLAN_CIPHER_SUITE_CCMP:
	case WLAN_CIPHER_SUITE_WEP40:
	case WLAN_CIPHER_SUITE_WEP104:
		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
					   0, NULL, 0);
					   0, NULL, 0, key_offset);
		break;
	default:
		ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
					   0, NULL, 0);
					   0, NULL, 0, key_offset);
	}

	return ret;
@@ -1433,7 +1449,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
			struct ieee80211_vif *vif,
			struct ieee80211_sta *sta,
			struct ieee80211_key_conf *keyconf,
			bool have_key_offset)
			u8 key_offset)
{
	bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);
	u8 sta_id;
@@ -1443,7 +1459,7 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
	lockdep_assert_held(&mvm->mutex);

	/* Get the station id from the mvm local station table */
	sta_id = iwl_mvm_get_key_sta_id(vif, sta);
	sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
	if (sta_id == IWL_MVM_STATION_COUNT) {
		IWL_ERR(mvm, "Failed to find station id\n");
		return -EINVAL;
@@ -1470,18 +1486,25 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
	if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
		return -EINVAL;

	if (!have_key_offset) {
		/*
		 * The D3 firmware hardcodes the PTK offset to 0, so we have to
		 * configure it there. As a result, this workaround exists to
		 * let the caller set the key offset (hw_key_idx), see d3.c.
	/* If the key_offset is not pre-assigned, we need to find a
	 * new offset to use.  In normal cases, the offset is not
	 * pre-assigned, but during HW_RESTART we want to reuse the
	 * same indices, so we pass them when this function is called.
	 *
	 * In D3 entry, we need to hardcoded the indices (because the
	 * firmware hardcodes the PTK offset to 0).  In this case, we
	 * need to make sure we don't overwrite the hw_key_idx in the
	 * keyconf structure, because otherwise we cannot configure
	 * the original ones back when resuming.
	 */
		keyconf->hw_key_idx = iwl_mvm_set_fw_key_idx(mvm);
		if (keyconf->hw_key_idx == STA_KEY_IDX_INVALID)
	if (key_offset == STA_KEY_IDX_INVALID) {
		key_offset  = iwl_mvm_set_fw_key_idx(mvm);
		if (key_offset == STA_KEY_IDX_INVALID)
			return -ENOSPC;
		keyconf->hw_key_idx = key_offset;
	}

	ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, mcast);
	ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, key_offset, mcast);
	if (ret) {
		__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
		goto end;
@@ -1495,7 +1518,8 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
	 */
	if (keyconf->cipher == WLAN_CIPHER_SUITE_WEP40 ||
	    keyconf->cipher == WLAN_CIPHER_SUITE_WEP104) {
		ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf, !mcast);
		ret = __iwl_mvm_set_sta_key(mvm, vif, sta, keyconf,
					    key_offset, !mcast);
		if (ret) {
			__clear_bit(keyconf->hw_key_idx, mvm->fw_key_table);
			__iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
@@ -1521,7 +1545,7 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
	lockdep_assert_held(&mvm->mutex);

	/* Get the station id from the mvm local station table */
	sta_id = iwl_mvm_get_key_sta_id(vif, sta);
	sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);

	IWL_DEBUG_WEP(mvm, "mvm remove dynamic key: idx=%d sta=%d\n",
		      keyconf->keyidx, sta_id);
@@ -1547,24 +1571,6 @@ int iwl_mvm_remove_sta_key(struct iwl_mvm *mvm,
		return 0;
	}

	/*
	 * It is possible that the 'sta' parameter is NULL, and thus
	 * there is a need to retrieve the sta from the local station table,
	 * for example when a GTK is removed (where the sta_id will then be
	 * the AP ID, and no station was passed by mac80211.)
	 */
	if (!sta) {
		sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[sta_id],
						lockdep_is_held(&mvm->mutex));
		if (!sta) {
			IWL_ERR(mvm, "Invalid station id\n");
			return -EINVAL;
		}
	}

	if (WARN_ON_ONCE(iwl_mvm_sta_from_mac80211(sta)->vif != vif))
		return -EINVAL;

	ret = __iwl_mvm_remove_sta_key(mvm, sta_id, keyconf, mcast);
	if (ret)
		return ret;
@@ -1584,7 +1590,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,
			     u16 *phase1key)
{
	struct iwl_mvm_sta *mvm_sta;
	u8 sta_id = iwl_mvm_get_key_sta_id(vif, sta);
	u8 sta_id = iwl_mvm_get_key_sta_id(mvm, vif, sta);
	bool mcast = !(keyconf->flags & IEEE80211_KEY_FLAG_PAIRWISE);

	if (WARN_ON_ONCE(sta_id == IWL_MVM_STATION_COUNT))
@@ -1602,7 +1608,7 @@ void iwl_mvm_update_tkip_key(struct iwl_mvm *mvm,

	mvm_sta = iwl_mvm_sta_from_mac80211(sta);
	iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, mcast,
			     iv32, phase1key, CMD_ASYNC);
			     iv32, phase1key, CMD_ASYNC, keyconf->hw_key_idx);
	rcu_read_unlock();
}

Loading