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

Commit c7c46676 authored by Tomas Winkler's avatar Tomas Winkler Committed by John W. Linville
Browse files

[PATCH] iwlwifi: Fix rate setting in probe request for HW sacn



This patch fixes setting of rates in probe request used in
HW scan. The bug was reported by Helmut Schaa <hschaa@suse.de>

Signed-off-by: default avatarTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 023384fa
Loading
Loading
Loading
Loading
+26 −16
Original line number Diff line number Diff line
@@ -1747,21 +1747,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv)
 * return : set the bit for each supported rate insert in ie
 */
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
				    u16 basic_rate, int max_count)
				    u16 basic_rate, int *left)
{
	u16 ret_rates = 0, bit;
	int i;
	u8 *rates;

	rates = &(ie[1]);
	u8 *cnt = ie;
	u8 *rates = ie + 1;

	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
		if (bit & supported_rate) {
			ret_rates |= bit;
			rates[*ie] = iwl_rates[i].ieee |
			rates[*cnt] = iwl_rates[i].ieee |
				((bit & basic_rate) ? 0x80 : 0x00);
			*ie = *ie + 1;
			if (*ie >= max_count)
			(*cnt)++;
			(*left)--;
			if ((*left <= 0) ||
			    (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
				break;
		}
	}
@@ -1778,7 +1779,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
{
	int len = 0;
	u8 *pos = NULL;
	u16 ret_rates;
	u16 active_rates, ret_rates, cck_rates;

	/* Make sure there is enough space for the probe request,
	 * two mandatory IEs and the data */
@@ -1823,19 +1824,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
	left -= 2;
	if (left < 0)
		return 0;

	/* ... fill it in... */
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos = 0;
	ret_rates = priv->active_rate = priv->rates_mask;

	priv->active_rate = priv->rates_mask;
	active_rates = priv->active_rate;
	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;

	iwl_supported_rate_to_ie(pos, priv->active_rate,
				 priv->active_rate_basic, left);
	cck_rates = IWL_CCK_RATES_MASK & active_rates;
	ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
			priv->active_rate_basic, &left);
	active_rates &= ~ret_rates;

	ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
				 priv->active_rate_basic, &left);
	active_rates &= ~ret_rates;

	len += 2 + *pos;
	pos += (*pos) + 1;
	ret_rates = ~ret_rates & priv->active_rate;

	if (ret_rates == 0)
	if (active_rates == 0)
		goto fill_end;

	/* fill in supported extended rate */
@@ -1846,7 +1855,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
	/* ... fill it in... */
	*pos++ = WLAN_EID_EXT_SUPP_RATES;
	*pos = 0;
	iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
	iwl_supported_rate_to_ie(pos, active_rates,
				 priv->active_rate_basic, &left);
	if (*pos > 0)
		len += 2 + *pos;

+26 −16
Original line number Diff line number Diff line
@@ -1800,21 +1800,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv)
 * return : set the bit for each supported rate insert in ie
 */
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
				    u16 basic_rate, int max_count)
				    u16 basic_rate, int *left)
{
	u16 ret_rates = 0, bit;
	int i;
	u8 *rates;

	rates = &(ie[1]);
	u8 *cnt = ie;
	u8 *rates = ie + 1;

	for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
		if (bit & supported_rate) {
			ret_rates |= bit;
			rates[*ie] = iwl_rates[i].ieee |
			rates[*cnt] = iwl_rates[i].ieee |
				((bit & basic_rate) ? 0x80 : 0x00);
			*ie = *ie + 1;
			if (*ie >= max_count)
			(*cnt)++;
			(*left)--;
			if ((*left <= 0) ||
			    (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
				break;
		}
	}
@@ -1837,7 +1838,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
{
	int len = 0;
	u8 *pos = NULL;
	u16 ret_rates;
	u16 active_rates, ret_rates, cck_rates;

	/* Make sure there is enough space for the probe request,
	 * two mandatory IEs and the data */
@@ -1882,19 +1883,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
	left -= 2;
	if (left < 0)
		return 0;

	/* ... fill it in... */
	*pos++ = WLAN_EID_SUPP_RATES;
	*pos = 0;
	ret_rates = priv->active_rate = priv->rates_mask;

	priv->active_rate = priv->rates_mask;
	active_rates = priv->active_rate;
	priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;

	iwl_supported_rate_to_ie(pos, priv->active_rate,
				 priv->active_rate_basic, left);
	cck_rates = IWL_CCK_RATES_MASK & active_rates;
	ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
			priv->active_rate_basic, &left);
	active_rates &= ~ret_rates;

	ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
				 priv->active_rate_basic, &left);
	active_rates &= ~ret_rates;

	len += 2 + *pos;
	pos += (*pos) + 1;
	ret_rates = ~ret_rates & priv->active_rate;

	if (ret_rates == 0)
	if (active_rates == 0)
		goto fill_end;

	/* fill in supported extended rate */
@@ -1905,7 +1914,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
	/* ... fill it in... */
	*pos++ = WLAN_EID_EXT_SUPP_RATES;
	*pos = 0;
	iwl_supported_rate_to_ie(pos, ret_rates, priv->active_rate_basic, left);
	iwl_supported_rate_to_ie(pos, active_rates,
				 priv->active_rate_basic, &left);
	if (*pos > 0)
		len += 2 + *pos;