aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn W. Linville2011-09-16 16:20:43 -0400
committerJohn W. Linville2011-09-16 16:20:43 -0400
commitbd1a272806e6554c54959f2b46f6d40c182468c0 (patch)
treed254c7bac34710948cb6250e12b391a442ca2604
parent55768fa6d9462c18c1ce3c862db3bf55bac3b1c7 (diff)
parentc6ceb8726f0cee28c6ff1101e6c326e6d86ea749 (diff)
Merge branch 'for-linville' of git://github.com/lucacoelho/wl12xx
-rw-r--r--drivers/net/wireless/wl12xx/boot.c4
-rw-r--r--drivers/net/wireless/wl12xx/main.c50
-rw-r--r--drivers/net/wireless/wl12xx/scan.c66
-rw-r--r--drivers/net/wireless/wl12xx/tx.c8
-rw-r--r--drivers/net/wireless/wl12xx/tx.h1
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h3
6 files changed, 103 insertions, 29 deletions
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index cc70422c0575..6d5664bfc37d 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -294,9 +294,7 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
*/
if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
- /* for now 11a is unsupported in AP mode */
- if (wl->bss_type != BSS_TYPE_AP_BSS &&
- nvs->general_params.dual_mode_select)
+ if (nvs->general_params.dual_mode_select)
wl->enable_11a = true;
}
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 82f4408e89ad..bde84027ab7f 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -236,7 +236,7 @@ static struct conf_drv_settings default_conf = {
.ps_poll_recovery_period = 700,
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 50,
- .psm_entry_retries = 5,
+ .psm_entry_retries = 8,
.psm_exit_retries = 16,
.psm_entry_nullfunc_retries = 3,
.psm_entry_hangover_period = 1,
@@ -2064,6 +2064,7 @@ deinit:
wl->session_counter = 0;
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->vif = NULL;
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl1271_free_ap_keys(wl);
memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
wl->ap_fw_ps_map = 0;
@@ -2199,10 +2200,14 @@ out:
static void wl1271_set_band_rate(struct wl1271 *wl)
{
- if (wl->band == IEEE80211_BAND_2GHZ)
+ if (wl->band == IEEE80211_BAND_2GHZ) {
wl->basic_rate_set = wl->conf.tx.basic_rate;
- else
+ 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)
@@ -2653,6 +2658,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
+ /*
+ * A STA set to GEM cipher requires 2 tx spare blocks.
+ * Return to default value when GEM cipher key is removed
+ */
+ if (key_type == KEY_GEM) {
+ if (action == KEY_ADD_OR_REPLACE)
+ wl->tx_spare_blocks = 2;
+ else if (action == KEY_REMOVE)
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+ }
+
addr = sta ? sta->addr : bcast_addr;
if (is_zero_ether_addr(addr)) {
@@ -3345,19 +3361,6 @@ sta_not_found:
ret = wl1271_acx_conn_monit_params(wl, true);
if (ret < 0)
goto out;
-
- /* If we want to go in PSM but we're not there yet */
- if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
- !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- enum wl1271_cmd_ps_mode mode;
-
- mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode,
- wl->basic_rate,
- true);
- if (ret < 0)
- goto out;
- }
} else {
/* use defaults when not associated */
bool was_assoc =
@@ -3501,6 +3504,19 @@ sta_not_found:
if (ret < 0)
goto out;
}
+
+ /* If we want to go in PSM but we're not there yet */
+ if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
+ !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+ enum wl1271_cmd_ps_mode mode;
+
+ mode = STATION_POWER_SAVE_MODE;
+ ret = wl1271_ps_set_mode(wl, mode,
+ wl->basic_rate,
+ true);
+ if (ret < 0)
+ goto out;
+ }
}
/* Handle new association with HT. Do this after join. */
@@ -4475,6 +4491,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
wl->hw->wiphy->max_scan_ssids = 1;
+ wl->hw->wiphy->max_sched_scan_ssids = 8;
/*
* Maximum length of elements in scanning probe request templates
* should be the maximum length possible for a template, without
@@ -4599,6 +4616,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->sched_scanning = false;
wl->tx_security_seq = 0;
wl->tx_security_last_seq_lsb = 0;
+ wl->tx_spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
wl->role_id = WL12XX_INVALID_ROLE_ID;
wl->system_hlid = WL12XX_SYSTEM_HLID;
wl->sta_hlid = WL12XX_INVALID_LINK_ID;
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 7229eaa89018..af4ad2353f59 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -473,6 +473,51 @@ wl1271_scan_sched_scan_channels(struct wl1271 *wl,
cfg->passive[2] || cfg->active[2];
}
+/* Returns 0 if no wildcard is used, 1 if wildcard is used or a
+ * negative value on error */
+static int
+wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl,
+ struct cfg80211_sched_scan_request *req)
+{
+ struct wl1271_cmd_sched_scan_ssid_list *cmd = NULL;
+ struct cfg80211_ssid *ssid = req->ssids;
+ int ret, wildcard = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd sched scan ssid list");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd)
+ return -ENOMEM;
+
+ while ((cmd->n_ssids < req->n_ssids) && ssid) {
+ if (ssid->ssid_len == 0) {
+ wildcard = 1;
+ cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_PUBLIC;
+ } else {
+ cmd->ssids[cmd->n_ssids].type = SCAN_SSID_TYPE_HIDDEN;
+ }
+ cmd->ssids[cmd->n_ssids].len = ssid->ssid_len;
+ memcpy(cmd->ssids[cmd->n_ssids].ssid, ssid->ssid,
+ ssid->ssid_len);
+ ssid++;
+ cmd->n_ssids++;
+ }
+
+ wl1271_dump(DEBUG_SCAN, "SSID_LIST: ", cmd, sizeof(*cmd));
+
+ ret = wl1271_cmd_send(wl, CMD_CONNECTION_SCAN_SSID_CFG, cmd,
+ sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("cmd sched scan ssid list failed");
+ goto out;
+ }
+
+ ret = wildcard;
+out:
+ kfree(cmd);
+ return ret;
+}
+
int wl1271_scan_sched_scan_config(struct wl1271 *wl,
struct cfg80211_sched_scan_request *req,
struct ieee80211_sched_scan_ies *ies)
@@ -504,14 +549,21 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
for (i = 0; i < SCAN_MAX_CYCLE_INTERVALS; i++)
cfg->intervals[i] = cpu_to_le32(req->interval);
- if (!force_passive && req->ssids[0].ssid_len && req->ssids[0].ssid) {
- cfg->filter_type = SCAN_SSID_FILTER_SPECIFIC;
- cfg->ssid_len = req->ssids[0].ssid_len;
- memcpy(cfg->ssid, req->ssids[0].ssid,
- req->ssids[0].ssid_len);
- } else {
+ cfg->ssid_len = 0;
+ if (req->n_ssids == 0) {
+ wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_ANY");
cfg->filter_type = SCAN_SSID_FILTER_ANY;
- cfg->ssid_len = 0;
+ } else {
+ ret = wl12xx_scan_sched_scan_ssid_list(wl, req);
+ if (ret < 0)
+ goto out;
+ if (ret) {
+ wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_DISABLED");
+ cfg->filter_type = SCAN_SSID_FILTER_DISABLED;
+ } else {
+ wl1271_debug(DEBUG_SCAN, "using SCAN_SSID_FILTER_LIST");
+ cfg->filter_type = SCAN_SSID_FILTER_LIST;
+ }
}
if (!wl1271_scan_sched_scan_channels(wl, req, cfg)) {
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 0f1578577b1a..08227e69616b 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -204,9 +204,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
u32 len;
u32 total_blocks;
int id, ret = -EBUSY, ac;
-
- /* we use 1 spare block */
- u32 spare_blocks = 1;
+ u32 spare_blocks = wl->tx_spare_blocks;
if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
return -EAGAIN;
@@ -220,6 +218,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
in the firmware */
len = wl12xx_calc_packet_alignment(wl, total_len);
+ /* in case of a dummy packet, use default amount of spare mem blocks */
+ if (unlikely(wl12xx_is_dummy_packet(wl, skb)))
+ spare_blocks = TX_HW_BLOCK_SPARE_DEFAULT;
+
total_blocks = (len + TX_HW_BLOCK_SIZE - 1) / TX_HW_BLOCK_SIZE +
spare_blocks;
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 7da35c0e411b..6519be4b2c38 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -25,6 +25,7 @@
#ifndef __TX_H__
#define __TX_H__
+#define TX_HW_BLOCK_SPARE_DEFAULT 1
#define TX_HW_BLOCK_SIZE 252
#define TX_HW_MGMT_PKT_LIFETIME_TU 2000
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 61a7c2163ea2..fb2753c46300 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -425,6 +425,9 @@ struct wl1271 {
u32 tx_allocated_blocks;
u32 tx_results_count;
+ /* amount of spare TX blocks to use */
+ u32 tx_spare_blocks;
+
/* Accounting for allocated / available Tx packets in HW */
u32 tx_pkts_freed[NUM_TX_QUEUES];
u32 tx_allocated_pkts[NUM_TX_QUEUES];