Commit 85a8eefd authored by John W. Linville's avatar John W. Linville

Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx

parents bb8f2cb2 6b661895
wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \ wl12xx-objs = main.o cmd.o io.o event.o tx.o rx.o ps.o acx.o \
boot.o init.o debugfs.o scan.o boot.o init.o debugfs.o scan.o
wl12xx_spi-objs = spi.o wl12xx_spi-objs = spi.o
wl12xx_sdio-objs = sdio.o wl12xx_sdio-objs = sdio.o
wl12xx_sdio_test-objs = sdio_test.o wl12xx_sdio_test-objs = sdio_test.o
wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o wl12xx-$(CONFIG_NL80211_TESTMODE) += testmode.o
obj-$(CONFIG_WL12XX) += wl12xx.o obj-$(CONFIG_WL12XX) += wl12xx.o
obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.o
obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o obj-$(CONFIG_WL12XX_SDIO) += wl12xx_sdio.o
obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o obj-$(CONFIG_WL12XX_SDIO_TEST) += wl12xx_sdio_test.o
# small builtin driver bit # small builtin driver bit
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
...@@ -661,12 +661,9 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) ...@@ -661,12 +661,9 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id); wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id);
/* /* trying to use hidden SSID with an old hostapd version */
* We currently do not support hidden SSID. The real SSID if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) {
* should be fetched from mac80211 first. wl1271_error("got a null SSID from beacon/bss");
*/
if (wl->ssid_len == 0) {
wl1271_warning("Hidden SSID currently not supported for AP");
ret = -EINVAL; ret = -EINVAL;
goto out; goto out;
} }
...@@ -695,9 +692,18 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl) ...@@ -695,9 +692,18 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
cmd->ap.dtim_interval = bss_conf->dtim_period; cmd->ap.dtim_interval = bss_conf->dtim_period;
cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP; cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
cmd->channel = wl->channel; cmd->channel = wl->channel;
cmd->ap.ssid_len = wl->ssid_len;
cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC; if (!bss_conf->hidden_ssid) {
memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len); /* take the SSID from the beacon for backward compatibility */
cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
cmd->ap.ssid_len = wl->ssid_len;
memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
} else {
cmd->ap.ssid_type = WL12XX_SSID_TYPE_HIDDEN;
cmd->ap.ssid_len = bss_conf->ssid_len;
memcpy(cmd->ap.ssid, bss_conf->ssid, bss_conf->ssid_len);
}
cmd->ap.local_rates = cpu_to_le32(0xffffffff); cmd->ap.local_rates = cpu_to_le32(0xffffffff);
switch (wl->band) { switch (wl->band) {
...@@ -1106,6 +1112,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, ...@@ -1106,6 +1112,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
{ {
struct sk_buff *skb; struct sk_buff *skb;
int ret; int ret;
u32 rate;
skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
ie, ie_len); ie, ie_len);
...@@ -1116,14 +1123,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl, ...@@ -1116,14 +1123,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len); wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
if (band == IEEE80211_BAND_2GHZ) if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
skb->data, skb->len, 0, skb->data, skb->len, 0, rate);
wl->conf.tx.basic_rate);
else else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
skb->data, skb->len, 0, skb->data, skb->len, 0, rate);
wl->conf.tx.basic_rate_5);
out: out:
dev_kfree_skb(skb); dev_kfree_skb(skb);
...@@ -1134,6 +1140,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, ...@@ -1134,6 +1140,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
struct sk_buff *skb) struct sk_buff *skb)
{ {
int ret; int ret;
u32 rate;
if (!skb) if (!skb)
skb = ieee80211_ap_probereq_get(wl->hw, wl->vif); skb = ieee80211_ap_probereq_get(wl->hw, wl->vif);
...@@ -1142,14 +1149,13 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl, ...@@ -1142,14 +1149,13 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len); wl1271_dump(DEBUG_SCAN, "AP PROBE REQ: ", skb->data, skb->len);
rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[wl->band]);
if (wl->band == IEEE80211_BAND_2GHZ) if (wl->band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
skb->data, skb->len, 0, skb->data, skb->len, 0, rate);
wl->conf.tx.basic_rate);
else else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
skb->data, skb->len, 0, skb->data, skb->len, 0, rate);
wl->conf.tx.basic_rate_5);
if (ret < 0) if (ret < 0)
wl1271_error("Unable to set ap probe request template."); wl1271_error("Unable to set ap probe request template.");
...@@ -1442,7 +1448,8 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid) ...@@ -1442,7 +1448,8 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET; sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
cmd->supported_rates = cmd->supported_rates =
cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates)); cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates,
wl->band));
wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x", wl1271_debug(DEBUG_CMD, "new peer rates=0x%x queues=0x%x",
cmd->supported_rates, sta->uapsd_queues); cmd->supported_rates, sta->uapsd_queues);
......
...@@ -454,12 +454,10 @@ struct conf_rx_settings { ...@@ -454,12 +454,10 @@ struct conf_rx_settings {
#define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \ #define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS) CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
/* /* default rates for working as IBSS (11b and OFDM) */
* Default rates for working as IBSS. use 11b rates
*/
#define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \ #define CONF_TX_IBSS_DEFAULT_RATES (CONF_HW_BIT_RATE_1MBPS | \
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \ CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS | \
CONF_HW_BIT_RATE_11MBPS); CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES);
struct conf_tx_rate_class { struct conf_tx_rate_class {
......
...@@ -181,7 +181,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl) ...@@ -181,7 +181,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl)
} else { } else {
int i; int i;
struct wl1271_link *lnk; struct wl1271_link *lnk;
for (i = WL1271_AP_STA_HLID_START; i < WL12XX_MAX_LINKS; i++) { for (i = WL1271_AP_STA_HLID_START; i < AP_MAX_LINKS; i++) {
lnk = &wl->links[i]; lnk = &wl->links[i];
if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap) if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
continue; continue;
......
...@@ -103,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) ...@@ -103,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
{ {
struct wl12xx_disconn_template *tmpl; struct wl12xx_disconn_template *tmpl;
int ret; int ret;
u32 rate;
tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL); tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
if (!tmpl) { if (!tmpl) {
...@@ -113,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl) ...@@ -113,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT | tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_DEAUTH); IEEE80211_STYPE_DEAUTH);
rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
tmpl, sizeof(*tmpl), 0, tmpl, sizeof(*tmpl), 0, rate);
wl1271_tx_min_rate_get(wl));
out: out:
kfree(tmpl); kfree(tmpl);
...@@ -126,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) ...@@ -126,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
{ {
struct ieee80211_hdr_3addr *nullfunc; struct ieee80211_hdr_3addr *nullfunc;
int ret; int ret;
u32 rate;
nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL); nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
if (!nullfunc) { if (!nullfunc) {
...@@ -142,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl) ...@@ -142,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN); memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN); memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
sizeof(*nullfunc), 0, sizeof(*nullfunc), 0, rate);
wl1271_tx_min_rate_get(wl));
out: out:
kfree(nullfunc); kfree(nullfunc);
...@@ -155,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) ...@@ -155,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
{ {
struct ieee80211_qos_hdr *qosnull; struct ieee80211_qos_hdr *qosnull;
int ret; int ret;
u32 rate;
qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL); qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
if (!qosnull) { if (!qosnull) {
...@@ -171,9 +174,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl) ...@@ -171,9 +174,9 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN); memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN); memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull, ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
sizeof(*qosnull), 0, sizeof(*qosnull), 0, rate);
wl1271_tx_min_rate_get(wl));
out: out:
kfree(qosnull); kfree(qosnull);
...@@ -498,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl) ...@@ -498,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
return ret; return ret;
/* use the min basic rate for AP broadcast/multicast */ /* use the min basic rate for AP broadcast/multicast */
rc.enabled_rates = wl1271_tx_min_rate_get(wl); rc.enabled_rates = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
rc.short_retry_limit = 10; rc.short_retry_limit = 10;
rc.long_retry_limit = 10; rc.long_retry_limit = 10;
rc.aflags = 0; rc.aflags = 0;
......
...@@ -2099,6 +2099,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, ...@@ -2099,6 +2099,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
wl->time_offset = 0; wl->time_offset = 0;
wl->session_counter = 0; wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC; wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
wl->vif = NULL; wl->vif = NULL;
wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT; wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl1271_free_ap_keys(wl); wl1271_free_ap_keys(wl);
...@@ -2237,14 +2239,8 @@ static int wl1271_unjoin(struct wl1271 *wl) ...@@ -2237,14 +2239,8 @@ static int wl1271_unjoin(struct wl1271 *wl)
static void wl1271_set_band_rate(struct wl1271 *wl) static void wl1271_set_band_rate(struct wl1271 *wl)
{ {
if (wl->band == IEEE80211_BAND_2GHZ) { wl->basic_rate_set = wl->bitrate_masks[wl->band];
wl->basic_rate_set = wl->conf.tx.basic_rate; wl->rate_set = wl->basic_rate_set;
wl->rate_set = wl->conf.tx.basic_rate;
} else {
wl->basic_rate_set = wl->conf.tx.basic_rate_5;
wl->rate_set = wl->conf.tx.basic_rate_5;
}
} }
static bool wl12xx_is_roc(struct wl1271 *wl) static bool wl12xx_is_roc(struct wl1271 *wl)
...@@ -2273,7 +2269,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle) ...@@ -2273,7 +2269,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
if (ret < 0) if (ret < 0)
goto out; goto out;
} }
wl->rate_set = wl1271_tx_min_rate_get(wl); wl->rate_set = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -2355,6 +2351,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2355,6 +2351,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_CHANNEL && if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
((wl->band != conf->channel->band) || ((wl->band != conf->channel->band) ||
(wl->channel != channel))) { (wl->channel != channel))) {
/* send all pending packets */
wl1271_tx_work_locked(wl);
wl->band = conf->channel->band; wl->band = conf->channel->band;
wl->channel = channel; wl->channel = channel;
...@@ -2368,7 +2366,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) ...@@ -2368,7 +2366,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
wl1271_set_band_rate(wl); wl1271_set_band_rate(wl);
wl->basic_rate = wl1271_tx_min_rate_get(wl); wl->basic_rate =
wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
wl1271_warning("rate policy for channel " wl1271_warning("rate policy for channel "
...@@ -3069,6 +3068,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb, ...@@ -3069,6 +3068,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
return 0; return 0;
} }
static void wl12xx_remove_ie(struct sk_buff *skb, u8 eid, int ieoffset)
{
int len;
const u8 *next, *end = skb->data + skb->len;
u8 *ie = (u8 *)cfg80211_find_ie(eid, skb->data + ieoffset,
skb->len - ieoffset);
if (!ie)
return;
len = ie[1] + 2;
next = ie + len;
memmove(ie, next, end - next);
skb_trim(skb, skb->len - len);
}
static void wl12xx_remove_vendor_ie(struct sk_buff *skb,
unsigned int oui, u8 oui_type,
int ieoffset)
{
int len;
const u8 *next, *end = skb->data + skb->len;
u8 *ie = (u8 *)cfg80211_find_vendor_ie(oui, oui_type,
skb->data + ieoffset,
skb->len - ieoffset);
if (!ie)
return;
len = ie[1] + 2;
next = ie + len;
memmove(ie, next, end - next);
skb_trim(skb, skb->len - len);
}
static int wl1271_ap_set_probe_resp_tmpl(struct wl1271 *wl,
u8 *probe_rsp_data,
size_t probe_rsp_len,
u32 rates)
{
struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
u8 probe_rsp_templ[WL1271_CMD_TEMPL_MAX_SIZE];
int ssid_ie_offset, ie_offset, templ_len;
const u8 *ptr;
/* no need to change probe response if the SSID is set correctly */
if (wl->ssid_len > 0)
return wl1271_cmd_template_set(wl,
CMD_TEMPL_AP_PROBE_RESPONSE,
probe_rsp_data,
probe_rsp_len, 0,
rates);
if (probe_rsp_len + bss_conf->ssid_len > WL1271_CMD_TEMPL_MAX_SIZE) {
wl1271_error("probe_rsp template too big");
return -EINVAL;
}
/* start searching from IE offset */
ie_offset = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
ptr = cfg80211_find_ie(WLAN_EID_SSID, probe_rsp_data + ie_offset,
probe_rsp_len - ie_offset);
if (!ptr) {
wl1271_error("No SSID in beacon!");
return -EINVAL;
}
ssid_ie_offset = ptr - probe_rsp_data;
ptr += (ptr[1] + 2);
memcpy(probe_rsp_templ, probe_rsp_data, ssid_ie_offset);
/* insert SSID from bss_conf */
probe_rsp_templ[ssid_ie_offset] = WLAN_EID_SSID;
probe_rsp_templ[ssid_ie_offset + 1] = bss_conf->ssid_len;
memcpy(probe_rsp_templ + ssid_ie_offset + 2,
bss_conf->ssid, bss_conf->ssid_len);
templ_len = ssid_ie_offset + 2 + bss_conf->ssid_len;
memcpy(probe_rsp_templ + ssid_ie_offset + 2 + bss_conf->ssid_len,
ptr, probe_rsp_len - (ptr - probe_rsp_data));
templ_len += probe_rsp_len - (ptr - probe_rsp_data);
return wl1271_cmd_template_set(wl,
CMD_TEMPL_AP_PROBE_RESPONSE,
probe_rsp_templ,
templ_len, 0,
rates);
}
static int wl1271_bss_erp_info_changed(struct wl1271 *wl, static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
struct ieee80211_bss_conf *bss_conf, struct ieee80211_bss_conf *bss_conf,
u32 changed) u32 changed)
...@@ -3125,6 +3211,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, ...@@ -3125,6 +3211,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BEACON)) { if ((changed & BSS_CHANGED_BEACON)) {
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
u32 min_rate;
int ieoffset = offsetof(struct ieee80211_mgmt, int ieoffset = offsetof(struct ieee80211_mgmt,
u.beacon.variable); u.beacon.variable);
struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif); struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
...@@ -3140,28 +3227,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl, ...@@ -3140,28 +3227,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
dev_kfree_skb(beacon); dev_kfree_skb(beacon);
goto out; goto out;
} }
min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON : tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
CMD_TEMPL_BEACON; CMD_TEMPL_BEACON;
ret = wl1271_cmd_template_set(wl, tmpl_id, ret = wl1271_cmd_template_set(wl, tmpl_id,
beacon->data, beacon->data,
beacon->len, 0, beacon->len, 0,
wl1271_tx_min_rate_get(wl)); min_rate);
if (ret < 0) { if (ret < 0) {
dev_kfree_skb(beacon); dev_kfree_skb(beacon);
goto out; goto out;
} }
/* remove TIM ie from probe response */
wl12xx_remove_ie(beacon, WLAN_EID_TIM, ieoffset);
/*
* remove p2p ie from probe response.
* the fw reponds to probe requests that don't include
* the p2p ie. probe requests with p2p ie will be passed,
* and will be responded by the supplicant (the spec
* forbids including the p2p ie when responding to probe
* requests that didn't include it).
*/
wl12xx_remove_vendor_ie(beacon, WLAN_OUI_WFA,
WLAN_OUI_TYPE_WFA_P2P, ieoffset);
hdr = (struct ieee80211_hdr *) beacon->data; hdr = (struct ieee80211_hdr *) beacon->data;
hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
IEEE80211_STYPE_PROBE_RESP); IEEE80211_STYPE_PROBE_RESP);
if (is_ap)
tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE : ret = wl1271_ap_set_probe_resp_tmpl(wl,
CMD_TEMPL_PROBE_RESPONSE; beacon->data,
ret = wl1271_cmd_template_set(wl, beacon->len,
tmpl_id, min_rate);
beacon->data, else
beacon->len, 0, ret = wl1271_cmd_template_set(wl,
wl1271_tx_min_rate_get(wl)); CMD_TEMPL_PROBE_RESPONSE,
beacon->data,
beacon->len, 0,
min_rate);
dev_kfree_skb(beacon); dev_kfree_skb(beacon);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -3182,8 +3287,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl, ...@@ -3182,8 +3287,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
if ((changed & BSS_CHANGED_BASIC_RATES)) { if ((changed & BSS_CHANGED_BASIC_RATES)) {
u32 rates = bss_conf->basic_rates; u32 rates = bss_conf->basic_rates;
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates); wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates,
wl->basic_rate = wl1271_tx_min_rate_get(wl); wl->band);
wl->basic_rate = wl1271_tx_min_rate_get(wl,
wl->basic_rate_set);
ret = wl1271_init_ap_rates(wl); ret = wl1271_init_ap_rates(wl);
if (ret < 0) { if (ret < 0) {
...@@ -3365,12 +3472,15 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ...@@ -3365,12 +3472,15 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
* to use with control frames. * to use with control frames.
*/ */
rates = bss_conf->basic_rates; rates = bss_conf->basic_rates;
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, wl->basic_rate_set =
rates); wl1271_tx_enabled_rates_get(wl, rates,
wl->basic_rate = wl1271_tx_min_rate_get(wl); wl->band);
wl->basic_rate =
wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
if (sta_rate_set) if (sta_rate_set)
wl->rate_set = wl1271_tx_enabled_rates_get(wl, wl->rate_set = wl1271_tx_enabled_rates_get(wl,
sta_rate_set); sta_rate_set,
wl->band);
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -3417,7 +3527,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ...@@ -3417,7 +3527,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
/* revert back to minimum rates for the current band */ /* revert back to minimum rates for the current band */
wl1271_set_band_rate(wl); wl1271_set_band_rate(wl);
wl->basic_rate = wl1271_tx_min_rate_get(wl); wl->basic_rate =
wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
goto out; goto out;
...@@ -3468,11 +3579,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl, ...@@ -3468,11 +3579,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
if (bss_conf->ibss_joined) { if (bss_conf->ibss_joined) {
u32 rates = bss_conf->basic_rates; u32 rates = bss_conf->basic_rates;
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, wl->basic_rate_set =
rates); wl1271_tx_enabled_rates_get(wl, rates,
wl->basic_rate = wl1271_tx_min_rate_get(wl); wl->band);
wl->basic_rate =
wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
/* by default, use 11b rates */ /* by default, use 11b + OFDM rates */
wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES; wl->rate_set = CONF_TX_IBSS_DEFAULT_RATES;
ret = wl1271_acx_sta_rate_policies(wl); ret = wl1271_acx_sta_rate_policies(wl);
if (ret < 0) if (ret < 0)
...@@ -3992,6 +4105,29 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, ...@@ -3992,6 +4105,29 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
return ret; return ret;
} }
static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
const struct cfg80211_bitrate_mask *mask)
{
struct wl1271 *wl = hw->priv;
int i;
wl1271_debug(DEBUG_MAC80211, "mac80211 set_bitrate_mask 0x%x 0x%x",
mask->control[NL80211_BAND_2GHZ].legacy,
mask->control[NL80211_BAND_5GHZ].legacy);
mutex_lock(&wl->mutex);
for (i = 0; i < IEEE80211_NUM_BANDS; i++)
wl->bitrate_masks[i] =
wl1271_tx_enabled_rates_get(wl,
mask->control[i].legacy,
i);
mutex_unlock(&wl->mutex);
return 0;
}
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{ {
struct wl1271 *wl = hw->priv; struct wl1271 *wl = hw->priv;
...@@ -4267,6 +4403,7 @@ static const struct ieee80211_ops wl1271_ops = { ...@@ -4267,6 +4403,7 @@ static const struct ieee80211_ops wl1271_ops = {
.sta_remove = wl1271_op_sta_remove, .sta_remove = wl1271_op_sta_remove,
.ampdu_action = wl1271_op_ampdu_action, .ampdu_action = wl1271_op_ampdu_action,
.tx_frames_pending = wl1271_tx_frames_pending, .tx_frames_pending = wl1271_tx_frames_pending,
.set_bitrate_mask = wl12xx_set_bitrate_mask,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd) CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
}; };
...@@ -4585,6 +4722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) ...@@ -4585,6 +4722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
int i, j, ret; int i, j, ret;
unsigned int order; unsigned int order;
BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS);
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops); hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) { if (!hw) {
wl1271_error("could not alloc ieee80211_hw"); wl1271_error("could not alloc ieee80211_hw");
...@@ -4687,6 +4826,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void) ...@@ -4687,6 +4826,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
/* Apply default driver configuration. */ /* Apply default driver configuration. */
wl1271_conf_init(wl); wl1271_conf_init(wl);
wl->bitrate_masks[IEEE80211_BAND_2GHZ] = wl->conf.tx.basic_rate;
wl->bitrate_masks[IEEE80211_BAND_5GHZ] = wl->conf.tx.basic_rate_5;
order = get_order(WL1271_AGGR_BUFFER_SIZE); order = get_order(WL1271_AGGR_BUFFER_SIZE);
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include "scan.h" #include "scan.h"
#include "acx.h" #include "acx.h"
#include "ps.h" #include "ps.h"
#include "tx.h"
void wl1271_scan_complete_work(struct work_struct *work) void wl1271_scan_complete_work(struct work_struct *work)
{ {
...@@ -99,14 +100,18 @@ static int wl1271_get_scan_channels(struct wl1271 *wl, ...@@ -99,14 +100,18 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
for (i = 0, j = 0; for (i = 0, j = 0;
i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS; i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS;
i++) { i++) {
flags = req->channels[i]->flags; flags = req->channels[i]->flags;
if (!test_bit(i, wl->scan.scanned_ch) && if (!test_bit(i, wl->scan.scanned_ch) &&
!(flags & IEEE80211_CHAN_DISABLED) && !(flags & IEEE80211_CHAN_DISABLED) &&
((!!(flags & IEEE80211_CHAN_PASSIVE_SCAN)) == passive) && (req->channels[i]->band == band) &&
(req->channels[i]->band == band)) { /*
* In passive scans, we scan all remaining
* channels, even if not marked as such.
* In active scans, we only scan channels not
* marked as passive.
*/
(passive || !(flags & IEEE80211_CHAN_PASSIVE_SCAN))) {
wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ", wl1271_debug(DEBUG_SCAN, "band %d, center_freq %d ",
req->channels[i]->band, req->channels[i]->band,
req->channels[i]->center_freq); req->channels[i]->center_freq);
...@@ -158,6 +163,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -158,6 +163,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
int ret; int ret;
u16 scan_options = 0; u16 scan_options = 0;
/* skip active scans if we don't have SSIDs */
if (!passive && wl->scan.req->n_ssids == 0)
return WL1271_NOTHING_TO_SCAN;
cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
trigger = kzalloc(sizeof(*trigger), GFP_KERNEL); trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
if (!cmd || !trigger) { if (!cmd || !trigger) {
...@@ -165,8 +174,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -165,8 +174,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
goto out; goto out;
} }
/* No SSIDs means that we have a forced passive scan */ if (passive)
if (passive || wl->scan.req->n_ssids == 0)
scan_options |= WL1271_SCAN_OPT_PASSIVE; scan_options |= WL1271_SCAN_OPT_PASSIVE;
if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) { if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) {
...@@ -236,14 +244,17 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band, ...@@ -236,14 +244,17 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
void wl1271_scan_stm(struct wl1271 *wl) void wl1271_scan_stm(struct wl1271 *wl)
{ {
int ret = 0; int ret = 0;
enum ieee80211_band band;
u32 rate;
switch (wl->scan.state) { switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE: case WL1271_SCAN_STATE_IDLE:
break; break;
case WL1271_SCAN_STATE_2GHZ_ACTIVE: case WL1271_SCAN_STATE_2GHZ_ACTIVE:
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false, band = IEEE80211_BAND_2GHZ;
wl->conf.tx.basic_rate); rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
ret = wl1271_scan_send(wl, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE; wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl);
...@@ -252,8 +263,9 @@ void wl1271_scan_stm(struct wl1271 *wl) ...@@ -252,8 +263,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break; break;
case WL1271_SCAN_STATE_2GHZ_PASSIVE: case WL1271_SCAN_STATE_2GHZ_PASSIVE:
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true, band = IEEE80211_BAND_2GHZ;
wl->conf.tx.basic_rate); rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
ret = wl1271_scan_send(wl, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
if (wl->enable_11a) if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE; wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
...@@ -265,8 +277,9 @@ void wl1271_scan_stm(struct wl1271 *wl) ...@@ -265,8 +277,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break; break;
case WL1271_SCAN_STATE_5GHZ_ACTIVE: case WL1271_SCAN_STATE_5GHZ_ACTIVE:
ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false, band = IEEE80211_BAND_5GHZ;
wl->conf.tx.basic_rate_5); rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
ret = wl1271_scan_send(wl, band, false, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE; wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl);
...@@ -275,8 +288,9 @@ void wl1271_scan_stm(struct wl1271 *wl) ...@@ -275,8 +288,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
break; break;
case WL1271_SCAN_STATE_5GHZ_PASSIVE: case WL1271_SCAN_STATE_5GHZ_PASSIVE:
ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true, band = IEEE80211_BAND_5GHZ;
wl->conf.tx.basic_rate_5); rate = wl1271_tx_min_rate_get(wl, wl->bitrate_masks[band]);
ret = wl1271_scan_send(wl, band, true, rate);
if (ret == WL1271_NOTHING_TO_SCAN) { if (ret == WL1271_NOTHING_TO_SCAN) {
wl->scan.state = WL1271_SCAN_STATE_DONE; wl->scan.state = WL1271_SCAN_STATE_DONE;
wl1271_scan_stm(wl); wl1271_scan_stm(wl);
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include <linux/mmc/sdio_func.h> #include <linux/mmc/sdio_func.h>
#include <linux/mmc/sdio_ids.h> #include <linux/mmc/sdio_ids.h>
#include <linux/mmc/card.h> #include <linux/mmc/card.h>
#include <linux/mmc/host.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/wl12xx.h> #include <linux/wl12xx.h>
#include <linux/kthread.h> #include <linux/kthread.h>
...@@ -142,14 +143,23 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable) ...@@ -142,14 +143,23 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
ret = pm_runtime_get_sync(&func->dev); ret = pm_runtime_get_sync(&func->dev);
if (ret < 0) if (ret < 0)
goto out; goto out;
/* Runtime PM might be disabled, power up the card manually */
ret = mmc_power_restore_host(func->card->host);
if (ret < 0)
goto out;
sdio_claim_host(func); sdio_claim_host(func);
sdio_enable_func(func); sdio_enable_func(func);
sdio_release_host(func);
} else { } else {
sdio_claim_host(func);
sdio_disable_func(func); sdio_disable_func(func);
sdio_release_host(func); sdio_release_host(func);
/* Runtime PM might be disabled, power off the card manually */
ret = mmc_power_save_host(func->card->host);
if (ret < 0)
goto out;
/* Power down the card */ /* Power down the card */
ret = pm_runtime_put_sync(&func->dev); ret = pm_runtime_put_sync(&func->dev);
} }
...@@ -433,7 +443,6 @@ static int __devinit wl1271_probe(struct sdio_func *func, ...@@ -433,7 +443,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
sdio_set_drvdata(func, wl_test); sdio_set_drvdata(func, wl_test);
/* power up the device */ /* power up the device */
ret = wl1271_chip_wakeup(wl); ret = wl1271_chip_wakeup(wl);
if (ret) { if (ret) {
......
...@@ -81,8 +81,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl, ...@@ -81,8 +81,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
int ret; int ret;
hdr = (struct ieee80211_hdr *)(skb->data + hdr = (struct ieee80211_hdr *)skb->data;
sizeof(struct wl1271_tx_hw_descr));
/* /*
* stop bssid-based filtering before transmitting authentication * stop bssid-based filtering before transmitting authentication
...@@ -181,14 +180,20 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb) ...@@ -181,14 +180,20 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb) static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
{ {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
if (wl12xx_is_dummy_packet(wl, skb)) if (wl12xx_is_dummy_packet(wl, skb))
return wl->system_hlid; return wl->system_hlid;
if (wl->bss_type == BSS_TYPE_AP_BSS) if (wl->bss_type == BSS_TYPE_AP_BSS)
return wl12xx_tx_get_hlid_ap(wl, skb); return wl12xx_tx_get_hlid_ap(wl, skb);
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) || wl1271_tx_update_filters(wl, skb);
test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))
if ((test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags)) &&
!ieee80211_is_auth(hdr->frame_control) &&
!ieee80211_is_assoc_req(hdr->frame_control))
return wl->sta_hlid; return wl->sta_hlid;
else else
return wl->dev_hlid; return wl->dev_hlid;
...@@ -423,8 +428,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, ...@@ -423,8 +428,6 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
if (wl->bss_type == BSS_TYPE_AP_BSS) { if (wl->bss_type == BSS_TYPE_AP_BSS) {
wl1271_tx_ap_update_inconnection_sta(wl, skb); wl1271_tx_ap_update_inconnection_sta(wl, skb);
wl1271_tx_regulate_link(wl, hlid); wl1271_tx_regulate_link(wl, hlid);
} else {
wl1271_tx_update_filters(wl, skb);
} }
/* /*
...@@ -447,13 +450,14 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb, ...@@ -447,13 +450,14 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
return total_len; return total_len;
} }
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
enum ieee80211_band rate_band)
{ {
struct ieee80211_supported_band *band; struct ieee80211_supported_band *band;
u32 enabled_rates = 0; u32 enabled_rates = 0;
int bit; int bit;
band = wl->hw->wiphy->bands[wl->band]; band = wl->hw->wiphy->bands[rate_band];
for (bit = 0; bit < band->n_bitrates; bit++) { for (bit = 0; bit < band->n_bitrates; bit++) {
if (rate_set & 0x1) if (rate_set & 0x1)
enabled_rates |= band->bitrates[bit].hw_value; enabled_rates |= band->bitrates[bit].hw_value;
...@@ -986,20 +990,10 @@ void wl1271_tx_flush(struct wl1271 *wl) ...@@ -986,20 +990,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
wl1271_warning("Unable to flush all TX buffers, timed out."); wl1271_warning("Unable to flush all TX buffers, timed out.");
} }
u32 wl1271_tx_min_rate_get(struct wl1271 *wl) u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set)
{ {
int i; if (WARN_ON(!rate_set))
u32 rate = 0; return 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; return BIT(__ffs(rate_set));
} }
...@@ -209,8 +209,9 @@ void wl1271_tx_complete(struct wl1271 *wl); ...@@ -209,8 +209,9 @@ void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues); void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
void wl1271_tx_flush(struct wl1271 *wl); void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band); u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set); u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
u32 wl1271_tx_min_rate_get(struct wl1271 *wl); enum ieee80211_band rate_band);
u32 wl1271_tx_min_rate_get(struct wl1271 *wl, u32 rate_set);
u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb); u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid); void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
void wl1271_handle_tx_low_watermark(struct wl1271 *wl); void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
......
...@@ -138,7 +138,7 @@ extern u32 wl12xx_debug_level; ...@@ -138,7 +138,7 @@ extern u32 wl12xx_debug_level;
#define WL1271_DEFAULT_DTIM_PERIOD 1 #define WL1271_DEFAULT_DTIM_PERIOD 1
#define WL12XX_MAX_ROLES 4 #define WL12XX_MAX_ROLES 4
#define WL12XX_MAX_LINKS 8 #define WL12XX_MAX_LINKS 12
#define WL12XX_INVALID_ROLE_ID 0xff #define WL12XX_INVALID_ROLE_ID 0xff
#define WL12XX_INVALID_LINK_ID 0xff #define WL12XX_INVALID_LINK_ID 0xff
...@@ -279,7 +279,7 @@ struct wl12xx_fw_status { ...@@ -279,7 +279,7 @@ struct wl12xx_fw_status {
/* Cumulative counter of released Voice memory blocks */ /* Cumulative counter of released Voice memory blocks */
u8 tx_voice_released_blks; u8 tx_voice_released_blks;
u8 padding_1[7]; u8 padding_1[3];
__le32 log_start_addr; __le32 log_start_addr;
} __packed; } __packed;
...@@ -526,6 +526,7 @@ struct wl1271 { ...@@ -526,6 +526,7 @@ struct wl1271 {
u32 basic_rate_set; u32 basic_rate_set;
u32 basic_rate; u32 basic_rate;
u32 rate_set; u32 rate_set;
u32 bitrate_masks[IEEE80211_NUM_BANDS];
/* The current band */ /* The current band */
enum ieee80211_band band; enum ieee80211_band band;
......
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