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

[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
...@@ -1747,21 +1747,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv) ...@@ -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 * return : set the bit for each supported rate insert in ie
*/ */
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, 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; u16 ret_rates = 0, bit;
int i; int i;
u8 *rates; u8 *cnt = ie;
u8 *rates = ie + 1;
rates = &(ie[1]);
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) { if (bit & supported_rate) {
ret_rates |= bit; ret_rates |= bit;
rates[*ie] = iwl_rates[i].ieee | rates[*cnt] = iwl_rates[i].ieee |
((bit & basic_rate) ? 0x80 : 0x00); ((bit & basic_rate) ? 0x80 : 0x00);
*ie = *ie + 1; (*cnt)++;
if (*ie >= max_count) (*left)--;
if ((*left <= 0) ||
(*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
break; break;
} }
} }
...@@ -1778,7 +1779,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -1778,7 +1779,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
{ {
int len = 0; int len = 0;
u8 *pos = NULL; u8 *pos = NULL;
u16 ret_rates; u16 active_rates, ret_rates, cck_rates;
/* Make sure there is enough space for the probe request, /* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */ * two mandatory IEs and the data */
...@@ -1823,19 +1824,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -1823,19 +1824,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
left -= 2; left -= 2;
if (left < 0) if (left < 0)
return 0; return 0;
/* ... fill it in... */ /* ... fill it in... */
*pos++ = WLAN_EID_SUPP_RATES; *pos++ = WLAN_EID_SUPP_RATES;
*pos = 0; *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; priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
iwl_supported_rate_to_ie(pos, priv->active_rate, cck_rates = IWL_CCK_RATES_MASK & active_rates;
priv->active_rate_basic, left); 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; len += 2 + *pos;
pos += (*pos) + 1; pos += (*pos) + 1;
ret_rates = ~ret_rates & priv->active_rate; if (active_rates == 0)
if (ret_rates == 0)
goto fill_end; goto fill_end;
/* fill in supported extended rate */ /* fill in supported extended rate */
...@@ -1846,7 +1855,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -1846,7 +1855,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/* ... fill it in... */ /* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0; *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) if (*pos > 0)
len += 2 + *pos; len += 2 + *pos;
......
...@@ -1800,21 +1800,22 @@ static void iwl_unset_hw_setting(struct iwl_priv *priv) ...@@ -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 * return : set the bit for each supported rate insert in ie
*/ */
static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate, 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; u16 ret_rates = 0, bit;
int i; int i;
u8 *rates; u8 *cnt = ie;
u8 *rates = ie + 1;
rates = &(ie[1]);
for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) { for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
if (bit & supported_rate) { if (bit & supported_rate) {
ret_rates |= bit; ret_rates |= bit;
rates[*ie] = iwl_rates[i].ieee | rates[*cnt] = iwl_rates[i].ieee |
((bit & basic_rate) ? 0x80 : 0x00); ((bit & basic_rate) ? 0x80 : 0x00);
*ie = *ie + 1; (*cnt)++;
if (*ie >= max_count) (*left)--;
if ((*left <= 0) ||
(*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
break; break;
} }
} }
...@@ -1837,7 +1838,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -1837,7 +1838,7 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
{ {
int len = 0; int len = 0;
u8 *pos = NULL; u8 *pos = NULL;
u16 ret_rates; u16 active_rates, ret_rates, cck_rates;
/* Make sure there is enough space for the probe request, /* Make sure there is enough space for the probe request,
* two mandatory IEs and the data */ * two mandatory IEs and the data */
...@@ -1882,19 +1883,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -1882,19 +1883,27 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
left -= 2; left -= 2;
if (left < 0) if (left < 0)
return 0; return 0;
/* ... fill it in... */ /* ... fill it in... */
*pos++ = WLAN_EID_SUPP_RATES; *pos++ = WLAN_EID_SUPP_RATES;
*pos = 0; *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; priv->active_rate_basic = priv->rates_mask & IWL_BASIC_RATES_MASK;
iwl_supported_rate_to_ie(pos, priv->active_rate, cck_rates = IWL_CCK_RATES_MASK & active_rates;
priv->active_rate_basic, left); 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; len += 2 + *pos;
pos += (*pos) + 1; pos += (*pos) + 1;
ret_rates = ~ret_rates & priv->active_rate; if (active_rates == 0)
if (ret_rates == 0)
goto fill_end; goto fill_end;
/* fill in supported extended rate */ /* fill in supported extended rate */
...@@ -1905,7 +1914,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv, ...@@ -1905,7 +1914,8 @@ static u16 iwl_fill_probe_req(struct iwl_priv *priv,
/* ... fill it in... */ /* ... fill it in... */
*pos++ = WLAN_EID_EXT_SUPP_RATES; *pos++ = WLAN_EID_EXT_SUPP_RATES;
*pos = 0; *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) if (*pos > 0)
len += 2 + *pos; len += 2 + *pos;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment