Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx
This commit is contained in:
commit
85a8eefdc9
11 changed files with 274 additions and 106 deletions
|
@ -1,16 +1,16 @@
|
|||
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
|
||||
|
||||
wl12xx_spi-objs = spi.o
|
||||
wl12xx_spi-objs = spi.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
|
||||
obj-$(CONFIG_WL12XX) += wl12xx.o
|
||||
obj-$(CONFIG_WL12XX_SPI) += wl12xx_spi.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
|
||||
obj-$(CONFIG_WL12XX_PLATFORM_DATA) += wl12xx_platform_data.o
|
||||
|
|
|
@ -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);
|
||||
|
||||
/*
|
||||
* We currently do not support hidden SSID. The real SSID
|
||||
* should be fetched from mac80211 first.
|
||||
*/
|
||||
if (wl->ssid_len == 0) {
|
||||
wl1271_warning("Hidden SSID currently not supported for AP");
|
||||
/* trying to use hidden SSID with an old hostapd version */
|
||||
if (wl->ssid_len == 0 && !bss_conf->hidden_ssid) {
|
||||
wl1271_error("got a null SSID from beacon/bss");
|
||||
ret = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
@ -695,9 +692,18 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
|
|||
cmd->ap.dtim_interval = bss_conf->dtim_period;
|
||||
cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
|
||||
cmd->channel = wl->channel;
|
||||
cmd->ap.ssid_len = wl->ssid_len;
|
||||
cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
|
||||
memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
|
||||
|
||||
if (!bss_conf->hidden_ssid) {
|
||||
/* 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);
|
||||
|
||||
switch (wl->band) {
|
||||
|
@ -1106,6 +1112,7 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
|
|||
{
|
||||
struct sk_buff *skb;
|
||||
int ret;
|
||||
u32 rate;
|
||||
|
||||
skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
|
||||
ie, ie_len);
|
||||
|
@ -1116,14 +1123,13 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
|
|||
|
||||
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)
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
skb->data, skb->len, 0,
|
||||
wl->conf.tx.basic_rate);
|
||||
skb->data, skb->len, 0, rate);
|
||||
else
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
skb->data, skb->len, 0,
|
||||
wl->conf.tx.basic_rate_5);
|
||||
skb->data, skb->len, 0, rate);
|
||||
|
||||
out:
|
||||
dev_kfree_skb(skb);
|
||||
|
@ -1134,6 +1140,7 @@ struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
|
|||
struct sk_buff *skb)
|
||||
{
|
||||
int ret;
|
||||
u32 rate;
|
||||
|
||||
if (!skb)
|
||||
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,
|
|||
|
||||
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)
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
|
||||
skb->data, skb->len, 0,
|
||||
wl->conf.tx.basic_rate);
|
||||
skb->data, skb->len, 0, rate);
|
||||
else
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
|
||||
skb->data, skb->len, 0,
|
||||
wl->conf.tx.basic_rate_5);
|
||||
skb->data, skb->len, 0, rate);
|
||||
|
||||
if (ret < 0)
|
||||
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)
|
|||
sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
|
||||
|
||||
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",
|
||||
cmd->supported_rates, sta->uapsd_queues);
|
||||
|
|
|
@ -454,12 +454,10 @@ struct conf_rx_settings {
|
|||
#define CONF_TX_AP_DEFAULT_MGMT_RATES (CONF_HW_BIT_RATE_1MBPS | \
|
||||
CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
|
||||
|
||||
/*
|
||||
* Default rates for working as IBSS. use 11b rates
|
||||
*/
|
||||
/* default rates for working as IBSS (11b and OFDM) */
|
||||
#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_11MBPS);
|
||||
CONF_HW_BIT_RATE_11MBPS | CONF_TX_OFDM_RATES);
|
||||
|
||||
struct conf_tx_rate_class {
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ static void wl1271_stop_ba_event(struct wl1271 *wl)
|
|||
} else {
|
||||
int i;
|
||||
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];
|
||||
if (!wl1271_is_active_sta(wl, i) || !lnk->ba_bitmap)
|
||||
continue;
|
||||
|
|
|
@ -103,6 +103,7 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
|
|||
{
|
||||
struct wl12xx_disconn_template *tmpl;
|
||||
int ret;
|
||||
u32 rate;
|
||||
|
||||
tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
|
||||
if (!tmpl) {
|
||||
|
@ -113,9 +114,9 @@ static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
|
|||
tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_DEAUTH);
|
||||
|
||||
rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
|
||||
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
|
||||
tmpl, sizeof(*tmpl), 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
tmpl, sizeof(*tmpl), 0, rate);
|
||||
|
||||
out:
|
||||
kfree(tmpl);
|
||||
|
@ -126,6 +127,7 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
|
|||
{
|
||||
struct ieee80211_hdr_3addr *nullfunc;
|
||||
int ret;
|
||||
u32 rate;
|
||||
|
||||
nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
|
||||
if (!nullfunc) {
|
||||
|
@ -142,9 +144,9 @@ static int wl1271_ap_init_null_template(struct wl1271 *wl)
|
|||
memcpy(nullfunc->addr2, 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,
|
||||
sizeof(*nullfunc), 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
sizeof(*nullfunc), 0, rate);
|
||||
|
||||
out:
|
||||
kfree(nullfunc);
|
||||
|
@ -155,6 +157,7 @@ static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
|
|||
{
|
||||
struct ieee80211_qos_hdr *qosnull;
|
||||
int ret;
|
||||
u32 rate;
|
||||
|
||||
qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
|
||||
if (!qosnull) {
|
||||
|
@ -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->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,
|
||||
sizeof(*qosnull), 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
sizeof(*qosnull), 0, rate);
|
||||
|
||||
out:
|
||||
kfree(qosnull);
|
||||
|
@ -498,7 +501,7 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
|
|||
return ret;
|
||||
|
||||
/* 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.long_retry_limit = 10;
|
||||
rc.aflags = 0;
|
||||
|
|
|
@ -2099,6 +2099,8 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
|
|||
wl->time_offset = 0;
|
||||
wl->session_counter = 0;
|
||||
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->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
|
||||
wl1271_free_ap_keys(wl);
|
||||
|
@ -2237,14 +2239,8 @@ static int wl1271_unjoin(struct wl1271 *wl)
|
|||
|
||||
static void wl1271_set_band_rate(struct wl1271 *wl)
|
||||
{
|
||||
if (wl->band == IEEE80211_BAND_2GHZ) {
|
||||
wl->basic_rate_set = wl->conf.tx.basic_rate;
|
||||
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;
|
||||
}
|
||||
|
||||
wl->basic_rate_set = wl->bitrate_masks[wl->band];
|
||||
wl->rate_set = wl->basic_rate_set;
|
||||
}
|
||||
|
||||
static bool wl12xx_is_roc(struct wl1271 *wl)
|
||||
|
@ -2273,7 +2269,7 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
|
|||
if (ret < 0)
|
||||
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);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -2355,6 +2351,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
if (changed & IEEE80211_CONF_CHANGE_CHANNEL &&
|
||||
((wl->band != conf->channel->band) ||
|
||||
(wl->channel != channel))) {
|
||||
/* send all pending packets */
|
||||
wl1271_tx_work_locked(wl);
|
||||
wl->band = conf->channel->band;
|
||||
wl->channel = channel;
|
||||
|
||||
|
@ -2368,7 +2366,8 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
|
|||
if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
|
||||
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);
|
||||
if (ret < 0)
|
||||
wl1271_warning("rate policy for channel "
|
||||
|
@ -3069,6 +3068,93 @@ static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
|
|||
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,
|
||||
struct ieee80211_bss_conf *bss_conf,
|
||||
u32 changed)
|
||||
|
@ -3125,6 +3211,7 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
|
|||
|
||||
if ((changed & BSS_CHANGED_BEACON)) {
|
||||
struct ieee80211_hdr *hdr;
|
||||
u32 min_rate;
|
||||
int ieoffset = offsetof(struct ieee80211_mgmt,
|
||||
u.beacon.variable);
|
||||
struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
|
||||
|
@ -3140,28 +3227,46 @@ static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
|
|||
dev_kfree_skb(beacon);
|
||||
goto out;
|
||||
}
|
||||
min_rate = wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
|
||||
tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
|
||||
CMD_TEMPL_BEACON;
|
||||
ret = wl1271_cmd_template_set(wl, tmpl_id,
|
||||
beacon->data,
|
||||
beacon->len, 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
min_rate);
|
||||
if (ret < 0) {
|
||||
dev_kfree_skb(beacon);
|
||||
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->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
|
||||
IEEE80211_STYPE_PROBE_RESP);
|
||||
|
||||
tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
|
||||
CMD_TEMPL_PROBE_RESPONSE;
|
||||
ret = wl1271_cmd_template_set(wl,
|
||||
tmpl_id,
|
||||
beacon->data,
|
||||
beacon->len, 0,
|
||||
wl1271_tx_min_rate_get(wl));
|
||||
if (is_ap)
|
||||
ret = wl1271_ap_set_probe_resp_tmpl(wl,
|
||||
beacon->data,
|
||||
beacon->len,
|
||||
min_rate);
|
||||
else
|
||||
ret = wl1271_cmd_template_set(wl,
|
||||
CMD_TEMPL_PROBE_RESPONSE,
|
||||
beacon->data,
|
||||
beacon->len, 0,
|
||||
min_rate);
|
||||
dev_kfree_skb(beacon);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -3182,8 +3287,10 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
|
|||
if ((changed & BSS_CHANGED_BASIC_RATES)) {
|
||||
u32 rates = bss_conf->basic_rates;
|
||||
|
||||
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
|
||||
wl->basic_rate = wl1271_tx_min_rate_get(wl);
|
||||
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates,
|
||||
wl->band);
|
||||
wl->basic_rate = wl1271_tx_min_rate_get(wl,
|
||||
wl->basic_rate_set);
|
||||
|
||||
ret = wl1271_init_ap_rates(wl);
|
||||
if (ret < 0) {
|
||||
|
@ -3365,12 +3472,15 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
* 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_tx_min_rate_get(wl);
|
||||
wl->basic_rate_set =
|
||||
wl1271_tx_enabled_rates_get(wl, rates,
|
||||
wl->band);
|
||||
wl->basic_rate =
|
||||
wl1271_tx_min_rate_get(wl, wl->basic_rate_set);
|
||||
if (sta_rate_set)
|
||||
wl->rate_set = wl1271_tx_enabled_rates_get(wl,
|
||||
sta_rate_set);
|
||||
sta_rate_set,
|
||||
wl->band);
|
||||
ret = wl1271_acx_sta_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -3417,7 +3527,8 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
|
||||
/* revert back to minimum rates for the current band */
|
||||
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);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
@ -3468,11 +3579,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
|
|||
|
||||
if (bss_conf->ibss_joined) {
|
||||
u32 rates = bss_conf->basic_rates;
|
||||
wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
|
||||
rates);
|
||||
wl->basic_rate = wl1271_tx_min_rate_get(wl);
|
||||
wl->basic_rate_set =
|
||||
wl1271_tx_enabled_rates_get(wl, rates,
|
||||
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;
|
||||
ret = wl1271_acx_sta_rate_policies(wl);
|
||||
if (ret < 0)
|
||||
|
@ -3992,6 +4105,29 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
|
|||
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)
|
||||
{
|
||||
struct wl1271 *wl = hw->priv;
|
||||
|
@ -4267,6 +4403,7 @@ static const struct ieee80211_ops wl1271_ops = {
|
|||
.sta_remove = wl1271_op_sta_remove,
|
||||
.ampdu_action = wl1271_op_ampdu_action,
|
||||
.tx_frames_pending = wl1271_tx_frames_pending,
|
||||
.set_bitrate_mask = wl12xx_set_bitrate_mask,
|
||||
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
|
||||
};
|
||||
|
||||
|
@ -4585,6 +4722,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
|
|||
int i, j, ret;
|
||||
unsigned int order;
|
||||
|
||||
BUILD_BUG_ON(AP_MAX_LINKS > WL12XX_MAX_LINKS);
|
||||
|
||||
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
|
||||
if (!hw) {
|
||||
wl1271_error("could not alloc ieee80211_hw");
|
||||
|
@ -4687,6 +4826,8 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
|
|||
|
||||
/* Apply default driver configuration. */
|
||||
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);
|
||||
wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order);
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#include "scan.h"
|
||||
#include "acx.h"
|
||||
#include "ps.h"
|
||||
#include "tx.h"
|
||||
|
||||
void wl1271_scan_complete_work(struct work_struct *work)
|
||||
{
|
||||
|
@ -99,14 +100,18 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
|
|||
for (i = 0, j = 0;
|
||||
i < req->n_channels && j < WL1271_SCAN_MAX_CHANNELS;
|
||||
i++) {
|
||||
|
||||
flags = req->channels[i]->flags;
|
||||
|
||||
if (!test_bit(i, wl->scan.scanned_ch) &&
|
||||
!(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 ",
|
||||
req->channels[i]->band,
|
||||
req->channels[i]->center_freq);
|
||||
|
@ -158,6 +163,10 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
|
|||
int ret;
|
||||
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);
|
||||
trigger = kzalloc(sizeof(*trigger), GFP_KERNEL);
|
||||
if (!cmd || !trigger) {
|
||||
|
@ -165,8 +174,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
|
|||
goto out;
|
||||
}
|
||||
|
||||
/* No SSIDs means that we have a forced passive scan */
|
||||
if (passive || wl->scan.req->n_ssids == 0)
|
||||
if (passive)
|
||||
scan_options |= WL1271_SCAN_OPT_PASSIVE;
|
||||
|
||||
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,
|
|||
void wl1271_scan_stm(struct wl1271 *wl)
|
||||
{
|
||||
int ret = 0;
|
||||
enum ieee80211_band band;
|
||||
u32 rate;
|
||||
|
||||
switch (wl->scan.state) {
|
||||
case WL1271_SCAN_STATE_IDLE:
|
||||
break;
|
||||
|
||||
case WL1271_SCAN_STATE_2GHZ_ACTIVE:
|
||||
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, false,
|
||||
wl->conf.tx.basic_rate);
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
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) {
|
||||
wl->scan.state = WL1271_SCAN_STATE_2GHZ_PASSIVE;
|
||||
wl1271_scan_stm(wl);
|
||||
|
@ -252,8 +263,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
|
|||
break;
|
||||
|
||||
case WL1271_SCAN_STATE_2GHZ_PASSIVE:
|
||||
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
|
||||
wl->conf.tx.basic_rate);
|
||||
band = IEEE80211_BAND_2GHZ;
|
||||
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 (wl->enable_11a)
|
||||
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
|
||||
|
@ -265,8 +277,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
|
|||
break;
|
||||
|
||||
case WL1271_SCAN_STATE_5GHZ_ACTIVE:
|
||||
ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, false,
|
||||
wl->conf.tx.basic_rate_5);
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
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) {
|
||||
wl->scan.state = WL1271_SCAN_STATE_5GHZ_PASSIVE;
|
||||
wl1271_scan_stm(wl);
|
||||
|
@ -275,8 +288,9 @@ void wl1271_scan_stm(struct wl1271 *wl)
|
|||
break;
|
||||
|
||||
case WL1271_SCAN_STATE_5GHZ_PASSIVE:
|
||||
ret = wl1271_scan_send(wl, IEEE80211_BAND_5GHZ, true,
|
||||
wl->conf.tx.basic_rate_5);
|
||||
band = IEEE80211_BAND_5GHZ;
|
||||
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) {
|
||||
wl->scan.state = WL1271_SCAN_STATE_DONE;
|
||||
wl1271_scan_stm(wl);
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
#include <linux/mmc/sdio_func.h>
|
||||
#include <linux/mmc/sdio_ids.h>
|
||||
#include <linux/mmc/card.h>
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <linux/wl12xx.h>
|
||||
#include <linux/kthread.h>
|
||||
|
@ -142,14 +143,23 @@ static int wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
|
|||
ret = pm_runtime_get_sync(&func->dev);
|
||||
if (ret < 0)
|
||||
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_enable_func(func);
|
||||
sdio_release_host(func);
|
||||
} else {
|
||||
sdio_claim_host(func);
|
||||
sdio_disable_func(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 */
|
||||
ret = pm_runtime_put_sync(&func->dev);
|
||||
}
|
||||
|
@ -433,7 +443,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
|
|||
|
||||
sdio_set_drvdata(func, wl_test);
|
||||
|
||||
|
||||
/* power up the device */
|
||||
ret = wl1271_chip_wakeup(wl);
|
||||
if (ret) {
|
||||
|
|
|
@ -81,8 +81,7 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
|
|||
struct ieee80211_hdr *hdr;
|
||||
int ret;
|
||||
|
||||
hdr = (struct ieee80211_hdr *)(skb->data +
|
||||
sizeof(struct wl1271_tx_hw_descr));
|
||||
hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
/*
|
||||
* stop bssid-based filtering before transmitting authentication
|
||||
|
@ -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)
|
||||
{
|
||||
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
||||
|
||||
if (wl12xx_is_dummy_packet(wl, skb))
|
||||
return wl->system_hlid;
|
||||
|
||||
if (wl->bss_type == BSS_TYPE_AP_BSS)
|
||||
return wl12xx_tx_get_hlid_ap(wl, skb);
|
||||
|
||||
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
|
||||
test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))
|
||||
wl1271_tx_update_filters(wl, skb);
|
||||
|
||||
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;
|
||||
else
|
||||
return wl->dev_hlid;
|
||||
|
@ -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) {
|
||||
wl1271_tx_ap_update_inconnection_sta(wl, skb);
|
||||
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,
|
|||
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;
|
||||
u32 enabled_rates = 0;
|
||||
int bit;
|
||||
|
||||
band = wl->hw->wiphy->bands[wl->band];
|
||||
band = wl->hw->wiphy->bands[rate_band];
|
||||
for (bit = 0; bit < band->n_bitrates; bit++) {
|
||||
if (rate_set & 0x1)
|
||||
enabled_rates |= band->bitrates[bit].hw_value;
|
||||
|
@ -986,20 +990,10 @@ void wl1271_tx_flush(struct wl1271 *wl)
|
|||
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;
|
||||
u32 rate = 0;
|
||||
if (WARN_ON(!rate_set))
|
||||
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);
|
|||
void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
|
||||
void wl1271_tx_flush(struct wl1271 *wl);
|
||||
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_min_rate_get(struct wl1271 *wl);
|
||||
u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set,
|
||||
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);
|
||||
void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
|
||||
void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
|
||||
|
|
|
@ -138,7 +138,7 @@ extern u32 wl12xx_debug_level;
|
|||
#define WL1271_DEFAULT_DTIM_PERIOD 1
|
||||
|
||||
#define WL12XX_MAX_ROLES 4
|
||||
#define WL12XX_MAX_LINKS 8
|
||||
#define WL12XX_MAX_LINKS 12
|
||||
#define WL12XX_INVALID_ROLE_ID 0xff
|
||||
#define WL12XX_INVALID_LINK_ID 0xff
|
||||
|
||||
|
@ -279,7 +279,7 @@ struct wl12xx_fw_status {
|
|||
|
||||
/* Cumulative counter of released Voice memory blocks */
|
||||
u8 tx_voice_released_blks;
|
||||
u8 padding_1[7];
|
||||
u8 padding_1[3];
|
||||
__le32 log_start_addr;
|
||||
} __packed;
|
||||
|
||||
|
@ -526,6 +526,7 @@ struct wl1271 {
|
|||
u32 basic_rate_set;
|
||||
u32 basic_rate;
|
||||
u32 rate_set;
|
||||
u32 bitrate_masks[IEEE80211_NUM_BANDS];
|
||||
|
||||
/* The current band */
|
||||
enum ieee80211_band band;
|
||||
|
|
Loading…
Reference in a new issue