Commit ebba60c6 authored by Juuso Oikarinen's avatar Juuso Oikarinen Committed by John W. Linville

wl1271: Use minimum rate for each band for control messages

Currently the mac80211 is not telling a hardware rate controlled driver a
rate to use for association frames etc. So to be safe, use the lowest rate
of each band for communication.
Signed-off-by: default avatarJuuso Oikarinen <juuso.oikarinen@nokia.com>
Reviewed-by: default avatarTeemu Paasikivi <ext-teemu.3.paasikivi@nokia.com>
Signed-off-by: default avatarLuciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 40b359c6
...@@ -447,6 +447,7 @@ struct wl1271 { ...@@ -447,6 +447,7 @@ struct wl1271 {
/* currently configured rate set */ /* currently configured rate set */
u32 sta_rate_set; u32 sta_rate_set;
u32 basic_rate_set; u32 basic_rate_set;
u32 basic_rate;
u32 rate_set; u32 rate_set;
/* The current band */ /* The current band */
......
...@@ -802,7 +802,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl) ...@@ -802,7 +802,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl)
/* configure one basic rate class */ /* configure one basic rate class */
idx = ACX_TX_BASIC_RATE; idx = ACX_TX_BASIC_RATE;
acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set); acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
acx->rate_class[idx].short_retry_limit = c->short_retry_limit; acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
acx->rate_class[idx].long_retry_limit = c->long_retry_limit; acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
acx->rate_class[idx].aflags = c->aflags; acx->rate_class[idx].aflags = c->aflags;
......
...@@ -317,18 +317,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type) ...@@ -317,18 +317,10 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
join->rx_config_options = cpu_to_le32(wl->rx_config); join->rx_config_options = cpu_to_le32(wl->rx_config);
join->rx_filter_options = cpu_to_le32(wl->rx_filter); join->rx_filter_options = cpu_to_le32(wl->rx_filter);
join->bss_type = bss_type; join->bss_type = bss_type;
join->basic_rate_set = wl->basic_rate_set;
if (wl->band == IEEE80211_BAND_2GHZ) if (wl->band == IEEE80211_BAND_5GHZ)
join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS |
CONF_HW_BIT_RATE_2MBPS |
CONF_HW_BIT_RATE_5_5MBPS |
CONF_HW_BIT_RATE_11MBPS);
else {
join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ; join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS |
CONF_HW_BIT_RATE_12MBPS |
CONF_HW_BIT_RATE_24MBPS);
}
join->beacon_interval = cpu_to_le16(wl->beacon_int); join->beacon_interval = cpu_to_le16(wl->beacon_int);
join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD; join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
...@@ -581,17 +573,21 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, ...@@ -581,17 +573,21 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
struct wl1271_cmd_trigger_scan_to *trigger = NULL; struct wl1271_cmd_trigger_scan_to *trigger = NULL;
struct wl1271_cmd_scan *params = NULL; struct wl1271_cmd_scan *params = NULL;
struct ieee80211_channel *channels; struct ieee80211_channel *channels;
u32 rate;
int i, j, n_ch, ret; int i, j, n_ch, ret;
u16 scan_options = 0; u16 scan_options = 0;
u8 ieee_band; u8 ieee_band;
if (band == WL1271_SCAN_BAND_2_4_GHZ) if (band == WL1271_SCAN_BAND_2_4_GHZ) {
ieee_band = IEEE80211_BAND_2GHZ; ieee_band = IEEE80211_BAND_2GHZ;
else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) rate = wl->conf.tx.basic_rate;
} else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) {
ieee_band = IEEE80211_BAND_2GHZ; ieee_band = IEEE80211_BAND_2GHZ;
else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) rate = wl->conf.tx.basic_rate;
} else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) {
ieee_band = IEEE80211_BAND_5GHZ; ieee_band = IEEE80211_BAND_5GHZ;
else rate = wl->conf.tx.basic_rate_5;
} else
return -EINVAL; return -EINVAL;
if (wl->hw->wiphy->bands[ieee_band]->channels == NULL) if (wl->hw->wiphy->bands[ieee_band]->channels == NULL)
...@@ -618,8 +614,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len, ...@@ -618,8 +614,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
params->params.scan_options = cpu_to_le16(scan_options); params->params.scan_options = cpu_to_le16(scan_options);
params->params.num_probe_requests = probe_requests; params->params.num_probe_requests = probe_requests;
/* Let the fw autodetect suitable tx_rate for probes */ params->params.tx_rate = rate;
params->params.tx_rate = 0;
params->params.tid_trigger = 0; params->params.tid_trigger = 0;
params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG; params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
......
...@@ -674,6 +674,19 @@ struct conf_tx_settings { ...@@ -674,6 +674,19 @@ struct conf_tx_settings {
*/ */
u16 tx_compl_threshold; u16 tx_compl_threshold;
/*
* The rate used for control messages and scanning on the 2.4GHz band
*
* Range: CONF_HW_BIT_RATE_* bit mask
*/
u32 basic_rate;
/*
* The rate used for control messages and scanning on the 5GHz band
*
* Range: CONF_HW_BIT_RATE_* bit mask
*/
u32 basic_rate_5;
}; };
enum { enum {
......
...@@ -116,8 +116,7 @@ static struct conf_drv_settings default_conf = { ...@@ -116,8 +116,7 @@ static struct conf_drv_settings default_conf = {
.tx = { .tx = {
.tx_energy_detection = 0, .tx_energy_detection = 0,
.rc_conf = { .rc_conf = {
.enabled_rates = CONF_HW_BIT_RATE_1MBPS | .enabled_rates = 0,
CONF_HW_BIT_RATE_2MBPS,
.short_retry_limit = 10, .short_retry_limit = 10,
.long_retry_limit = 10, .long_retry_limit = 10,
.aflags = 0 .aflags = 0
...@@ -214,7 +213,9 @@ static struct conf_drv_settings default_conf = { ...@@ -214,7 +213,9 @@ static struct conf_drv_settings default_conf = {
}, },
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD, .frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
.tx_compl_timeout = 700, .tx_compl_timeout = 700,
.tx_compl_threshold = 4 .tx_compl_threshold = 4,
.basic_rate = CONF_HW_BIT_RATE_1MBPS,
.basic_rate_5 = CONF_HW_BIT_RATE_6MBPS,
}, },
.conn = { .conn = {
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM, .wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
...@@ -1171,6 +1172,32 @@ static int wl1271_unjoin_channel(struct wl1271 *wl) ...@@ -1171,6 +1172,32 @@ static int wl1271_unjoin_channel(struct wl1271 *wl)
return ret; return ret;
} }
static void wl1271_set_band_rate(struct wl1271 *wl)
{
if (wl->band == IEEE80211_BAND_2GHZ)
wl->basic_rate_set = wl->conf.tx.basic_rate;
else
wl->basic_rate_set = wl->conf.tx.basic_rate_5;
}
static u32 wl1271_min_rate_get(struct wl1271 *wl)
{
int i;
u32 rate = 0;
if (!wl->basic_rate_set) {
WARN_ON(1);
wl->basic_rate_set = wl->conf.tx.basic_rate;
}
for (i = 0; !rate; i++) {
if ((wl->basic_rate_set >> i) & 0x1)
rate = 1 << i;
}
return rate;
}
static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
{ {
struct wl1271 *wl = hw->priv; struct wl1271 *wl = hw->priv;
...@@ -1187,12 +1214,38 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1187,12 +1214,38 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&wl->mutex); mutex_lock(&wl->mutex);
wl->band = conf->channel->band;
ret = wl1271_ps_elp_wakeup(wl, false); ret = wl1271_ps_elp_wakeup(wl, false);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* if the channel changes while joined, join again */
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
wl->band = conf->channel->band;
wl->channel = channel;
/*
* FIXME: the mac80211 should really provide a fixed rate
* to use here. for now, just use the smallest possible rate
* for the band as a fixed rate for association frames and
* other control messages.
*/
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
wl1271_set_band_rate(wl);
wl->basic_rate = wl1271_min_rate_get(wl);
ret = wl1271_acx_rate_policies(wl);
if (ret < 0)
wl1271_warning("rate policy for update channel "
"failed %d", ret);
if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
ret = wl1271_cmd_join(wl, wl->set_bss_type);
if (ret < 0)
wl1271_warning("cmd join to update channel "
"failed %d", ret);
}
}
if (changed & IEEE80211_CONF_CHANGE_IDLE) { if (changed & IEEE80211_CONF_CHANGE_IDLE) {
if (conf->flags & IEEE80211_CONF_IDLE && if (conf->flags & IEEE80211_CONF_IDLE &&
test_bit(WL1271_FLAG_JOINED, &wl->flags)) test_bit(WL1271_FLAG_JOINED, &wl->flags))
...@@ -1201,7 +1254,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1201,7 +1254,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wl1271_join_channel(wl, channel); wl1271_join_channel(wl, channel);
if (conf->flags & IEEE80211_CONF_IDLE) { if (conf->flags & IEEE80211_CONF_IDLE) {
wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = wl1271_min_rate_get(wl);
wl->sta_rate_set = 0; wl->sta_rate_set = 0;
wl1271_acx_rate_policies(wl); wl1271_acx_rate_policies(wl);
wl1271_acx_keep_alive_config( wl1271_acx_keep_alive_config(
...@@ -1210,18 +1263,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -1210,18 +1263,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
} }
} }
/* if the channel changes while joined, join again */
if (channel != wl->channel &&
test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
wl->channel = channel;
/* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
ret = wl1271_cmd_join(wl, wl->set_bss_type);
if (ret < 0)
wl1271_warning("cmd join to update channel failed %d",
ret);
} else
wl->channel = channel;
if (conf->flags & IEEE80211_CONF_PS && if (conf->flags & IEEE80211_CONF_PS &&
!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) { !test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags); set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
...@@ -1659,9 +1700,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1659,9 +1700,22 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_ASSOC) { if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) { if (bss_conf->assoc) {
u32 rates;
wl->aid = bss_conf->aid; wl->aid = bss_conf->aid;
set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
/*
* use basic rates from AP, and determine lowest rate
* to use with control frames.
*/
rates = bss_conf->basic_rates;
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
rates);
wl->basic_rate = wl1271_min_rate_get(wl);
ret = wl1271_acx_rate_policies(wl);
if (ret < 0)
goto out_sleep;
/* /*
* with wl1271, we don't need to update the * with wl1271, we don't need to update the
* beacon_int and dtim_period, because the firmware * beacon_int and dtim_period, because the firmware
...@@ -1712,6 +1766,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, ...@@ -1712,6 +1766,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags); clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
wl->aid = 0; wl->aid = 0;
/* revert back to minimum rates for the current band */
wl1271_set_band_rate(wl);
wl->basic_rate = wl1271_min_rate_get(wl);
ret = wl1271_acx_rate_policies(wl);
if (ret < 0)
goto out_sleep;
/* disable connection monitor features */ /* disable connection monitor features */
ret = wl1271_acx_conn_monit_params(wl, false); ret = wl1271_acx_conn_monit_params(wl, false);
...@@ -2261,6 +2322,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void) ...@@ -2261,6 +2322,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->psm_entry_retry = 0; wl->psm_entry_retry = 0;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL; wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->sta_rate_set = 0; wl->sta_rate_set = 0;
wl->band = IEEE80211_BAND_2GHZ; wl->band = IEEE80211_BAND_2GHZ;
......
...@@ -220,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb) ...@@ -220,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
return ret; return ret;
} }
static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
{ {
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
u32 enabled_rates = 0; u32 enabled_rates = 0;
......
...@@ -160,5 +160,6 @@ void wl1271_tx_work(struct work_struct *work); ...@@ -160,5 +160,6 @@ void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl); void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_flush(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate); u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate);
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
#endif #endif
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