Hi,
These patches have been pending on our internal tree (for way too long, I have
to admit). The reason was that I couldn't test these patches before submitting
them upstream.
I have applied all these patches to the new wl12xx git tree [1]. I'll send a
pull request to John shortly.
John, no need to apply this, as I'll send them as part of a pull request.
Cheers,
Luca.
[1] git://git.kernel.org/pub/scm/linux/kernel/git/luca/wl12xx.git
Juuso Oikarinen (22):
wl1271: Implement CMD_SET_STA_STATE to indicate connection completion
to FW
wl1271: Add trigger to net_device oper_state to change BT coex
priority
wl1271: Fix scan race condition
wl1271: Change supported channel order for a more optimal scan
wl1271: Remove outdated FIXME's
wl1271: Move setting of wake-up conditions to ps.c from cmd.c
wl1271: Remove acx_fw_version function
wl1271: Release interrupt *after* releasing the driver context
wl1271: Remove function cmd_read_memory
wl1271: Enable/disable 11a support based on INI configuration
wl1271: Reduce rate used for last PSM entry attempt
wl1271: Enable 11a support always, prevent scanning for unsupporting
chips
wl1271: Add support for hardware GEM cipher
wl1271: Fix tid-configuration of TX frames
wl1271: Fix AC/TID default configuration
wl1271: Move scan complete invocation into work function
wl1271: Fix work cancelling when shutting down the driver
wl1271: Separate interface removal to another function
wl1271: Add hardware recovery mechanism
wl1271: Add handling for failing hardware scan command
wl1271: Optimize scan duration
wl1271: Increase connection reliability
Luciano Coelho (3):
wl1271: remove deprecated ACX definition
wl1271: remove useless 11a check when scanning
wl1271: fix forced passive scan
drivers/net/wireless/wl12xx/wl1271.h | 24 +-
drivers/net/wireless/wl12xx/wl1271_acx.c | 34 ---
drivers/net/wireless/wl12xx/wl1271_acx.h | 31 ---
drivers/net/wireless/wl12xx/wl1271_boot.c | 39 ++-
drivers/net/wireless/wl12xx/wl1271_cmd.c | 89 +++----
drivers/net/wireless/wl12xx/wl1271_cmd.h | 49 +---
drivers/net/wireless/wl12xx/wl1271_conf.h | 57 ++++-
drivers/net/wireless/wl12xx/wl1271_event.c | 15 +-
drivers/net/wireless/wl12xx/wl1271_init.c | 35 ++--
drivers/net/wireless/wl12xx/wl1271_main.c | 358 ++++++++++++++++---------
drivers/net/wireless/wl12xx/wl1271_ps.c | 20 ++-
drivers/net/wireless/wl12xx/wl1271_ps.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_scan.c | 79 +++++-
drivers/net/wireless/wl12xx/wl1271_scan.h | 6 +-
drivers/net/wireless/wl12xx/wl1271_sdio.c | 3 +-
drivers/net/wireless/wl12xx/wl1271_spi.c | 3 +-
drivers/net/wireless/wl12xx/wl1271_testmode.c | 14 +-
drivers/net/wireless/wl12xx/wl1271_tx.c | 6 +-
drivers/net/wireless/wl12xx/wl1271_tx.h | 17 --
19 files changed, 486 insertions(+), 395 deletions(-)
This code was a leftover of the previous scanning mechanism. The if is
totally unnecessary, since both branches do the same thing.
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 5 +----
1 files changed, 1 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 02ad6c6..b42ee48 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1624,10 +1624,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
if (ret < 0)
goto out;
- if (wl1271_11a_enabled())
- ret = wl1271_scan(hw->priv, ssid, len, req);
- else
- ret = wl1271_scan(hw->priv, ssid, len, req);
+ ret = wl1271_scan(hw->priv, ssid, len, req);
wl1271_ps_elp_sleep(wl);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Incorrect TID was configured for TX frames. This resulted in incorrect
queues to be used for classes in transmission.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_tx.c | 4 ++--
drivers/net/wireless/wl12xx/wl1271_tx.h | 17 -----------------
2 files changed, 2 insertions(+), 19 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 0f99eff..1b8295c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -110,9 +110,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
/* configure the tx attributes */
tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
- /* queue */
+ /* queue (we use same identifiers for tid's and ac's */
ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
- desc->tid = wl1271_tx_ac_to_tid(ac);
+ desc->tid = ac;
desc->aid = TX_HW_DEFAULT_AID;
desc->reserved = 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index 48bf926..d12a129 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -139,23 +139,6 @@ static inline int wl1271_tx_get_queue(int queue)
}
}
-/* wl1271 tx descriptor needs the tid and we need to convert it from ac */
-static inline int wl1271_tx_ac_to_tid(int ac)
-{
- switch (ac) {
- case 0:
- return 0;
- case 1:
- return 2;
- case 2:
- return 4;
- case 3:
- return 6;
- default:
- return 0;
- }
-}
-
void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_reset(struct wl1271 *wl);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Instead of hardcoding 11a support, enable/disable driver support based on
the dual-mode-select parameter in the nvs-file general paramters.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 18 +++---------------
drivers/net/wireless/wl12xx/wl1271_boot.c | 22 ++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_init.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 18 +++---------------
drivers/net/wireless/wl12xx/wl1271_scan.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_testmode.c | 14 +-------------
6 files changed, 31 insertions(+), 45 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 1098d16..763ece8 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -117,11 +117,6 @@ enum {
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
-/*
- * Enable/disable 802.11a support for WL1273
- */
-#undef WL1271_80211A_ENABLED
-
#define WL1271_BUSY_WORD_CNT 1
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
@@ -363,6 +358,7 @@ struct wl1271 {
u8 *fw;
size_t fw_len;
struct wl1271_nvs_file *nvs;
+ size_t nvs_len;
s8 hw_pg_ver;
@@ -476,6 +472,8 @@ struct wl1271 {
bool sg_enabled;
+ bool enable_11a;
+
struct list_head list;
/* Most recently reported noise in dBm */
@@ -499,14 +497,4 @@ int wl1271_plt_stop(struct wl1271 *wl);
#define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
#define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
-static inline bool wl1271_11a_enabled(void)
-{
- /* FIXME: this could be determined based on the NVS-INI file */
-#ifdef WL1271_80211A_ENABLED
- return true;
-#else
- return false;
-#endif
-}
-
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index f750d5a..b910212 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
if (wl->nvs == NULL)
return -ENODEV;
+ /*
+ * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
+ * configurations) can be removed when those NVS files stop floating
+ * around.
+ */
+ if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
+ wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
+ if (wl->nvs->general_params.dual_mode_select)
+ wl->enable_11a = true;
+ }
+
+ if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
+ (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
+ wl->enable_11a)) {
+ wl1271_error("nvs size is not as expected: %zu != %zu",
+ wl->nvs_len, sizeof(struct wl1271_nvs_file));
+ kfree(wl->nvs);
+ wl->nvs = NULL;
+ wl->nvs_len = 0;
+ return -EILSEQ;
+ }
+
/* only the first part of the NVS needs to be uploaded */
nvs_len = sizeof(wl->nvs->nvs);
nvs_ptr = (u8 *)wl->nvs->nvs;
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 4447af1..879bae0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -61,7 +61,7 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if (ret < 0)
return ret;
- if (wl1271_11a_enabled()) {
+ if (wl->enable_11a) {
size_t size = sizeof(struct wl12xx_probe_req_template);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
NULL, size, 0,
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index bbd075a..11e112f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -622,20 +622,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
return ret;
}
- /*
- * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
- * configurations) can be removed when those NVS files stop floating
- * around.
- */
- if (fw->size != sizeof(struct wl1271_nvs_file) &&
- (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
- wl1271_11a_enabled())) {
- wl1271_error("nvs size is not as expected: %zu != %zu",
- fw->size, sizeof(struct wl1271_nvs_file));
- ret = -EILSEQ;
- goto out;
- }
-
wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file), GFP_KERNEL);
if (!wl->nvs) {
@@ -644,6 +630,8 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
goto out;
}
+ wl->nvs_len = fw->size;
+
out:
release_firmware(fw);
@@ -2414,7 +2402,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
- if (wl1271_11a_enabled())
+ if (wl->enable_11a)
wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
wl->hw->queues = 4;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 7f42ca9..8d30150 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -188,7 +188,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
wl->conf.tx.basic_rate);
if (ret == WL1271_NOTHING_TO_SCAN) {
- if (wl1271_11a_enabled())
+ if (wl->enable_11a)
wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
else
wl->scan.state = WL1271_SCAN_STATE_DONE;
diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c b/drivers/net/wireless/wl12xx/wl1271_testmode.c
index 6e0952f..a3aa843 100644
--- a/drivers/net/wireless/wl12xx/wl1271_testmode.c
+++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c
@@ -199,19 +199,6 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
len = nla_len(tb[WL1271_TM_ATTR_DATA]);
- /*
- * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz band
- * configurations) can be removed when those NVS files stop floating
- * around.
- */
- if (len != sizeof(struct wl1271_nvs_file) &&
- (len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
- wl1271_11a_enabled())) {
- wl1271_error("nvs size is not as expected: %zu != %zu",
- len, sizeof(struct wl1271_nvs_file));
- return -EMSGSIZE;
- }
-
mutex_lock(&wl->mutex);
kfree(wl->nvs);
@@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271 *wl, struct nlattr *tb[])
}
memcpy(wl->nvs, buf, len);
+ wl->nvs_len = len;
wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Currently, the driver does not handle a failing hardware command to scan in
any way - effectively, the scan machine will jam until the driver is shut down,
and future scan requests will just return -EBUSY to user space, resulting in
a type of busy-loop. The same problem occurs if the firmware fails to deliver
the scan completion event - add timeout for this.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 3 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 4 +-
drivers/net/wireless/wl12xx/wl1271_scan.c | 30 +++++++++++++++++++++++++---
drivers/net/wireless/wl12xx/wl1271_scan.h | 2 +
4 files changed, 32 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index b5369a6..6eb96ce 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -298,6 +298,7 @@ struct wl1271_rx_mem_pool_addr {
struct wl1271_scan {
struct cfg80211_scan_request *req;
bool *scanned_ch;
+ bool failed;
u8 state;
u8 ssid[IW_ESSID_MAX_SIZE+1];
size_t ssid_len;
@@ -421,7 +422,7 @@ struct wl1271 {
/* Are we currently scanning */
struct wl1271_scan scan;
- struct work_struct scan_complete_work;
+ struct delayed_work scan_complete_work;
/* Our association ID */
u16 aid;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 6e98c75..3f4e154 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -657,8 +657,8 @@ static int wl1271_setup(struct wl1271 *wl)
INIT_WORK(&wl->irq_work, wl1271_irq_work);
INIT_WORK(&wl->tx_work, wl1271_tx_work);
- INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
+ INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
return 0;
}
@@ -1013,7 +1013,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl)
mutex_unlock(&wl->mutex);
- cancel_work_sync(&wl->scan_complete_work);
+ cancel_delayed_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_delayed_work_sync(&wl->pspoll_work);
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 20caceb..37f9ccb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -30,8 +30,11 @@
void wl1271_scan_complete_work(struct work_struct *work)
{
- struct wl1271 *wl =
- container_of(work, struct wl1271, scan_complete_work);
+ struct delayed_work *dwork;
+ struct wl1271 *wl;
+
+ dwork = container_of(work, struct delayed_work, work);
+ wl = container_of(dwork, struct wl1271, scan_complete_work);
wl1271_debug(DEBUG_SCAN, "Scanning complete");
@@ -48,6 +51,11 @@ void wl1271_scan_complete_work(struct work_struct *work)
mutex_unlock(&wl->mutex);
ieee80211_scan_completed(wl->hw, false);
+
+ if (wl->scan.failed) {
+ wl1271_info("Scan completed due to error.");
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
+ }
}
@@ -191,7 +199,7 @@ out:
void wl1271_scan_stm(struct wl1271 *wl)
{
- int ret;
+ int ret = 0;
switch (wl->scan.state) {
case WL1271_SCAN_STATE_IDLE:
@@ -241,13 +249,22 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_DONE:
- ieee80211_queue_work(wl->hw, &wl->scan_complete_work);
+ wl->scan.failed = false;
+ cancel_delayed_work(&wl->scan_complete_work);
+ ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+ msecs_to_jiffies(0));
break;
default:
wl1271_error("invalid scan state");
break;
}
+
+ if (ret < 0) {
+ cancel_delayed_work(&wl->scan_complete_work);
+ ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+ msecs_to_jiffies(0));
+ }
}
int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
@@ -270,6 +287,11 @@ int wl1271_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
wl->scan.scanned_ch = kzalloc(req->n_channels *
sizeof(*wl->scan.scanned_ch),
GFP_KERNEL);
+ /* we assume failure so that timeout scenarios are handled correctly */
+ wl->scan.failed = true;
+ ieee80211_queue_delayed_work(wl->hw, &wl->scan_complete_work,
+ msecs_to_jiffies(WL1271_SCAN_TIMEOUT));
+
wl1271_scan_stm(wl);
return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h
index 1404e00..bb7af2a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.h
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
@@ -46,6 +46,8 @@ void wl1271_scan_complete_work(struct work_struct *work);
#define WL1271_SCAN_BAND_5_GHZ 1
#define WL1271_SCAN_PROBE_REQS 3
+#define WL1271_SCAN_TIMEOUT 10000 /* msec */
+
enum {
WL1271_SCAN_STATE_IDLE,
WL1271_SCAN_STATE_2GHZ_ACTIVE,
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Implement the command function to send CMD_SET_STA_STATE to the firmware. This
is used to indicate that association (and the related EAP negotiation) are
complete.
This is used to tune WLAN-BT coexistense priority towards BT, improving BT
A2DP and SCO performance.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 28 ++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_cmd.h | 10 ++++++++++
2 files changed, 38 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index ce503dd..a338b1c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -746,3 +746,31 @@ out_free:
out:
return ret;
}
+
+int wl1271_cmd_set_sta_state(struct wl1271 *wl)
+{
+ struct wl1271_cmd_set_sta_state *cmd;
+ int ret = 0;
+
+ wl1271_debug(DEBUG_CMD, "cmd set sta state");
+
+ cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+ if (!cmd) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
+
+ ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
+ if (ret < 0) {
+ wl1271_error("failed to send set STA state command");
+ goto out_free;
+ }
+
+out_free:
+ kfree(cmd);
+
+out:
+ return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index af577ee..ce0476c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -55,6 +55,7 @@ int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
u32 tx_seq_32, u16 tx_seq_16);
int wl1271_cmd_disconnect(struct wl1271 *wl);
+int wl1271_cmd_set_sta_state(struct wl1271 *wl);
enum wl1271_commands {
CMD_INTERROGATE = 1, /*use this to read information elements*/
@@ -469,4 +470,13 @@ struct wl1271_cmd_disconnect {
u8 padding;
} __packed;
+#define WL1271_CMD_STA_STATE_CONNECTED 1
+
+struct wl1271_cmd_set_sta_state {
+ struct wl1271_cmd_header header;
+
+ u8 state;
+ u8 padding[3];
+} __attribute__ ((packed));
+
#endif /* __WL1271_CMD_H__ */
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch adds support for the hardware GEM cipher suite.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 2 ++
drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 16 ++++++++++++++++
3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 763ece8..22e850f 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -117,6 +117,8 @@ enum {
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
+#define WL1271_CIPHER_SUITE_GEM 0x00147201
+
#define WL1271_BUSY_WORD_CNT 1
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index ff8e35e..33b946b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -279,7 +279,7 @@ enum wl1271_cmd_key_type {
KEY_WEP = 1,
KEY_TKIP = 2,
KEY_AES = 3,
- KEY_GEM = 4
+ KEY_GEM = 4,
};
/* FIXME: Add description for key-types */
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index f0c2532..39b5985 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1528,6 +1528,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
break;
+ case WL1271_CIPHER_SUITE_GEM:
+ key_type = KEY_GEM;
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+ break;
default:
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
@@ -2382,6 +2387,14 @@ EXPORT_SYMBOL_GPL(wl1271_unregister_hw);
int wl1271_init_ieee80211(struct wl1271 *wl)
{
+ static const u32 cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WL1271_CIPHER_SUITE_GEM,
+ };
+
/* The tx descriptor buffer and the TKIP space. */
wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
sizeof(struct wl1271_tx_hw_descr);
@@ -2399,6 +2412,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI;
+ wl->hw->wiphy->cipher_suites = cipher_suites;
+ wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
wl->hw->wiphy->max_scan_ssids = 1;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Currently then dwell times for each channel in scans is set to an overly
long value, and excessive number of probe-requests are transmitted on each
channel (for active scans.)
Based on testing, comparable results can be received with smaller dwell-time,
and, with fever probe-requests - in fact, reducing the number of probe-requests
to 2 seems to increase the number of found results.
Configure more optimal values for per channel dwell times. Comparison for the
different scan configurations (in my current office environment):
dwell-time 60000 3x probe-req == ~60 results
40000 3x probe-req == ~50 results
30000 3x probe-req == ~40 results
dwell-time 60000 2x probe-req == ~70 results
40000 2x probe-req == ~60 results
30000 2x probe-req == ~58 results
The above are results for a cumulative 3 scan run. For individual scans, the
number of results drop slightly more.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_conf.h | 39 +++++++++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_main.c | 9 ++++++-
drivers/net/wireless/wl12xx/wl1271_scan.c | 18 +++++++++---
drivers/net/wireless/wl12xx/wl1271_scan.h | 3 --
4 files changed, 60 insertions(+), 9 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index feb493e..ab716f5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -1016,6 +1016,44 @@ struct conf_roam_trigger_settings {
u8 avg_weight_snr_data;
};
+struct conf_scan_settings {
+ /*
+ * The minimum time to wait on each channel for active scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 min_dwell_time_active;
+
+ /*
+ * The maximum time to wait on each channel for active scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 max_dwell_time_active;
+
+ /*
+ * The maximum time to wait on each channel for passive scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 min_dwell_time_passive;
+
+ /*
+ * The maximum time to wait on each channel for passive scans
+ *
+ * Range: 0 - 65536 tu
+ */
+ u16 max_dwell_time_passive;
+
+ /*
+ * Number of probe requests to transmit on each active scan channel
+ *
+ * Range: u8
+ */
+ u16 num_probe_reqs;
+
+};
+
struct conf_drv_settings {
struct conf_sg_settings sg;
struct conf_rx_settings rx;
@@ -1024,6 +1062,7 @@ struct conf_drv_settings {
struct conf_itrim_settings itrim;
struct conf_pm_config_settings pm_config;
struct conf_roam_trigger_settings roam_trigger;
+ struct conf_scan_settings scan;
};
#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 3f4e154..dcbd6f5 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -232,7 +232,14 @@ static struct conf_drv_settings default_conf = {
.avg_weight_rssi_data = 10,
.avg_weight_snr_beacon = 20,
.avg_weight_snr_data = 10
- }
+ },
+ .scan = {
+ .min_dwell_time_active = 7500,
+ .max_dwell_time_active = 30000,
+ .min_dwell_time_passive = 30000,
+ .max_dwell_time_passive = 60000,
+ .num_probe_reqs = 2,
+ },
};
static void __wl1271_op_remove_interface(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 37f9ccb..5c76b79 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -64,6 +64,7 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
struct basic_scan_channel_params *channels,
enum ieee80211_band band, bool passive)
{
+ struct conf_scan_settings *c = &wl->conf.scan;
int i, j;
u32 flags;
@@ -91,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
wl1271_debug(DEBUG_SCAN, "beacon_found %d",
req->channels[i]->beacon_found);
- channels[j].min_duration =
- cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
- channels[j].max_duration =
- cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
+ if (!passive) {
+ channels[j].min_duration =
+ cpu_to_le32(c->min_dwell_time_active);
+ channels[j].max_duration =
+ cpu_to_le32(c->max_dwell_time_active);
+ } else {
+ channels[j].min_duration =
+ cpu_to_le32(c->min_dwell_time_passive);
+ channels[j].max_duration =
+ cpu_to_le32(c->max_dwell_time_passive);
+ }
channels[j].early_termination = 0;
channels[j].tx_power_att = req->channels[i]->max_power;
channels[j].channel = req->channels[i]->hw_value;
@@ -151,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
cmd->params.rx_filter_options =
cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
- cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
+ cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
cmd->params.tx_rate = cpu_to_le32(basic_rate);
cmd->params.tid_trigger = 0;
cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h
index bb7af2a..6d57127 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.h
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
@@ -40,11 +40,8 @@ void wl1271_scan_complete_work(struct work_struct *work);
#define WL1271_SCAN_OPT_ACTIVE 0
#define WL1271_SCAN_OPT_PASSIVE 1
#define WL1271_SCAN_OPT_PRIORITY_HIGH 4
-#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
-#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
#define WL1271_SCAN_BAND_2_4_GHZ 0
#define WL1271_SCAN_BAND_5_GHZ 1
-#define WL1271_SCAN_PROBE_REQS 3
#define WL1271_SCAN_TIMEOUT 10000 /* msec */
--
1.6.3.3
On Mon, 2010-09-27 at 10:51 +0200, ext Johannes Berg wrote:
> On Mon, 2010-09-27 at 11:37 +0300, Luciano Coelho wrote:
>
> > - /* queue */
> > + /* queue (we use same identifiers for tid's and ac's */
> > ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
> > - desc->tid = wl1271_tx_ac_to_tid(ac);
> > + desc->tid = ac;
>
> That cannot be right unless the "tid" field in "desc" should really be
> named "ac", since there are twice as many TIDs as ACs. Nor can
> "ac_to_tid" ever be a valid function, for the same reason, it can't be a
> surjective function.
You are probably confused by the name "tid", by which name TI refers to
this field. Practically, currently, it is essentially the same thing as
AC. The mapping between the tid's and AC's is specified in the wl1271
driver, and you'll find AC's and tid's are one-to-one.
The naming of this field is like this due to planned future
implementation.
-Juuso
> If you need the TID (with some fallback for non-QoS frames) you should
> probably add that to the tx info somehow.
>
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
On Mon, 2010-09-27 at 12:46 +0300, Juuso Oikarinen wrote:
> > > +#define WL1271_CIPHER_SUITE_GEM 0x000FACFF
> >
> > NACK, this is a standards-reserved value. Use the correct ID for it or
> > allocate one within your own OUI if you don't want to admit what this
> > really is (and by now all readers here will know anyway.)
>
> Well I'm sure many or most know what this patch is about. The choice of
> value was not intended to hide that.
>
> You're right though, we'll need to change the OUI of the value, unless
> you can point me to an official value to use.
Well, ISO/IEC JTC 1 N 9880 says you should use 00-14-72:1.
johannes
On Mon, 2010-09-27 at 10:48 +0200, ext Johannes Berg wrote:
> On Mon, 2010-09-27 at 11:37 +0300, Luciano Coelho wrote:
> > From: Juuso Oikarinen <[email protected]>
> >
> > The mac80211 inserts channels into a scan request in the same order the driver
> > registers them. Use this fact to optimize scan by ordering the channels so
> > that adjacent channels don't get scanned consecutively.
>
> Cute, but not really ...
>
> First of all, iw will also report channels in this order, and that's
> just weird.
>
> Secondly, if you pass any channels to scan manually (say with iw), this
> assertion is no longer true -- cfg80211 will actually _sort_ the
> channels in that case to make sure there are no duplicates.
>
> So you really shouldn't be doing this.
Indeed, thanks for pointing out.
This was a shortcut that seemed so easy to follow that we couldn't
resist.
I think we can release this patch as is, because it already helps in
some cases. And we'll come with a proper and generic solution in
mac80211/cfg80211 soon.
--
Cheers,
Luca.
From: Juuso Oikarinen <[email protected]>
The function is not used anywhere.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 35 ----------------------------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 37 ------------------------------
2 files changed, 0 insertions(+), 72 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index a516035..42e7d2f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -421,41 +421,6 @@ out:
return ret;
}
-int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
- size_t len)
-{
- struct cmd_read_write_memory *cmd;
- int ret = 0;
-
- wl1271_debug(DEBUG_CMD, "cmd read memory");
-
- cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
- if (!cmd) {
- ret = -ENOMEM;
- goto out;
- }
-
- WARN_ON(len > MAX_READ_SIZE);
- len = min_t(size_t, len, MAX_READ_SIZE);
-
- cmd->addr = cpu_to_le32(addr);
- cmd->size = cpu_to_le32(len);
-
- ret = wl1271_cmd_send(wl, CMD_READ_MEMORY, cmd, sizeof(*cmd),
- sizeof(*cmd));
- if (ret < 0) {
- wl1271_error("read memory command failed: %d", ret);
- goto out;
- }
-
- /* the read command got in */
- memcpy(answer, cmd->value, len);
-
-out:
- kfree(cmd);
- return ret;
-}
-
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
void *buf, size_t buf_len, int index, u32 rates)
{
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index ce0476c..92747ce 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -39,8 +39,6 @@ int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
-int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
- size_t len);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
void *buf, size_t buf_len, int index, u32 rates);
int wl1271_cmd_build_null_data(struct wl1271 *wl);
@@ -161,41 +159,6 @@ enum {
MAX_COMMAND_STATUS = 0xff
};
-
-/*
- * CMD_READ_MEMORY
- *
- * The host issues this command to read the WiLink device memory/registers.
- *
- * Note: The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-/*
- * CMD_WRITE_MEMORY
- *
- * The host issues this command to write the WiLink device memory/registers.
- *
- * The Base Band address has special handling (16 bits registers and
- * addresses). For more information, see the hardware specification.
- */
-#define MAX_READ_SIZE 256
-
-struct cmd_read_write_memory {
- struct wl1271_cmd_header header;
-
- /* The address of the memory to read from or write to.*/
- __le32 addr;
-
- /* The amount of data in bytes to read from or write to the WiLink
- * device.*/
- __le32 size;
-
- /* The actual value read from or written to the Wilink. The source
- of this field is the Host in WRITE command or the Wilink in READ
- command. */
- u8 value[MAX_READ_SIZE];
-} __packed;
-
#define CMDMBOX_HEADER_LEN 4
#define CMDMBOX_INFO_ELEM_HEADER_LEN 4
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Remove outdated FIXME's from the code.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_boot.c | 17 +++++------------
drivers/net/wireless/wl12xx/wl1271_main.c | 7 ++-----
drivers/net/wireless/wl12xx/wl1271_tx.c | 2 --
3 files changed, 7 insertions(+), 19 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index e5a7f04..f750d5a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -251,8 +251,10 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
burst_len = nvs_ptr[0];
dest_addr = (nvs_ptr[1] & 0xfe) | ((u32)(nvs_ptr[2] << 8));
- /* FIXME: Due to our new wl1271_translate_reg_addr function,
- we need to add the REGISTER_BASE to the destination */
+ /*
+ * Due to our new wl1271_translate_reg_addr function,
+ * we need to add the REGISTER_BASE to the destination
+ */
dest_addr += REGISTERS_BASE;
/* We move our pointer to the data */
@@ -280,8 +282,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
ALIGN(nvs_ptr - (u8 *)wl->nvs->nvs + 7, 4);
nvs_len -= nvs_ptr - (u8 *)wl->nvs->nvs;
- /* FIXME: The driver sets the partition here, but this is not needed,
- since it sets to the same one as currently in use */
/* Now we must set the partition correctly */
wl1271_set_partition(wl, &part_table[PART_WORK]);
@@ -291,9 +291,6 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
return -ENOMEM;
/* And finally we upload the NVS tables */
- /* FIXME: In wl1271, we upload everything at once.
- No endianness handling needed here?! The ref driver doesn't do
- anything about it at this point */
wl1271_write(wl, CMD_MBOX_ADDRESS, nvs_aligned, nvs_len, false);
kfree(nvs_aligned);
@@ -491,10 +488,7 @@ int wl1271_boot(struct wl1271 *wl)
wl1271_debug(DEBUG_BOOT, "pause1 0x%x", pause);
- pause &= ~(WU_COUNTER_PAUSE_VAL); /* FIXME: This should probably be
- * WU_COUNTER_PAUSE_VAL instead of
- * 0x3ff (magic number ). How does
- * this work?! */
+ pause &= ~(WU_COUNTER_PAUSE_VAL);
pause |= WU_COUNTER_PAUSE_VAL;
wl1271_write32(wl, WU_COUNTER_PAUSE, pause);
@@ -548,7 +542,6 @@ int wl1271_boot(struct wl1271 *wl)
if (ret < 0)
goto out;
- /* FIXME: Need to check whether this is really what we want */
wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
WL1271_ACX_ALL_EVENTS_VECTOR);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 8ce891a..bbd075a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -251,7 +251,6 @@ static struct conf_drv_settings default_conf = {
.host_fast_wakeup_support = false
},
.roam_trigger = {
- /* FIXME: due to firmware bug, must use value 1 for now */
.trigger_pacing = 1,
.avg_weight_rssi_beacon = 20,
.avg_weight_rssi_data = 10,
@@ -2281,8 +2280,7 @@ static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev,
struct wl1271 *wl = dev_get_drvdata(dev);
ssize_t len;
- /* FIXME: what's the maximum length of buf? page size?*/
- len = 500;
+ len = PAGE_SIZE;
mutex_lock(&wl->mutex);
len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n",
@@ -2343,8 +2341,7 @@ static ssize_t wl1271_sysfs_show_hw_pg_ver(struct device *dev,
struct wl1271 *wl = dev_get_drvdata(dev);
ssize_t len;
- /* FIXME: what's the maximum length of buf? page size?*/
- len = 500;
+ len = PAGE_SIZE;
mutex_lock(&wl->mutex);
if (wl->hw_pg_ver >= 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index dc0b46c..0f99eff 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -422,8 +422,6 @@ void wl1271_tx_reset(struct wl1271 *wl)
struct sk_buff *skb;
/* TX failure */
-/* control->flags = 0; FIXME */
-
while ((skb = skb_dequeue(&wl->tx_queue))) {
wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
ieee80211_tx_status(wl->hw, skb);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The mac80211 inserts channels into a scan request in the same order the driver
registers them. Use this fact to optimize scan by ordering the channels so
that adjacent channels don't get scanned consecutively.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 86 +++++++++++++++-------------
1 files changed, 46 insertions(+), 40 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index b42ee48..8ce891a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -2057,21 +2057,24 @@ static struct ieee80211_rate wl1271_rates[] = {
.hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
};
-/* can't be const, mac80211 writes to this */
+/*
+ * Can't be const, mac80211 writes to this. The order of the channels here
+ * is designed to improve scanning.
+ */
static struct ieee80211_channel wl1271_channels[] = {
{ .hw_value = 1, .center_freq = 2412, .max_power = 25 },
- { .hw_value = 2, .center_freq = 2417, .max_power = 25 },
- { .hw_value = 3, .center_freq = 2422, .max_power = 25 },
- { .hw_value = 4, .center_freq = 2427, .max_power = 25 },
{ .hw_value = 5, .center_freq = 2432, .max_power = 25 },
- { .hw_value = 6, .center_freq = 2437, .max_power = 25 },
- { .hw_value = 7, .center_freq = 2442, .max_power = 25 },
- { .hw_value = 8, .center_freq = 2447, .max_power = 25 },
{ .hw_value = 9, .center_freq = 2452, .max_power = 25 },
- { .hw_value = 10, .center_freq = 2457, .max_power = 25 },
- { .hw_value = 11, .center_freq = 2462, .max_power = 25 },
- { .hw_value = 12, .center_freq = 2467, .max_power = 25 },
{ .hw_value = 13, .center_freq = 2472, .max_power = 25 },
+ { .hw_value = 4, .center_freq = 2427, .max_power = 25 },
+ { .hw_value = 8, .center_freq = 2447, .max_power = 25 },
+ { .hw_value = 12, .center_freq = 2467, .max_power = 25 },
+ { .hw_value = 3, .center_freq = 2422, .max_power = 25 },
+ { .hw_value = 7, .center_freq = 2442, .max_power = 25 },
+ { .hw_value = 11, .center_freq = 2462, .max_power = 25 },
+ { .hw_value = 2, .center_freq = 2417, .max_power = 25 },
+ { .hw_value = 6, .center_freq = 2437, .max_power = 25 },
+ { .hw_value = 10, .center_freq = 2457, .max_power = 25 },
};
/* mapping to indexes for wl1271_rates */
@@ -2140,49 +2143,52 @@ static struct ieee80211_rate wl1271_rates_5ghz[] = {
.hw_value_short = CONF_HW_BIT_RATE_54MBPS, },
};
-/* 5 GHz band channels for WL1273 */
+/*
+ * 5 GHz band channels for WL1273 - can't be const, mac80211 writes to this.
+ * The order of the channels here is designed to improve scanning.
+ */
static struct ieee80211_channel wl1271_channels_5ghz[] = {
{ .hw_value = 183, .center_freq = 4915},
- { .hw_value = 184, .center_freq = 4920},
- { .hw_value = 185, .center_freq = 4925},
- { .hw_value = 187, .center_freq = 4935},
{ .hw_value = 188, .center_freq = 4940},
- { .hw_value = 189, .center_freq = 4945},
- { .hw_value = 192, .center_freq = 4960},
- { .hw_value = 196, .center_freq = 4980},
- { .hw_value = 7, .center_freq = 5035},
{ .hw_value = 8, .center_freq = 5040},
- { .hw_value = 9, .center_freq = 5045},
- { .hw_value = 11, .center_freq = 5055},
- { .hw_value = 12, .center_freq = 5060},
- { .hw_value = 16, .center_freq = 5080},
{ .hw_value = 34, .center_freq = 5170},
- { .hw_value = 36, .center_freq = 5180},
- { .hw_value = 38, .center_freq = 5190},
- { .hw_value = 40, .center_freq = 5200},
- { .hw_value = 42, .center_freq = 5210},
{ .hw_value = 44, .center_freq = 5220},
- { .hw_value = 46, .center_freq = 5230},
- { .hw_value = 48, .center_freq = 5240},
- { .hw_value = 52, .center_freq = 5260},
- { .hw_value = 56, .center_freq = 5280},
{ .hw_value = 60, .center_freq = 5300},
- { .hw_value = 64, .center_freq = 5320},
- { .hw_value = 100, .center_freq = 5500},
- { .hw_value = 104, .center_freq = 5520},
- { .hw_value = 108, .center_freq = 5540},
{ .hw_value = 112, .center_freq = 5560},
- { .hw_value = 116, .center_freq = 5580},
- { .hw_value = 120, .center_freq = 5600},
- { .hw_value = 124, .center_freq = 5620},
- { .hw_value = 128, .center_freq = 5640},
{ .hw_value = 132, .center_freq = 5660},
+ { .hw_value = 157, .center_freq = 5785},
+ { .hw_value = 184, .center_freq = 4920},
+ { .hw_value = 189, .center_freq = 4945},
+ { .hw_value = 9, .center_freq = 5045},
+ { .hw_value = 36, .center_freq = 5180},
+ { .hw_value = 46, .center_freq = 5230},
+ { .hw_value = 64, .center_freq = 5320},
+ { .hw_value = 116, .center_freq = 5580},
{ .hw_value = 136, .center_freq = 5680},
+ { .hw_value = 192, .center_freq = 4960},
+ { .hw_value = 11, .center_freq = 5055},
+ { .hw_value = 38, .center_freq = 5190},
+ { .hw_value = 48, .center_freq = 5240},
+ { .hw_value = 100, .center_freq = 5500},
+ { .hw_value = 120, .center_freq = 5600},
{ .hw_value = 140, .center_freq = 5700},
+ { .hw_value = 185, .center_freq = 4925},
+ { .hw_value = 196, .center_freq = 4980},
+ { .hw_value = 12, .center_freq = 5060},
+ { .hw_value = 40, .center_freq = 5200},
+ { .hw_value = 52, .center_freq = 5260},
+ { .hw_value = 104, .center_freq = 5520},
+ { .hw_value = 124, .center_freq = 5620},
{ .hw_value = 149, .center_freq = 5745},
- { .hw_value = 153, .center_freq = 5765},
- { .hw_value = 157, .center_freq = 5785},
{ .hw_value = 161, .center_freq = 5805},
+ { .hw_value = 187, .center_freq = 4935},
+ { .hw_value = 7, .center_freq = 5035},
+ { .hw_value = 16, .center_freq = 5080},
+ { .hw_value = 42, .center_freq = 5210},
+ { .hw_value = 56, .center_freq = 5280},
+ { .hw_value = 108, .center_freq = 5540},
+ { .hw_value = 128, .center_freq = 5640},
+ { .hw_value = 153, .center_freq = 5765},
{ .hw_value = 165, .center_freq = 5825},
};
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The work cancelling has had several hazards, ranging from potentially
executing work after the driver is in OFF state, to executing work after
the driver and relevant memory structures are already removed.
Fix these.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_event.c | 3 +++
drivers/net/wireless/wl12xx/wl1271_main.c | 3 +++
drivers/net/wireless/wl12xx/wl1271_ps.c | 3 +++
3 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index bced829..e6c839a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -41,6 +41,9 @@ void wl1271_pspoll_work(struct work_struct *work)
mutex_lock(&wl->mutex);
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
if (!test_and_clear_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags))
goto out;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 37f61de..2c03cb1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -792,6 +792,8 @@ int wl1271_plt_stop(struct wl1271 *wl)
out:
mutex_unlock(&wl->mutex);
+ cancel_work_sync(&wl->irq_work);
+
return ret;
}
@@ -995,6 +997,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_delayed_work_sync(&wl->pspoll_work);
+ cancel_delayed_work_sync(&wl->elp_work);
mutex_lock(&wl->mutex);
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index f75668e..150dc67 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -39,6 +39,9 @@ void wl1271_elp_work(struct work_struct *work)
mutex_lock(&wl->mutex);
+ if (unlikely(wl->state == WL1271_STATE_OFF))
+ goto out;
+
if (test_bit(WL1271_FLAG_IN_ELP, &wl->flags) ||
(!test_bit(WL1271_FLAG_PSM, &wl->flags) &&
!test_bit(WL1271_FLAG_IDLE, &wl->flags)))
--
1.6.3.3
On Mon, 2010-09-27 at 11:58 +0200, Oikarinen Juuso (Nokia-MS/Tampere)
wrote:
> On Mon, 2010-09-27 at 11:49 +0200, ext Johannes Berg wrote:
> > On Mon, 2010-09-27 at 12:46 +0300, Juuso Oikarinen wrote:
> >
> > > > > +#define WL1271_CIPHER_SUITE_GEM 0x000FACFF
> > > >
> > > > NACK, this is a standards-reserved value. Use the correct ID for it or
> > > > allocate one within your own OUI if you don't want to admit what this
> > > > really is (and by now all readers here will know anyway.)
> > >
> > > Well I'm sure many or most know what this patch is about. The choice of
> > > value was not intended to hide that.
> > >
> > > You're right though, we'll need to change the OUI of the value, unless
> > > you can point me to an official value to use.
> >
> > Well, ISO/IEC JTC 1 N 9880 says you should use 00-14-72:1.
>
> Heh, yes, my local expert on this just gave me the same value. Thanks.
>
> One new patch coming up!
Cool, thanks for fixing this quickly, Juuso. I'll replace the current
patch with your new one.
--
Cheers,
Luca.
On Mon, 2010-09-27 at 11:37 +0300, Luciano Coelho wrote:
> From: Juuso Oikarinen <[email protected]>
>
> This patch adds support for the hardware GEM cipher suite.
>
> Signed-off-by: Juuso Oikarinen <[email protected]>
> Reviewed-by: Luciano Coelho <[email protected]>
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
> drivers/net/wireless/wl12xx/wl1271.h | 2 ++
> drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +-
> drivers/net/wireless/wl12xx/wl1271_main.c | 16 ++++++++++++++++
> 3 files changed, 19 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
> index 763ece8..9782bc1 100644
> --- a/drivers/net/wireless/wl12xx/wl1271.h
> +++ b/drivers/net/wireless/wl12xx/wl1271.h
> @@ -117,6 +117,8 @@ enum {
> #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
> #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
>
> +#define WL1271_CIPHER_SUITE_GEM 0x000FACFF
NACK, this is a standards-reserved value. Use the correct ID for it or
allocate one within your own OUI if you don't want to admit what this
really is (and by now all readers here will know anyway.)
johannes
From: Juuso Oikarinen <[email protected]>
It's not used anywhere.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_acx.c | 34 ------------------------------
drivers/net/wireless/wl12xx/wl1271_acx.h | 30 --------------------------
2 files changed, 0 insertions(+), 64 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index f03ad08..6189934 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -86,40 +86,6 @@ out:
return ret;
}
-int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len)
-{
- struct acx_revision *rev;
- int ret;
-
- wl1271_debug(DEBUG_ACX, "acx fw rev");
-
- rev = kzalloc(sizeof(*rev), GFP_KERNEL);
- if (!rev) {
- ret = -ENOMEM;
- goto out;
- }
-
- ret = wl1271_cmd_interrogate(wl, ACX_FW_REV, rev, sizeof(*rev));
- if (ret < 0) {
- wl1271_warning("ACX_FW_REV interrogate failed");
- goto out;
- }
-
- /* be careful with the buffer sizes */
- strncpy(buf, rev->fw_version, min(len, sizeof(rev->fw_version)));
-
- /*
- * if the firmware version string is exactly
- * sizeof(rev->fw_version) long or fw_len is less than
- * sizeof(rev->fw_version) it won't be null terminated
- */
- buf[min(len, sizeof(rev->fw_version)) - 1] = '\0';
-
-out:
- kfree(rev);
- return ret;
-}
-
int wl1271_acx_tx_power(struct wl1271 *wl, int power)
{
struct acx_current_tx_power *acx;
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 5c8bb7f..ebb341d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -100,35 +100,6 @@ struct acx_error_counter {
__le32 seq_num_miss;
} __packed;
-struct acx_revision {
- struct acx_header header;
-
- /*
- * The WiLink firmware version, an ASCII string x.x.x.x,
- * that uniquely identifies the current firmware.
- * The left most digit is incremented each time a
- * significant change is made to the firmware, such as
- * code redesign or new platform support.
- * The second digit is incremented when major enhancements
- * are added or major fixes are made.
- * The third digit is incremented for each GA release.
- * The fourth digit is incremented for each build.
- * The first two digits identify a firmware release version,
- * in other words, a unique set of features.
- * The first three digits identify a GA release.
- */
- char fw_version[20];
-
- /*
- * This 4 byte field specifies the WiLink hardware version.
- * bits 0 - 15: Reserved.
- * bits 16 - 23: Version ID - The WiLink version ID
- * (1 = first spin, 2 = second spin, and so on).
- * bits 24 - 31: Chip ID - The WiLink chip ID.
- */
- __le32 hw_version;
-} __packed;
-
enum wl1271_psm_mode {
/* Active mode */
WL1271_PSM_CAM = 0,
@@ -1076,7 +1047,6 @@ enum {
int wl1271_acx_wake_up_conditions(struct wl1271 *wl);
int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
-int wl1271_acx_fw_version(struct wl1271 *wl, char *buf, size_t len);
int wl1271_acx_tx_power(struct wl1271 *wl, int power);
int wl1271_acx_feature_cfg(struct wl1271 *wl);
int wl1271_acx_mem_map(struct wl1271 *wl,
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The current scan implementation can jam, if the scan request ends up
containing no work. This can especially happen if there is a scan request
with only 11a band channels for HW that does not support 11a.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 1 +
drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++
drivers/net/wireless/wl12xx/wl1271_scan.c | 23 ++++++++++++++++++-----
drivers/net/wireless/wl12xx/wl1271_scan.h | 1 +
4 files changed, 24 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 9782bc1..55ec656 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -418,6 +418,7 @@ struct wl1271 {
/* Are we currently scanning */
struct wl1271_scan scan;
+ struct work_struct scan_complete_work;
/* Our association ID */
u16 aid;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 44915ee..37f61de 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -634,6 +634,8 @@ static int wl1271_setup(struct wl1271 *wl)
INIT_WORK(&wl->irq_work, wl1271_irq_work);
INIT_WORK(&wl->tx_work, wl1271_tx_work);
+ INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+
return 0;
}
@@ -962,6 +964,8 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
struct wl1271 *wl = hw->priv;
int i;
+ cancel_work_sync(&wl->scan_complete_work);
+
mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 8d30150..9f1da82 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -28,6 +28,23 @@
#include "wl1271_scan.h"
#include "wl1271_acx.h"
+void wl1271_scan_complete_work(struct work_struct *work)
+{
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, scan_complete_work);
+
+ wl1271_debug(DEBUG_SCAN, "Scanning complete");
+
+ mutex_lock(&wl->mutex);
+ wl->scan.state = WL1271_SCAN_STATE_IDLE;
+ kfree(wl->scan.scanned_ch);
+ wl->scan.scanned_ch = NULL;
+ mutex_unlock(&wl->mutex);
+
+ ieee80211_scan_completed(wl->hw, false);
+}
+
+
static int wl1271_get_scan_channels(struct wl1271 *wl,
struct cfg80211_scan_request *req,
struct basic_scan_channel_params *channels,
@@ -218,11 +235,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_DONE:
- kfree(wl->scan.scanned_ch);
- wl->scan.scanned_ch = NULL;
-
- wl->scan.state = WL1271_SCAN_STATE_IDLE;
- ieee80211_scan_completed(wl->hw, false);
+ ieee80211_queue_work(wl->hw, &wl->scan_complete_work);
break;
default:
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h b/drivers/net/wireless/wl12xx/wl1271_scan.h
index f181570..1404e00 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.h
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
@@ -32,6 +32,7 @@ int wl1271_scan_build_probe_req(struct wl1271 *wl,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band);
void wl1271_scan_stm(struct wl1271 *wl);
+void wl1271_scan_complete_work(struct work_struct *work);
#define WL1271_SCAN_MAX_CHANNELS 24
#define WL1271_SCAN_DEFAULT_TAG 1
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch reduces the rate of the null-func used to enter PSM on the last
retry as precaution.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 4 ++--
drivers/net/wireless/wl12xx/wl1271_cmd.h | 4 +++-
drivers/net/wireless/wl12xx/wl1271_event.c | 17 ++++++++++++-----
drivers/net/wireless/wl12xx/wl1271_main.c | 8 +++++---
drivers/net/wireless/wl12xx/wl1271_ps.c | 8 +++++---
drivers/net/wireless/wl12xx/wl1271_ps.h | 2 +-
6 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 42e7d2f..06b14f2 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -390,7 +390,7 @@ out:
return ret;
}
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
{
struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0;
@@ -407,7 +407,7 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
ps_params->send_null_data = send;
ps_params->retries = 5;
ps_params->hang_over_period = 1;
- ps_params->null_data_rate = cpu_to_le32(wl->basic_rate_set);
+ ps_params->null_data_rate = cpu_to_le32(rates);
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
sizeof(*ps_params), 0);
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 92747ce..ff8e35e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -38,7 +38,9 @@ int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
+int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
+ size_t len);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
void *buf, size_t buf_len, int index, u32 rates);
int wl1271_cmd_build_null_data(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 25ce2cd..bced829 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -52,7 +52,7 @@ void wl1271_pspoll_work(struct work_struct *work)
* delivery failure occurred, and no-one changed state since, so
* we should go back to powersave.
*/
- wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, true);
+ wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE, wl->basic_rate, true);
out:
mutex_unlock(&wl->mutex);
@@ -70,7 +70,8 @@ static void wl1271_event_pspoll_delivery_fail(struct wl1271 *wl)
/* force active mode receive data from the AP */
if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
- ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE, true);
+ ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
+ wl->basic_rate, true);
if (ret < 0)
return;
set_bit(WL1271_FLAG_PSPOLL_FAILURE, &wl->flags);
@@ -91,6 +92,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
bool *beacon_loss)
{
int ret = 0;
+ u32 total_retries = wl->conf.conn.psm_entry_retries;
+ u32 rates;
wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
@@ -104,10 +107,14 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
break;
}
- if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
+ if (wl->psm_entry_retry < total_retries) {
wl->psm_entry_retry++;
+ if (wl->psm_entry_retry == total_retries)
+ rates = wl->basic_rate;
+ else
+ rates = wl->basic_rate_set;
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- true);
+ rates, true);
} else {
wl1271_info("No ack to nullfunc from AP.");
wl->psm_entry_retry = 0;
@@ -143,7 +150,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
/* make sure the firmware goes to active mode - the frame to
be sent next will indicate to the AP, that we are active. */
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- false);
+ wl->basic_rate, false);
break;
case EVENT_EXIT_POWER_SAVE_SUCCESS:
default:
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 11e112f..81f92a0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1341,7 +1341,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
wl1271_debug(DEBUG_PSM, "psm enabled");
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- true);
+ wl->basic_rate_set, true);
}
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
@@ -1351,7 +1351,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (test_bit(WL1271_FLAG_PSM, &wl->flags))
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- true);
+ wl->basic_rate_set, true);
}
if (conf->power_level != wl->power_level) {
@@ -1826,7 +1826,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
mode = STATION_POWER_SAVE_MODE;
- ret = wl1271_ps_set_mode(wl, mode, true);
+ ret = wl1271_ps_set_mode(wl, mode,
+ wl->basic_rate_set,
+ true);
if (ret < 0)
goto out_sleep;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index 52a6095..f75668e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -121,7 +121,7 @@ out:
}
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
- bool send)
+ u32 rates, bool send)
{
int ret;
@@ -135,7 +135,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
return ret;
}
- ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
+ ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
+ rates, send);
if (ret < 0)
return ret;
@@ -158,7 +159,8 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
if (ret < 0)
return ret;
- ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE, send);
+ ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
+ rates, send);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.h b/drivers/net/wireless/wl12xx/wl1271_ps.h
index 940276f..6ba7b03 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.h
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.h
@@ -28,7 +28,7 @@
#include "wl1271_acx.h"
int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
- bool send);
+ u32 rates, bool send);
void wl1271_ps_elp_sleep(struct wl1271 *wl);
int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
void wl1271_elp_work(struct work_struct *work);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch improves connection reliability by choosing the lowest basic
rate for null-func frames (which increases their range, as the firmware does
not do rate fall-back for null-func frames.) Also, increase the PSM entry
retry-counter.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Tested-by: Tuomas Katila <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 10 +++++-----
drivers/net/wireless/wl12xx/wl1271_conf.h | 16 ++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_event.c | 7 +------
drivers/net/wireless/wl12xx/wl1271_main.c | 10 ++++++----
4 files changed, 28 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 170b5a8..4a56ab0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -408,8 +408,8 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
ps_params->ps_mode = ps_mode;
ps_params->send_null_data = send;
- ps_params->retries = 5;
- ps_params->hang_over_period = 1;
+ ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
+ ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
ps_params->null_data_rate = cpu_to_le32(rates);
ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
@@ -484,7 +484,7 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
}
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
- WL1271_RATE_AUTOMATIC);
+ wl->basic_rate);
out:
dev_kfree_skb(skb);
@@ -507,7 +507,7 @@ int wl1271_cmd_build_klv_null_data(struct wl1271 *wl)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV,
skb->data, skb->len,
CMD_TEMPL_KLV_IDX_NULL_DATA,
- WL1271_RATE_AUTOMATIC);
+ wl->basic_rate);
out:
dev_kfree_skb(skb);
@@ -584,7 +584,7 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
sizeof(template), 0,
- WL1271_RATE_AUTOMATIC);
+ wl->basic_rate);
}
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index ab716f5..60c50d1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -912,6 +912,22 @@ struct conf_conn_settings {
u8 psm_entry_retries;
/*
+ * Specifies the maximum number of times to try transmit the PSM entry
+ * null-func frame for each PSM entry attempt
+ *
+ * Range 0 - 255
+ */
+ u8 psm_entry_nullfunc_retries;
+
+ /*
+ * Specifies the time to linger in active mode after successfully
+ * transmitting the PSM entry null-func frame.
+ *
+ * Range 0 - 255 TU's
+ */
+ u8 psm_entry_hangover_period;
+
+ /*
*
* Specifies the interval of the connection keep-alive null-func
* frame in ms.
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index e6c839a..7b3f503 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -96,7 +96,6 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
{
int ret = 0;
u32 total_retries = wl->conf.conn.psm_entry_retries;
- u32 rates;
wl1271_debug(DEBUG_EVENT, "ps_status: 0x%x", mbox->ps_status);
@@ -112,12 +111,8 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
if (wl->psm_entry_retry < total_retries) {
wl->psm_entry_retry++;
- if (wl->psm_entry_retry == total_retries)
- rates = wl->basic_rate;
- else
- rates = wl->basic_rate_set;
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- rates, true);
+ wl->basic_rate, true);
} else {
wl1271_info("No ack to nullfunc from AP.");
wl->psm_entry_retry = 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index dcbd6f5..cb18f22 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -214,7 +214,9 @@ static struct conf_drv_settings default_conf = {
.ps_poll_recovery_period = 700,
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 10,
- .psm_entry_retries = 3,
+ .psm_entry_retries = 5,
+ .psm_entry_nullfunc_retries = 3,
+ .psm_entry_hangover_period = 1,
.keep_alive_interval = 55000,
.max_listen_interval = 20,
},
@@ -1360,7 +1362,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
wl1271_debug(DEBUG_PSM, "psm enabled");
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
- wl->basic_rate_set, true);
+ wl->basic_rate, true);
}
} else if (!(conf->flags & IEEE80211_CONF_PS) &&
test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
@@ -1370,7 +1372,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (test_bit(WL1271_FLAG_PSM, &wl->flags))
ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
- wl->basic_rate_set, true);
+ wl->basic_rate, true);
}
if (conf->power_level != wl->power_level) {
@@ -1851,7 +1853,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
!test_bit(WL1271_FLAG_PSM, &wl->flags)) {
mode = STATION_POWER_SAVE_MODE;
ret = wl1271_ps_set_mode(wl, mode,
- wl->basic_rate_set,
+ wl->basic_rate,
true);
if (ret < 0)
goto out_sleep;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch adds support for the hardware GEM cipher suite.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 2 ++
drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 16 ++++++++++++++++
3 files changed, 19 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 763ece8..9782bc1 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -117,6 +117,8 @@ enum {
#define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
#define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
+#define WL1271_CIPHER_SUITE_GEM 0x000FACFF
+
#define WL1271_BUSY_WORD_CNT 1
#define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index ff8e35e..33b946b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -279,7 +279,7 @@ enum wl1271_cmd_key_type {
KEY_WEP = 1,
KEY_TKIP = 2,
KEY_AES = 3,
- KEY_GEM = 4
+ KEY_GEM = 4,
};
/* FIXME: Add description for key-types */
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index f0c2532..39b5985 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1528,6 +1528,11 @@ static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
break;
+ case WL1271_CIPHER_SUITE_GEM:
+ key_type = KEY_GEM;
+ tx_seq_32 = WL1271_TX_SECURITY_HI32(wl->tx_security_seq);
+ tx_seq_16 = WL1271_TX_SECURITY_LO16(wl->tx_security_seq);
+ break;
default:
wl1271_error("Unknown key algo 0x%x", key_conf->cipher);
@@ -2382,6 +2387,14 @@ EXPORT_SYMBOL_GPL(wl1271_unregister_hw);
int wl1271_init_ieee80211(struct wl1271 *wl)
{
+ static const u32 cipher_suites[] = {
+ WLAN_CIPHER_SUITE_WEP40,
+ WLAN_CIPHER_SUITE_WEP104,
+ WLAN_CIPHER_SUITE_TKIP,
+ WLAN_CIPHER_SUITE_CCMP,
+ WL1271_CIPHER_SUITE_GEM,
+ };
+
/* The tx descriptor buffer and the TKIP space. */
wl->hw->extra_tx_headroom = WL1271_TKIP_IV_SPACE +
sizeof(struct wl1271_tx_hw_descr);
@@ -2399,6 +2412,9 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI;
+ wl->hw->wiphy->cipher_suites = cipher_suites;
+ wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
+
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC);
wl->hw->wiphy->max_scan_ssids = 1;
--
1.6.3.3
As of Rev. 6.1.0.0.335, the ACX_SET_SMART_REFLEX_DEBUG command is
deprecated. This patch removes it from the wl1271 driver (it wasn't used
anyway).
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Saravanan Dhanabal <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_acx.h | 1 -
1 files changed, 0 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 4235bc5..5c8bb7f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -1060,7 +1060,6 @@ enum {
ACX_PEER_HT_CAP = 0x0057,
ACX_HT_BSS_OPERATION = 0x0058,
ACX_COEX_ACTIVITY = 0x0059,
- ACX_SET_SMART_REFLEX_DEBUG = 0x005A,
ACX_SET_DCO_ITRIM_PARAMS = 0x0061,
DOT11_RX_MSDU_LIFE_TIME = 0x1004,
DOT11_CUR_TX_PWR = 0x100D,
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch always enables 11a band towards the mac80211, but prevents scanning
(and hence the usage of) 11a band channels if the chipset does not support it.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_init.c | 15 +++++++--------
drivers/net/wireless/wl12xx/wl1271_main.c | 4 +---
2 files changed, 8 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 879bae0..5614a35 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -53,6 +53,7 @@ static int wl1271_init_hwenc_config(struct wl1271 *wl)
int wl1271_init_templates_config(struct wl1271 *wl)
{
int ret, i;
+ size_t size;
/* send empty templates for fw memory reservation */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
@@ -61,14 +62,12 @@ int wl1271_init_templates_config(struct wl1271 *wl)
if (ret < 0)
return ret;
- if (wl->enable_11a) {
- size_t size = sizeof(struct wl12xx_probe_req_template);
- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- NULL, size, 0,
- WL1271_RATE_AUTOMATIC);
- if (ret < 0)
- return ret;
- }
+ size = sizeof(struct wl12xx_probe_req_template);
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
+ NULL, size, 0,
+ WL1271_RATE_AUTOMATIC);
+ if (ret < 0)
+ return ret;
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
sizeof(struct wl12xx_null_data_template),
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 81f92a0..f0c2532 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -2403,9 +2403,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
BIT(NL80211_IFTYPE_ADHOC);
wl->hw->wiphy->max_scan_ssids = 1;
wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
-
- if (wl->enable_11a)
- wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
+ wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
wl->hw->queues = 4;
wl->hw->max_rates = 1;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This removes a fixme. Also, it removes a redundant setting of the wake-up
conditions when exiting power save mode, which should improve performance.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 7 -------
drivers/net/wireless/wl12xx/wl1271_ps.c | 6 ++++++
2 files changed, 6 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index a338b1c..a516035 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -395,13 +395,6 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, bool send)
struct wl1271_cmd_ps_params *ps_params = NULL;
int ret = 0;
- /* FIXME: this should be in ps.c */
- ret = wl1271_acx_wake_up_conditions(wl);
- if (ret < 0) {
- wl1271_error("couldn't set wake up conditions");
- goto out;
- }
-
wl1271_debug(DEBUG_CMD, "cmd set ps mode");
ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index a5e60e0..52a6095 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -129,6 +129,12 @@ int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
case STATION_POWER_SAVE_MODE:
wl1271_debug(DEBUG_PSM, "entering psm");
+ ret = wl1271_acx_wake_up_conditions(wl);
+ if (ret < 0) {
+ wl1271_error("couldn't set wake up conditions");
+ return ret;
+ }
+
ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE, send);
if (ret < 0)
return ret;
--
1.6.3.3
When we get no SSIDs in the scan request, we should force a passive scan in
all channels. This patch adds code to force the passive scan flag to be set
in that case.
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_scan.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 8ceaabe..7f42ca9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -100,8 +100,11 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
/* We always use high priority scans */
scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
- if(passive)
+
+ /* No SSIDs means that we have a forced passive scan */
+ if (passive || wl->scan.req->n_ssids == 0)
scan_options |= WL1271_SCAN_OPT_PASSIVE;
+
cmd->params.scan_options = cpu_to_le16(scan_options);
cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
--
1.6.3.3
On Mon, 2010-09-27 at 11:12 +0200, ext Johannes Berg wrote:
> On Mon, 2010-09-27 at 11:37 +0300, Luciano Coelho wrote:
> > From: Juuso Oikarinen <[email protected]>
> >
> > This patch adds support for the hardware GEM cipher suite.
> >
> > Signed-off-by: Juuso Oikarinen <[email protected]>
> > Reviewed-by: Luciano Coelho <[email protected]>
> > Signed-off-by: Luciano Coelho <[email protected]>
> > ---
> > drivers/net/wireless/wl12xx/wl1271.h | 2 ++
> > drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 +-
> > drivers/net/wireless/wl12xx/wl1271_main.c | 16 ++++++++++++++++
> > 3 files changed, 19 insertions(+), 1 deletions(-)
> >
> > diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
> > index 763ece8..9782bc1 100644
> > --- a/drivers/net/wireless/wl12xx/wl1271.h
> > +++ b/drivers/net/wireless/wl12xx/wl1271.h
> > @@ -117,6 +117,8 @@ enum {
> > #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
> > #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
> >
> > +#define WL1271_CIPHER_SUITE_GEM 0x000FACFF
>
> NACK, this is a standards-reserved value. Use the correct ID for it or
> allocate one within your own OUI if you don't want to admit what this
> really is (and by now all readers here will know anyway.)
Well I'm sure many or most know what this patch is about. The choice of
value was not intended to hide that.
You're right though, we'll need to change the OUI of the value, unless
you can point me to an official value to use.
-Juuso
> johannes
>
>
On Mon, 2010-09-27 at 11:49 +0200, ext Johannes Berg wrote:
> On Mon, 2010-09-27 at 12:46 +0300, Juuso Oikarinen wrote:
>
> > > > +#define WL1271_CIPHER_SUITE_GEM 0x000FACFF
> > >
> > > NACK, this is a standards-reserved value. Use the correct ID for it or
> > > allocate one within your own OUI if you don't want to admit what this
> > > really is (and by now all readers here will know anyway.)
> >
> > Well I'm sure many or most know what this patch is about. The choice of
> > value was not intended to hide that.
> >
> > You're right though, we'll need to change the OUI of the value, unless
> > you can point me to an official value to use.
>
> Well, ISO/IEC JTC 1 N 9880 says you should use 00-14-72:1.
Heh, yes, my local expert on this just gave me the same value. Thanks.
One new patch coming up!
-Juuso
> johannes
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to [email protected]
> More majordomo info at http://vger.kernel.org/majordomo-info.html
From: Juuso Oikarinen <[email protected]>
Do this so the interface removal can be triggered from an upcoming hardware
failure recovery mechanism.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 17 +++++++++++------
drivers/net/wireless/wl12xx/wl1271_scan.c | 6 ++++++
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 2c03cb1..00da982 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -960,15 +960,10 @@ out:
return ret;
}
-static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+static void __wl1271_op_remove_interface(struct wl1271 *wl)
{
- struct wl1271 *wl = hw->priv;
int i;
- cancel_work_sync(&wl->scan_complete_work);
-
- mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
wl1271_info("down");
@@ -994,6 +989,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
+ cancel_work_sync(&wl->scan_complete_work);
cancel_work_sync(&wl->irq_work);
cancel_work_sync(&wl->tx_work);
cancel_delayed_work_sync(&wl->pspoll_work);
@@ -1039,7 +1035,16 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
wl->tx_res_if = NULL;
kfree(wl->target_mem_map);
wl->target_mem_map = NULL;
+}
+static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
+ struct wl1271 *wl = hw->priv;
+
+ mutex_lock(&wl->mutex);
+ WARN_ON(wl->vif != vif);
+ __wl1271_op_remove_interface(wl);
mutex_unlock(&wl->mutex);
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 9f1da82..20caceb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -36,6 +36,12 @@ void wl1271_scan_complete_work(struct work_struct *work)
wl1271_debug(DEBUG_SCAN, "Scanning complete");
mutex_lock(&wl->mutex);
+
+ if (wl->scan.state == WL1271_SCAN_STATE_IDLE) {
+ mutex_unlock(&wl->mutex);
+ return;
+ }
+
wl->scan.state = WL1271_SCAN_STATE_IDLE;
kfree(wl->scan.scanned_ch);
wl->scan.scanned_ch = NULL;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Add a trigger to net_device changes to monitor for oper_state changes in order
to be able to inform the firmware when association is fully complete (including
the EAP negotiation.)
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 1 +
drivers/net/wireless/wl12xx/wl1271_main.c | 69 +++++++++++++++++++++++++++++
2 files changed, 70 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 4134f44..1098d16 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -350,6 +350,7 @@ struct wl1271 {
#define WL1271_FLAG_IDLE (10)
#define WL1271_FLAG_IDLE_REQUESTED (11)
#define WL1271_FLAG_PSPOLL_FAILURE (12)
+#define WL1271_FLAG_STA_STATE_SENT (13)
unsigned long flags;
struct wl1271_partition_set part;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 776cd7c..45d4ce3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -277,6 +277,67 @@ static struct platform_device wl1271_device = {
static LIST_HEAD(wl_list);
+static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
+ void *arg)
+{
+ struct net_device *dev = arg;
+ struct wireless_dev *wdev;
+ struct wiphy *wiphy;
+ struct ieee80211_hw *hw;
+ struct wl1271 *wl;
+ struct wl1271 *wl_temp;
+ int ret = 0;
+
+ /* Check that this notification is for us. */
+ if (what != NETDEV_CHANGE)
+ return NOTIFY_DONE;
+
+ wdev = dev->ieee80211_ptr;
+ if (wdev == NULL)
+ return NOTIFY_DONE;
+
+ wiphy = wdev->wiphy;
+ if (wiphy == NULL)
+ return NOTIFY_DONE;
+
+ hw = wiphy_priv(wiphy);
+ if (hw == NULL)
+ return NOTIFY_DONE;
+
+ wl_temp = hw->priv;
+ list_for_each_entry(wl, &wl_list, list) {
+ if (wl == wl_temp)
+ break;
+ }
+ if (wl != wl_temp)
+ return NOTIFY_DONE;
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ if ((dev->operstate == IF_OPER_UP) &&
+ !test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags)) {
+ wl1271_cmd_set_sta_state(wl);
+ wl1271_info("Association completed.");
+ }
+
+ wl1271_ps_elp_sleep(wl);
+
+out:
+ mutex_unlock(&wl->mutex);
+
+ return NOTIFY_OK;
+}
+
static void wl1271_conf_init(struct wl1271 *wl)
{
@@ -814,6 +875,10 @@ static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
return NETDEV_TX_OK;
}
+static struct notifier_block wl1271_dev_notifier = {
+ .notifier_call = wl1271_dev_notify,
+};
+
static int wl1271_op_start(struct ieee80211_hw *hw)
{
wl1271_debug(DEBUG_MAC80211, "mac80211 start");
@@ -1783,6 +1848,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
}
} else {
/* use defaults when not associated */
+ clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
wl->aid = 0;
@@ -2307,6 +2373,8 @@ int wl1271_register_hw(struct wl1271 *wl)
wl->mac80211_registered = true;
+ register_netdevice_notifier(&wl1271_dev_notifier);
+
wl1271_notice("loaded");
return 0;
@@ -2315,6 +2383,7 @@ EXPORT_SYMBOL_GPL(wl1271_register_hw);
void wl1271_unregister_hw(struct wl1271 *wl)
{
+ unregister_netdevice_notifier(&wl1271_dev_notifier);
ieee80211_unregister_hw(wl->hw);
wl->mac80211_registered = false;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The current order causes driver releasing to fail in various ways, and causes
possible instability.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 3 +--
drivers/net/wireless/wl12xx/wl1271_spi.c | 3 +--
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index f2f0466..4c250d7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -274,9 +274,8 @@ static void __devexit wl1271_remove(struct sdio_func *func)
{
struct wl1271 *wl = sdio_get_drvdata(func);
- free_irq(wl->irq, wl);
-
wl1271_unregister_hw(wl);
+ free_irq(wl->irq, wl);
wl1271_free_hw(wl);
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index ced0a9e..75cbf36 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -416,9 +416,8 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
- free_irq(wl->irq, wl);
-
wl1271_unregister_hw(wl);
+ free_irq(wl->irq, wl);
wl1271_free_hw(wl);
return 0;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
There is some probability of hardware failures, which currently go largely
undetected. Attempt to recover from these failures by shutting down the
hardware, and requesting mac80211 to reconfigure it.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 3 +++
drivers/net/wireless/wl12xx/wl1271_cmd.c | 5 ++++-
drivers/net/wireless/wl12xx/wl1271_main.c | 28 +++++++++++++++++++++++++++-
drivers/net/wireless/wl12xx/wl1271_ps.c | 3 ++-
4 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 55ec656..b5369a6 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -410,6 +410,9 @@ struct wl1271 {
/* The target interrupt mask */
struct work_struct irq_work;
+ /* Hardware recovery work */
+ struct work_struct recovery_work;
+
/* The mbox event mask */
u32 event_mask;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 06b14f2..170b5a8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -94,6 +94,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
status = le16_to_cpu(cmd->status);
if (status != CMD_STATUS_SUCCESS) {
wl1271_error("command execute failure %d", status);
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
ret = -EIO;
}
@@ -182,8 +183,10 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
timeout = jiffies + msecs_to_jiffies(WL1271_EVENT_TIMEOUT);
do {
- if (time_after(jiffies, timeout))
+ if (time_after(jiffies, timeout)) {
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
return -ETIMEDOUT;
+ }
msleep(1);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 00da982..6e98c75 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -235,6 +235,9 @@ static struct conf_drv_settings default_conf = {
}
};
+static void __wl1271_op_remove_interface(struct wl1271 *wl);
+
+
static void wl1271_device_release(struct device *dev)
{
@@ -612,6 +615,26 @@ out:
return ret;
}
+static void wl1271_recovery_work(struct work_struct *work)
+{
+ struct wl1271 *wl =
+ container_of(work, struct wl1271, recovery_work);
+
+ mutex_lock(&wl->mutex);
+
+ if (wl->state != WL1271_STATE_ON)
+ goto out;
+
+ wl1271_info("Hardware recovery in progress.");
+
+ /* reboot the chipset */
+ __wl1271_op_remove_interface(wl);
+ ieee80211_restart_hw(wl->hw);
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
static void wl1271_fw_wakeup(struct wl1271 *wl)
{
u32 elp_reg;
@@ -635,6 +658,7 @@ static int wl1271_setup(struct wl1271 *wl)
INIT_WORK(&wl->irq_work, wl1271_irq_work);
INIT_WORK(&wl->tx_work, wl1271_tx_work);
INIT_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
+ INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
return 0;
}
@@ -793,11 +817,11 @@ out:
mutex_unlock(&wl->mutex);
cancel_work_sync(&wl->irq_work);
+ cancel_work_sync(&wl->recovery_work);
return ret;
}
-
static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
{
struct wl1271 *wl = hw->priv;
@@ -1046,6 +1070,8 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
WARN_ON(wl->vif != vif);
__wl1271_op_remove_interface(wl);
mutex_unlock(&wl->mutex);
+
+ cancel_work_sync(&wl->recovery_work);
}
static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
diff --git a/drivers/net/wireless/wl12xx/wl1271_ps.c b/drivers/net/wireless/wl12xx/wl1271_ps.c
index 150dc67..e3c332e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_ps.c
+++ b/drivers/net/wireless/wl12xx/wl1271_ps.c
@@ -64,7 +64,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl)
test_bit(WL1271_FLAG_IDLE, &wl->flags)) {
cancel_delayed_work(&wl->elp_work);
ieee80211_queue_delayed_work(wl->hw, &wl->elp_work,
- msecs_to_jiffies(ELP_ENTRY_DELAY));
+ msecs_to_jiffies(ELP_ENTRY_DELAY));
}
}
@@ -99,6 +99,7 @@ int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
&compl, msecs_to_jiffies(WL1271_WAKEUP_TIMEOUT));
if (ret == 0) {
wl1271_error("ELP wakeup timeout!");
+ ieee80211_queue_work(wl->hw, &wl->recovery_work);
ret = -ETIMEDOUT;
goto err;
} else if (ret < 0) {
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The WMM queue default configuration was incorrect, and caused uapsd mode
problems (among possible others.)
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Luciano Coelho <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_conf.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_init.c | 20 +++----
drivers/net/wireless/wl12xx/wl1271_main.c | 84 ++++++++++-------------------
3 files changed, 39 insertions(+), 67 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 0435ffd..feb493e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -595,7 +595,7 @@ struct conf_tx_ac_category {
u16 tx_op_limit;
};
-#define CONF_TX_MAX_TID_COUNT 7
+#define CONF_TX_MAX_TID_COUNT 8
enum {
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 5614a35..349571f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -290,8 +290,16 @@ int wl1271_hw_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- /* Default TID configuration */
+ /* Default TID/AC configuration */
+ BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ conf_ac = &wl->conf.tx.ac_conf[i];
+ ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+ conf_ac->cw_max, conf_ac->aifsn,
+ conf_ac->tx_op_limit);
+ if (ret < 0)
+ goto out_free_memmap;
+
conf_tid = &wl->conf.tx.tid_conf[i];
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
conf_tid->channel_type,
@@ -304,16 +312,6 @@ int wl1271_hw_init(struct wl1271 *wl)
goto out_free_memmap;
}
- /* Default AC configuration */
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- conf_ac = &wl->conf.tx.ac_conf[i];
- ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
- conf_ac->cw_max, conf_ac->aifsn,
- conf_ac->tx_op_limit);
- if (ret < 0)
- goto out_free_memmap;
- }
-
/* Configure TX rate classes */
ret = wl1271_acx_rate_policies(wl);
if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 39b5985..44915ee 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -124,28 +124,28 @@ static struct conf_drv_settings default_conf = {
},
.ac_conf_count = 4,
.ac_conf = {
- [0] = {
+ [CONF_TX_AC_BE] = {
.ac = CONF_TX_AC_BE,
.cw_min = 15,
.cw_max = 63,
.aifsn = 3,
.tx_op_limit = 0,
},
- [1] = {
+ [CONF_TX_AC_BK] = {
.ac = CONF_TX_AC_BK,
.cw_min = 15,
.cw_max = 63,
.aifsn = 7,
.tx_op_limit = 0,
},
- [2] = {
+ [CONF_TX_AC_VI] = {
.ac = CONF_TX_AC_VI,
.cw_min = 15,
.cw_max = 63,
.aifsn = CONF_TX_AIFS_PIFS,
.tx_op_limit = 3008,
},
- [3] = {
+ [CONF_TX_AC_VO] = {
.ac = CONF_TX_AC_VO,
.cw_min = 15,
.cw_max = 63,
@@ -153,64 +153,40 @@ static struct conf_drv_settings default_conf = {
.tx_op_limit = 1504,
},
},
- .tid_conf_count = 7,
+ .tid_conf_count = 4,
.tid_conf = {
- [0] = {
- .queue_id = 0,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
- .ack_policy = CONF_ACK_POLICY_LEGACY,
- .apsd_conf = {0, 0},
- },
- [1] = {
- .queue_id = 1,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
- .ack_policy = CONF_ACK_POLICY_LEGACY,
- .apsd_conf = {0, 0},
- },
- [2] = {
- .queue_id = 2,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
+ [CONF_TX_AC_BE] = {
+ .queue_id = CONF_TX_AC_BE,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
.tsid = CONF_TX_AC_BE,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [3] = {
- .queue_id = 3,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
+ [CONF_TX_AC_BK] = {
+ .queue_id = CONF_TX_AC_BK,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
+ .tsid = CONF_TX_AC_BK,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [4] = {
- .queue_id = 4,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
+ [CONF_TX_AC_VI] = {
+ .queue_id = CONF_TX_AC_VI,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
+ .tsid = CONF_TX_AC_VI,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [5] = {
- .queue_id = 5,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
+ [CONF_TX_AC_VO] = {
+ .queue_id = CONF_TX_AC_VO,
+ .channel_type = CONF_CHANNEL_TYPE_EDCF,
+ .tsid = CONF_TX_AC_VO,
.ps_scheme = CONF_PS_SCHEME_LEGACY,
.ack_policy = CONF_ACK_POLICY_LEGACY,
.apsd_conf = {0, 0},
},
- [6] = {
- .queue_id = 6,
- .channel_type = CONF_CHANNEL_TYPE_DCF,
- .tsid = CONF_TX_AC_BE,
- .ps_scheme = CONF_PS_SCHEME_LEGACY,
- .ack_policy = CONF_ACK_POLICY_LEGACY,
- .apsd_conf = {0, 0},
- }
},
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
.tx_compl_timeout = 700,
@@ -406,8 +382,16 @@ static int wl1271_plt_init(struct wl1271 *wl)
if (ret < 0)
goto out_free_memmap;
- /* Default TID configuration */
+ /* Default TID/AC configuration */
+ BUG_ON(wl->conf.tx.tid_conf_count != wl->conf.tx.ac_conf_count);
for (i = 0; i < wl->conf.tx.tid_conf_count; i++) {
+ conf_ac = &wl->conf.tx.ac_conf[i];
+ ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
+ conf_ac->cw_max, conf_ac->aifsn,
+ conf_ac->tx_op_limit);
+ if (ret < 0)
+ goto out_free_memmap;
+
conf_tid = &wl->conf.tx.tid_conf[i];
ret = wl1271_acx_tid_cfg(wl, conf_tid->queue_id,
conf_tid->channel_type,
@@ -420,16 +404,6 @@ static int wl1271_plt_init(struct wl1271 *wl)
goto out_free_memmap;
}
- /* Default AC configuration */
- for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
- conf_ac = &wl->conf.tx.ac_conf[i];
- ret = wl1271_acx_ac_cfg(wl, conf_ac->ac, conf_ac->cw_min,
- conf_ac->cw_max, conf_ac->aifsn,
- conf_ac->tx_op_limit);
- if (ret < 0)
- goto out_free_memmap;
- }
-
/* Enable data path */
ret = wl1271_cmd_data_path(wl, 1);
if (ret < 0)
--
1.6.3.3
On Mon, 2010-09-27 at 11:37 +0300, Luciano Coelho wrote:
> From: Juuso Oikarinen <[email protected]>
>
> The mac80211 inserts channels into a scan request in the same order the driver
> registers them. Use this fact to optimize scan by ordering the channels so
> that adjacent channels don't get scanned consecutively.
Cute, but not really ...
First of all, iw will also report channels in this order, and that's
just weird.
Secondly, if you pass any channels to scan manually (say with iw), this
assertion is no longer true -- cfg80211 will actually _sort_ the
channels in that case to make sure there are no duplicates.
So you really shouldn't be doing this.
johannes
On Mon, 2010-09-27 at 11:37 +0300, Luciano Coelho wrote:
> - /* queue */
> + /* queue (we use same identifiers for tid's and ac's */
> ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
> - desc->tid = wl1271_tx_ac_to_tid(ac);
> + desc->tid = ac;
That cannot be right unless the "tid" field in "desc" should really be
named "ac", since there are twice as many TIDs as ACs. Nor can
"ac_to_tid" ever be a valid function, for the same reason, it can't be a
surjective function.
If you need the TID (with some fallback for non-QoS frames) you should
probably add that to the tx info somehow.
johannes
From: Juuso Oikarinen <[email protected]>
In the scan state machine, the wl1271_mutex is unlocked first then relocked,
and then the scan state variables are modified.
This makes it possible for ieee80211_scan_complete to be called twice in some
scenarios, as the scan completion event from the firmware may be processed
while the mutex is unlocked.
To fix the issue, move the ieee80211_scan_complete call last in the function.
This is generally safer, but there still may be issues is functions calling
the scan state machine rely on states checked before the unlocking of the
global mutex.
(forward ported from 2.6.32 -- this is not strictly needed anymore, because
the mutex doesn't need to be unlocked anymore, but I'm applying this change
anyway, so that the call to ieee80211_scan_complete is in the same place)
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Saravanan Dhanabal <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_scan.c | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 45d4ce3..02ad6c6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1015,10 +1015,10 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
ieee80211_enable_dyn_ps(wl->vif);
if (wl->scan.state != WL1271_SCAN_STATE_IDLE) {
- ieee80211_scan_completed(wl->hw, true);
wl->scan.state = WL1271_SCAN_STATE_IDLE;
kfree(wl->scan.scanned_ch);
wl->scan.scanned_ch = NULL;
+ ieee80211_scan_completed(wl->hw, true);
}
wl->state = WL1271_STATE_OFF;
diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c b/drivers/net/wireless/wl12xx/wl1271_scan.c
index 9c80ba9..8ceaabe 100644
--- a/drivers/net/wireless/wl12xx/wl1271_scan.c
+++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
@@ -215,12 +215,11 @@ void wl1271_scan_stm(struct wl1271 *wl)
break;
case WL1271_SCAN_STATE_DONE:
- ieee80211_scan_completed(wl->hw, false);
-
kfree(wl->scan.scanned_ch);
wl->scan.scanned_ch = NULL;
wl->scan.state = WL1271_SCAN_STATE_IDLE;
+ ieee80211_scan_completed(wl->hw, false);
break;
default:
--
1.6.3.3
Hi,
On Tue, 2010-10-05 at 17:42 +0200, ext Gabay, Benzy wrote:
> Juuso,
> > > >
> > > > From: Juuso Oikarinen <[email protected]>
> > > >
> > > > Currently then dwell times for each channel in scans is set to an
> > > > overly
> > > > long value, and excessive number of probe-requests are transmitted
> > on
> > > > each
> > > > channel (for active scans.)
> > > >
> > > > Based on testing, comparable results can be received with smaller
> > > > dwell-time,
> > > > and, with fever probe-requests - in fact, reducing the number of
> > probe-
> > > > requests
> > > > to 2 seems to increase the number of found results.
> > >
> > > I think that this does not making any sense. Less prob requests
> > should give you back less results. As less beacons/prob responses are
> > getting back to the station.
> > > I think also that office with 70 AP is not a normal environment to
> > test and optimize numbers.
> > > I would suggest to re-test in a 1-6 AP environment which is making
> > more sense for both home and enterprise environment.
> >
> > We have actually performed more testing than just mentioned here, in
> > varied environments, and all of the testing seems to indicate that
> > reducing the number of probe-reqs per channel is not reducing the
> > number
> > of acquired results. Instead, in some scenarios, it is increasing the
> > number of acquired results.
> >
>
> >> I don’t know if that is conventional request: can you share the full results and setup details?
No, I don't have any formal documentation to share.
The setup details are simple enough though. The tested this on command
line using a simple script that flushes existing scan results, then
performs two or three scans counting the number of scan results on the
last round using grep and wc.
We performed the testing in office environment and a shielded chamber,
which only has selected AP's within it.
Between test rounds we modified the driver parameters related to
scanning, i.e. we modified the number of probe-reqs and the dwell time
on each channel.
-Juuso
> > We did not see reduction in the probability of finding a specific AP in
> > a few (one or two) AP environment either.
> >
> > The effect seems to be this way because reducing the number of
> > probe-req's dramatically reduces the noise generated by probe-responses
> > from AP's on neighbouring channels.
> >
> > -Juuso
> >
On Wed, 2010-10-06 at 07:21 +0200, ext Gabay, Benzy wrote:
> Juuso,
>
>
> > Sent: Tuesday, October 05, 2010 11:59 PM
> >
> > Hi,
> >
> > On Tue, 2010-10-05 at 17:42 +0200, ext Gabay, Benzy wrote:
> > > Juuso,
> >
> > > > > >
> > > > > > From: Juuso Oikarinen <[email protected]>
> > > > > >
> > > > > > Currently then dwell times for each channel in scans is set to
> > an
> > > > > > overly
> > > > > > long value, and excessive number of probe-requests are
> > transmitted
> > > > on
> > > > > > each
> > > > > > channel (for active scans.)
> > > > > >
> > > > > > Based on testing, comparable results can be received with
> > smaller
> > > > > > dwell-time,
> > > > > > and, with fever probe-requests - in fact, reducing the number
> > of
> > > > probe-
> > > > > > requests
> > > > > > to 2 seems to increase the number of found results.
> > > > >
> > > > > I think that this does not making any sense. Less prob requests
> > > > should give you back less results. As less beacons/prob responses
> > are
> > > > getting back to the station.
> > > > > I think also that office with 70 AP is not a normal environment
> > to
> > > > test and optimize numbers.
> > > > > I would suggest to re-test in a 1-6 AP environment which is
> > making
> > > > more sense for both home and enterprise environment.
> > > >
> > > > We have actually performed more testing than just mentioned here,
> > in
> > > > varied environments, and all of the testing seems to indicate that
> > > > reducing the number of probe-reqs per channel is not reducing the
> > > > number
> > > > of acquired results. Instead, in some scenarios, it is increasing
> > the
> > > > number of acquired results.
> > > >
> > >
> > > >> I don’t know if that is conventional request: can you share the
> > full results and setup details?
> >
> > No, I don't have any formal documentation to share.
> >
> > The setup details are simple enough though. The tested this on command
> > line using a simple script that flushes existing scan results, then
> > performs two or three scans counting the number of scan results on the
> > last round using grep and wc.
> >
> > We performed the testing in office environment and a shielded chamber,
> > which only has selected AP's within it.
> >
> > Between test rounds we modified the driver parameters related to
> > scanning, i.e. we modified the number of probe-reqs and the dwell time
> > on each channel.
> >
> > -Juuso
>
>
> Sounds great. Just one more: which AP brands (excluding Cisco) ?
In the office environment we have a variety of brands, including D-link,
Buffalo, Telewell, TP-link and linksys, cisco etc.
In the shielded chamber we are using linksys wrt610n AP's.
-Juuso
>
>
> >
> > > > We did not see reduction in the probability of finding a specific
> > AP in
> > > > a few (one or two) AP environment either.
> > > >
> > > > The effect seems to be this way because reducing the number of
> > > > probe-req's dramatically reduces the noise generated by probe-
> > responses
> > > > from AP's on neighbouring channels.
> > > >
> > > > -Juuso
> > > >
> >
>
> �{.n�+�������+%��lzwm��b�맲��r��zX��"��^�ȧ���ܨ}���Ơz�&j:+v�������zZ+��+zf���h���~����i���z��w���?����&�)ߢf
SnV1c28sDQoNCg0KPiBTZW50OiBUdWVzZGF5LCBPY3RvYmVyIDA1LCAyMDEwIDExOjU5IFBNDQo+
IA0KPiBIaSwNCj4gDQo+IE9uIFR1ZSwgMjAxMC0xMC0wNSBhdCAxNzo0MiArMDIwMCwgZXh0IEdh
YmF5LCBCZW56eSB3cm90ZToNCj4gPiBKdXVzbywNCj4gDQo+ID4gPiA+ID4NCj4gPiA+ID4gPiBG
cm9tOiBKdXVzbyBPaWthcmluZW4gPGp1dXNvLm9pa2FyaW5lbkBub2tpYS5jb20+DQo+ID4gPiA+
ID4NCj4gPiA+ID4gPiBDdXJyZW50bHkgdGhlbiBkd2VsbCB0aW1lcyBmb3IgZWFjaCBjaGFubmVs
IGluIHNjYW5zIGlzIHNldCB0bw0KPiBhbg0KPiA+ID4gPiA+IG92ZXJseQ0KPiA+ID4gPiA+IGxv
bmcgdmFsdWUsIGFuZCBleGNlc3NpdmUgbnVtYmVyIG9mIHByb2JlLXJlcXVlc3RzIGFyZQ0KPiB0
cmFuc21pdHRlZA0KPiA+ID4gb24NCj4gPiA+ID4gPiBlYWNoDQo+ID4gPiA+ID4gY2hhbm5lbCAo
Zm9yIGFjdGl2ZSBzY2Fucy4pDQo+ID4gPiA+ID4NCj4gPiA+ID4gPiBCYXNlZCBvbiB0ZXN0aW5n
LCBjb21wYXJhYmxlIHJlc3VsdHMgY2FuIGJlIHJlY2VpdmVkIHdpdGgNCj4gc21hbGxlcg0KPiA+
ID4gPiA+IGR3ZWxsLXRpbWUsDQo+ID4gPiA+ID4gYW5kLCB3aXRoIGZldmVyIHByb2JlLXJlcXVl
c3RzIC0gaW4gZmFjdCwgcmVkdWNpbmcgdGhlIG51bWJlcg0KPiBvZg0KPiA+ID4gcHJvYmUtDQo+
ID4gPiA+ID4gcmVxdWVzdHMNCj4gPiA+ID4gPiB0byAyIHNlZW1zIHRvIGluY3JlYXNlIHRoZSBu
dW1iZXIgb2YgZm91bmQgcmVzdWx0cy4NCj4gPiA+ID4NCj4gPiA+ID4gSSB0aGluayB0aGF0IHRo
aXMgZG9lcyBub3QgbWFraW5nIGFueSBzZW5zZS4gTGVzcyBwcm9iIHJlcXVlc3RzDQo+ID4gPiBz
aG91bGQgZ2l2ZSB5b3UgYmFjayBsZXNzIHJlc3VsdHMuIEFzIGxlc3MgYmVhY29ucy9wcm9iIHJl
c3BvbnNlcw0KPiBhcmUNCj4gPiA+IGdldHRpbmcgYmFjayB0byB0aGUgc3RhdGlvbi4NCj4gPiA+
ID4gSSB0aGluayBhbHNvIHRoYXQgb2ZmaWNlIHdpdGggNzAgQVAgaXMgbm90IGEgbm9ybWFsIGVu
dmlyb25tZW50DQo+IHRvDQo+ID4gPiB0ZXN0IGFuZCBvcHRpbWl6ZSBudW1iZXJzLg0KPiA+ID4g
PiBJIHdvdWxkIHN1Z2dlc3QgdG8gcmUtdGVzdCBpbiBhIDEtNiBBUCBlbnZpcm9ubWVudCB3aGlj
aCBpcw0KPiBtYWtpbmcNCj4gPiA+IG1vcmUgc2Vuc2UgZm9yIGJvdGggaG9tZSBhbmQgZW50ZXJw
cmlzZSBlbnZpcm9ubWVudC4NCj4gPiA+DQo+ID4gPiBXZSBoYXZlIGFjdHVhbGx5IHBlcmZvcm1l
ZCBtb3JlIHRlc3RpbmcgdGhhbiBqdXN0IG1lbnRpb25lZCBoZXJlLA0KPiBpbg0KPiA+ID4gdmFy
aWVkIGVudmlyb25tZW50cywgYW5kIGFsbCBvZiB0aGUgdGVzdGluZyBzZWVtcyB0byBpbmRpY2F0
ZSB0aGF0DQo+ID4gPiByZWR1Y2luZyB0aGUgbnVtYmVyIG9mIHByb2JlLXJlcXMgcGVyIGNoYW5u
ZWwgaXMgbm90IHJlZHVjaW5nIHRoZQ0KPiA+ID4gbnVtYmVyDQo+ID4gPiBvZiBhY3F1aXJlZCBy
ZXN1bHRzLiBJbnN0ZWFkLCBpbiBzb21lIHNjZW5hcmlvcywgaXQgaXMgaW5jcmVhc2luZw0KPiB0
aGUNCj4gPiA+IG51bWJlciBvZiBhY3F1aXJlZCByZXN1bHRzLg0KPiA+ID4NCj4gPg0KPiA+ID4+
ICBJIGRvbuKAmXQga25vdyBpZiB0aGF0IGlzIGNvbnZlbnRpb25hbCByZXF1ZXN0OiBjYW4geW91
IHNoYXJlIHRoZQ0KPiBmdWxsIHJlc3VsdHMgYW5kIHNldHVwIGRldGFpbHM/DQo+IA0KPiBObywg
SSBkb24ndCBoYXZlIGFueSBmb3JtYWwgZG9jdW1lbnRhdGlvbiB0byBzaGFyZS4NCj4gDQo+IFRo
ZSBzZXR1cCBkZXRhaWxzIGFyZSBzaW1wbGUgZW5vdWdoIHRob3VnaC4gVGhlIHRlc3RlZCB0aGlz
IG9uIGNvbW1hbmQNCj4gbGluZSB1c2luZyBhIHNpbXBsZSBzY3JpcHQgdGhhdCBmbHVzaGVzIGV4
aXN0aW5nIHNjYW4gcmVzdWx0cywgdGhlbg0KPiBwZXJmb3JtcyB0d28gb3IgdGhyZWUgc2NhbnMg
Y291bnRpbmcgdGhlIG51bWJlciBvZiBzY2FuIHJlc3VsdHMgb24gdGhlDQo+IGxhc3Qgcm91bmQg
dXNpbmcgZ3JlcCBhbmQgd2MuDQo+IA0KPiBXZSBwZXJmb3JtZWQgdGhlIHRlc3RpbmcgaW4gb2Zm
aWNlIGVudmlyb25tZW50IGFuZCBhIHNoaWVsZGVkIGNoYW1iZXIsDQo+IHdoaWNoIG9ubHkgaGFz
IHNlbGVjdGVkIEFQJ3Mgd2l0aGluIGl0Lg0KPiANCj4gQmV0d2VlbiB0ZXN0IHJvdW5kcyB3ZSBt
b2RpZmllZCB0aGUgZHJpdmVyIHBhcmFtZXRlcnMgcmVsYXRlZCB0bw0KPiBzY2FubmluZywgaS5l
LiB3ZSBtb2RpZmllZCB0aGUgbnVtYmVyIG9mIHByb2JlLXJlcXMgYW5kIHRoZSBkd2VsbCB0aW1l
DQo+IG9uIGVhY2ggY2hhbm5lbC4NCj4gDQo+IC1KdXVzbw0KDQoNClNvdW5kcyBncmVhdC4gSnVz
dCBvbmUgbW9yZTogd2hpY2ggQVAgYnJhbmRzIChleGNsdWRpbmcgQ2lzY28pID8NCg0KDQoNCj4g
DQo+ID4gPiBXZSBkaWQgbm90IHNlZSByZWR1Y3Rpb24gaW4gdGhlIHByb2JhYmlsaXR5IG9mIGZp
bmRpbmcgYSBzcGVjaWZpYw0KPiBBUCBpbg0KPiA+ID4gYSBmZXcgKG9uZSBvciB0d28pIEFQIGVu
dmlyb25tZW50IGVpdGhlci4NCj4gPiA+DQo+ID4gPiBUaGUgZWZmZWN0IHNlZW1zIHRvIGJlIHRo
aXMgd2F5IGJlY2F1c2UgcmVkdWNpbmcgdGhlIG51bWJlciBvZg0KPiA+ID4gcHJvYmUtcmVxJ3Mg
ZHJhbWF0aWNhbGx5IHJlZHVjZXMgdGhlIG5vaXNlIGdlbmVyYXRlZCBieSBwcm9iZS0NCj4gcmVz
cG9uc2VzDQo+ID4gPiBmcm9tIEFQJ3Mgb24gbmVpZ2hib3VyaW5nIGNoYW5uZWxzLg0KPiA+ID4N
Cj4gPiA+IC1KdXVzbw0KPiA+ID4NCj4gDQoNCg==
On Tue, 2010-10-05 at 07:30 +0200, ext Gabay, Benzy wrote:
> Juuso,
>
> >
> > From: Juuso Oikarinen <[email protected]>
> >
> > Currently then dwell times for each channel in scans is set to an
> > overly
> > long value, and excessive number of probe-requests are transmitted on
> > each
> > channel (for active scans.)
> >
> > Based on testing, comparable results can be received with smaller
> > dwell-time,
> > and, with fever probe-requests - in fact, reducing the number of probe-
> > requests
> > to 2 seems to increase the number of found results.
>
> I think that this does not making any sense. Less prob requests should give you back less results. As less beacons/prob responses are getting back to the station.
> I think also that office with 70 AP is not a normal environment to test and optimize numbers.
> I would suggest to re-test in a 1-6 AP environment which is making more sense for both home and enterprise environment.
We have actually performed more testing than just mentioned here, in
varied environments, and all of the testing seems to indicate that
reducing the number of probe-reqs per channel is not reducing the number
of acquired results. Instead, in some scenarios, it is increasing the
number of acquired results.
We did not see reduction in the probability of finding a specific AP in
a few (one or two) AP environment either.
The effect seems to be this way because reducing the number of
probe-req's dramatically reduces the noise generated by probe-responses
from AP's on neighbouring channels.
-Juuso
>
> >
> > Configure more optimal values for per channel dwell times. Comparison
> > for the
> > different scan configurations (in my current office environment):
> >
> > dwell-time 60000 3x probe-req == ~60 results
> > 40000 3x probe-req == ~50 results
> > 30000 3x probe-req == ~40 results
> >
> > dwell-time 60000 2x probe-req == ~70 results
> > 40000 2x probe-req == ~60 results
> > 30000 2x probe-req == ~58 results
> >
> > The above are results for a cumulative 3 scan run. For individual
> > scans, the
> > number of results drop slightly more.
> >
> > Signed-off-by: Juuso Oikarinen <[email protected]>
> > Reviewed-by: Teemu Paasikivi <[email protected]>
> > Signed-off-by: Luciano Coelho <[email protected]>
> > ---
> > drivers/net/wireless/wl12xx/wl1271_conf.h | 39
> > +++++++++++++++++++++++++++++
> > drivers/net/wireless/wl12xx/wl1271_main.c | 9 ++++++-
> > drivers/net/wireless/wl12xx/wl1271_scan.c | 18 +++++++++---
> > drivers/net/wireless/wl12xx/wl1271_scan.h | 3 --
> > 4 files changed, 60 insertions(+), 9 deletions(-)
> >
> > diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h
> > b/drivers/net/wireless/wl12xx/wl1271_conf.h
> > index feb493e..ab716f5 100644
> > --- a/drivers/net/wireless/wl12xx/wl1271_conf.h
> > +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
> > @@ -1016,6 +1016,44 @@ struct conf_roam_trigger_settings {
> > u8 avg_weight_snr_data;
> > };
> >
> > +struct conf_scan_settings {
> > + /*
> > + * The minimum time to wait on each channel for active scans
> > + *
> > + * Range: 0 - 65536 tu
> > + */
> > + u16 min_dwell_time_active;
> > +
> > + /*
> > + * The maximum time to wait on each channel for active scans
> > + *
> > + * Range: 0 - 65536 tu
> > + */
> > + u16 max_dwell_time_active;
> > +
> > + /*
> > + * The maximum time to wait on each channel for passive scans
> > + *
> > + * Range: 0 - 65536 tu
> > + */
> > + u16 min_dwell_time_passive;
> > +
> > + /*
> > + * The maximum time to wait on each channel for passive scans
> > + *
> > + * Range: 0 - 65536 tu
> > + */
> > + u16 max_dwell_time_passive;
> > +
> > + /*
> > + * Number of probe requests to transmit on each active scan
> > channel
> > + *
> > + * Range: u8
> > + */
> > + u16 num_probe_reqs;
> > +
> > +};
> > +
> > struct conf_drv_settings {
> > struct conf_sg_settings sg;
> > struct conf_rx_settings rx;
> > @@ -1024,6 +1062,7 @@ struct conf_drv_settings {
> > struct conf_itrim_settings itrim;
> > struct conf_pm_config_settings pm_config;
> > struct conf_roam_trigger_settings roam_trigger;
> > + struct conf_scan_settings scan;
> > };
> >
> > #endif
> > diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c
> > b/drivers/net/wireless/wl12xx/wl1271_main.c
> > index 3f4e154..dcbd6f5 100644
> > --- a/drivers/net/wireless/wl12xx/wl1271_main.c
> > +++ b/drivers/net/wireless/wl12xx/wl1271_main.c
> > @@ -232,7 +232,14 @@ static struct conf_drv_settings default_conf = {
> > .avg_weight_rssi_data = 10,
> > .avg_weight_snr_beacon = 20,
> > .avg_weight_snr_data = 10
> > - }
> > + },
> > + .scan = {
> > + .min_dwell_time_active = 7500,
> > + .max_dwell_time_active = 30000,
> > + .min_dwell_time_passive = 30000,
> > + .max_dwell_time_passive = 60000,
> > + .num_probe_reqs = 2,
> > + },
> > };
> >
> > static void __wl1271_op_remove_interface(struct wl1271 *wl);
> > diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c
> > b/drivers/net/wireless/wl12xx/wl1271_scan.c
> > index 37f9ccb..5c76b79 100644
> > --- a/drivers/net/wireless/wl12xx/wl1271_scan.c
> > +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
> > @@ -64,6 +64,7 @@ static int wl1271_get_scan_channels(struct wl1271
> > *wl,
> > struct basic_scan_channel_params *channels,
> > enum ieee80211_band band, bool passive)
> > {
> > + struct conf_scan_settings *c = &wl->conf.scan;
> > int i, j;
> > u32 flags;
> >
> > @@ -91,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271
> > *wl,
> > wl1271_debug(DEBUG_SCAN, "beacon_found %d",
> > req->channels[i]->beacon_found);
> >
> > - channels[j].min_duration =
> > - cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
> > - channels[j].max_duration =
> > - cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
> > + if (!passive) {
> > + channels[j].min_duration =
> > + cpu_to_le32(c->min_dwell_time_active);
> > + channels[j].max_duration =
> > + cpu_to_le32(c->max_dwell_time_active);
> > + } else {
> > + channels[j].min_duration =
> > + cpu_to_le32(c->min_dwell_time_passive);
> > + channels[j].max_duration =
> > + cpu_to_le32(c->max_dwell_time_passive);
> > + }
> > channels[j].early_termination = 0;
> > channels[j].tx_power_att = req->channels[i]-
> > >max_power;
> > channels[j].channel = req->channels[i]->hw_value;
> > @@ -151,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum
> > ieee80211_band band,
> > cmd->params.rx_filter_options =
> > cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN |
> > CFG_RX_BCN_EN);
> >
> > - cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
> > + cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
> > cmd->params.tx_rate = cpu_to_le32(basic_rate);
> > cmd->params.tid_trigger = 0;
> > cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
> > diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h
> > b/drivers/net/wireless/wl12xx/wl1271_scan.h
> > index bb7af2a..6d57127 100644
> > --- a/drivers/net/wireless/wl12xx/wl1271_scan.h
> > +++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
> > @@ -40,11 +40,8 @@ void wl1271_scan_complete_work(struct work_struct
> > *work);
> > #define WL1271_SCAN_OPT_ACTIVE 0
> > #define WL1271_SCAN_OPT_PASSIVE 1
> > #define WL1271_SCAN_OPT_PRIORITY_HIGH 4
> > -#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
> > -#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
> > #define WL1271_SCAN_BAND_2_4_GHZ 0
> > #define WL1271_SCAN_BAND_5_GHZ 1
> > -#define WL1271_SCAN_PROBE_REQS 3
> >
> > #define WL1271_SCAN_TIMEOUT 10000 /* msec */
> >
> > --
>
>
>
> Thank You
> =========
> Benzy Gabay
> OMAP-WLAN Lead
> Texas Instruments
Juuso,
>
> From: Juuso Oikarinen <[email protected]>
>
> Currently then dwell times for each channel in scans is set to an
> overly
> long value, and excessive number of probe-requests are transmitted on
> each
> channel (for active scans.)
>
> Based on testing, comparable results can be received with smaller
> dwell-time,
> and, with fever probe-requests - in fact, reducing the number of probe-
> requests
> to 2 seems to increase the number of found results.
I think that this does not making any sense. Less prob requests should give you back less results. As less beacons/prob responses are getting back to the station.
I think also that office with 70 AP is not a normal environment to test and optimize numbers.
I would suggest to re-test in a 1-6 AP environment which is making more sense for both home and enterprise environment.
>
> Configure more optimal values for per channel dwell times. Comparison
> for the
> different scan configurations (in my current office environment):
>
> dwell-time 60000 3x probe-req == ~60 results
> 40000 3x probe-req == ~50 results
> 30000 3x probe-req == ~40 results
>
> dwell-time 60000 2x probe-req == ~70 results
> 40000 2x probe-req == ~60 results
> 30000 2x probe-req == ~58 results
>
> The above are results for a cumulative 3 scan run. For individual
> scans, the
> number of results drop slightly more.
>
> Signed-off-by: Juuso Oikarinen <[email protected]>
> Reviewed-by: Teemu Paasikivi <[email protected]>
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
> drivers/net/wireless/wl12xx/wl1271_conf.h | 39
> +++++++++++++++++++++++++++++
> drivers/net/wireless/wl12xx/wl1271_main.c | 9 ++++++-
> drivers/net/wireless/wl12xx/wl1271_scan.c | 18 +++++++++---
> drivers/net/wireless/wl12xx/wl1271_scan.h | 3 --
> 4 files changed, 60 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h
> b/drivers/net/wireless/wl12xx/wl1271_conf.h
> index feb493e..ab716f5 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_conf.h
> +++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
> @@ -1016,6 +1016,44 @@ struct conf_roam_trigger_settings {
> u8 avg_weight_snr_data;
> };
>
> +struct conf_scan_settings {
> + /*
> + * The minimum time to wait on each channel for active scans
> + *
> + * Range: 0 - 65536 tu
> + */
> + u16 min_dwell_time_active;
> +
> + /*
> + * The maximum time to wait on each channel for active scans
> + *
> + * Range: 0 - 65536 tu
> + */
> + u16 max_dwell_time_active;
> +
> + /*
> + * The maximum time to wait on each channel for passive scans
> + *
> + * Range: 0 - 65536 tu
> + */
> + u16 min_dwell_time_passive;
> +
> + /*
> + * The maximum time to wait on each channel for passive scans
> + *
> + * Range: 0 - 65536 tu
> + */
> + u16 max_dwell_time_passive;
> +
> + /*
> + * Number of probe requests to transmit on each active scan
> channel
> + *
> + * Range: u8
> + */
> + u16 num_probe_reqs;
> +
> +};
> +
> struct conf_drv_settings {
> struct conf_sg_settings sg;
> struct conf_rx_settings rx;
> @@ -1024,6 +1062,7 @@ struct conf_drv_settings {
> struct conf_itrim_settings itrim;
> struct conf_pm_config_settings pm_config;
> struct conf_roam_trigger_settings roam_trigger;
> + struct conf_scan_settings scan;
> };
>
> #endif
> diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c
> b/drivers/net/wireless/wl12xx/wl1271_main.c
> index 3f4e154..dcbd6f5 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_main.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_main.c
> @@ -232,7 +232,14 @@ static struct conf_drv_settings default_conf = {
> .avg_weight_rssi_data = 10,
> .avg_weight_snr_beacon = 20,
> .avg_weight_snr_data = 10
> - }
> + },
> + .scan = {
> + .min_dwell_time_active = 7500,
> + .max_dwell_time_active = 30000,
> + .min_dwell_time_passive = 30000,
> + .max_dwell_time_passive = 60000,
> + .num_probe_reqs = 2,
> + },
> };
>
> static void __wl1271_op_remove_interface(struct wl1271 *wl);
> diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c
> b/drivers/net/wireless/wl12xx/wl1271_scan.c
> index 37f9ccb..5c76b79 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_scan.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
> @@ -64,6 +64,7 @@ static int wl1271_get_scan_channels(struct wl1271
> *wl,
> struct basic_scan_channel_params *channels,
> enum ieee80211_band band, bool passive)
> {
> + struct conf_scan_settings *c = &wl->conf.scan;
> int i, j;
> u32 flags;
>
> @@ -91,10 +92,17 @@ static int wl1271_get_scan_channels(struct wl1271
> *wl,
> wl1271_debug(DEBUG_SCAN, "beacon_found %d",
> req->channels[i]->beacon_found);
>
> - channels[j].min_duration =
> - cpu_to_le32(WL1271_SCAN_CHAN_MIN_DURATION);
> - channels[j].max_duration =
> - cpu_to_le32(WL1271_SCAN_CHAN_MAX_DURATION);
> + if (!passive) {
> + channels[j].min_duration =
> + cpu_to_le32(c->min_dwell_time_active);
> + channels[j].max_duration =
> + cpu_to_le32(c->max_dwell_time_active);
> + } else {
> + channels[j].min_duration =
> + cpu_to_le32(c->min_dwell_time_passive);
> + channels[j].max_duration =
> + cpu_to_le32(c->max_dwell_time_passive);
> + }
> channels[j].early_termination = 0;
> channels[j].tx_power_att = req->channels[i]-
> >max_power;
> channels[j].channel = req->channels[i]->hw_value;
> @@ -151,7 +159,7 @@ static int wl1271_scan_send(struct wl1271 *wl, enum
> ieee80211_band band,
> cmd->params.rx_filter_options =
> cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN |
> CFG_RX_BCN_EN);
>
> - cmd->params.n_probe_reqs = WL1271_SCAN_PROBE_REQS;
> + cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
> cmd->params.tx_rate = cpu_to_le32(basic_rate);
> cmd->params.tid_trigger = 0;
> cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
> diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.h
> b/drivers/net/wireless/wl12xx/wl1271_scan.h
> index bb7af2a..6d57127 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_scan.h
> +++ b/drivers/net/wireless/wl12xx/wl1271_scan.h
> @@ -40,11 +40,8 @@ void wl1271_scan_complete_work(struct work_struct
> *work);
> #define WL1271_SCAN_OPT_ACTIVE 0
> #define WL1271_SCAN_OPT_PASSIVE 1
> #define WL1271_SCAN_OPT_PRIORITY_HIGH 4
> -#define WL1271_SCAN_CHAN_MIN_DURATION 30000 /* TU */
> -#define WL1271_SCAN_CHAN_MAX_DURATION 60000 /* TU */
> #define WL1271_SCAN_BAND_2_4_GHZ 0
> #define WL1271_SCAN_BAND_5_GHZ 1
> -#define WL1271_SCAN_PROBE_REQS 3
>
> #define WL1271_SCAN_TIMEOUT 10000 /* msec */
>
> --
Thank You
=========
Benzy Gabay
OMAP-WLAN Lead
Texas Instruments
SnV1c28sDQoNCj4gU2VudDogV2VkbmVzZGF5LCBPY3RvYmVyIDA2LCAyMDEwIDEyOjI3IEFNDQo+
IA0KPiBPbiBXZWQsIDIwMTAtMTAtMDYgYXQgMDc6MjEgKzAyMDAsIGV4dCBHYWJheSwgQmVuenkg
d3JvdGU6DQo+ID4gSnV1c28sDQo+ID4NCj4gPg0KPiA+ID4gU2VudDogVHVlc2RheSwgT2N0b2Jl
ciAwNSwgMjAxMCAxMTo1OSBQTQ0KPiA+ID4NCj4gPiA+IEhpLA0KPiA+ID4NCj4gPiA+IE9uIFR1
ZSwgMjAxMC0xMC0wNSBhdCAxNzo0MiArMDIwMCwgZXh0IEdhYmF5LCBCZW56eSB3cm90ZToNCj4g
PiA+ID4gSnV1c28sDQo+ID4gPg0KPiA+ID4gPiA+ID4gPg0KPiA+ID4gPiA+ID4gPiBGcm9tOiBK
dXVzbyBPaWthcmluZW4gPGp1dXNvLm9pa2FyaW5lbkBub2tpYS5jb20+DQo+ID4gPiA+ID4gPiA+
DQo+ID4gPiA+ID4gPiA+IEN1cnJlbnRseSB0aGVuIGR3ZWxsIHRpbWVzIGZvciBlYWNoIGNoYW5u
ZWwgaW4gc2NhbnMgaXMgc2V0DQo+IHRvDQo+ID4gPiBhbg0KPiA+ID4gPiA+ID4gPiBvdmVybHkN
Cj4gPiA+ID4gPiA+ID4gbG9uZyB2YWx1ZSwgYW5kIGV4Y2Vzc2l2ZSBudW1iZXIgb2YgcHJvYmUt
cmVxdWVzdHMgYXJlDQo+ID4gPiB0cmFuc21pdHRlZA0KPiA+ID4gPiA+IG9uDQo+ID4gPiA+ID4g
PiA+IGVhY2gNCj4gPiA+ID4gPiA+ID4gY2hhbm5lbCAoZm9yIGFjdGl2ZSBzY2Fucy4pDQo+ID4g
PiA+ID4gPiA+DQo+ID4gPiA+ID4gPiA+IEJhc2VkIG9uIHRlc3RpbmcsIGNvbXBhcmFibGUgcmVz
dWx0cyBjYW4gYmUgcmVjZWl2ZWQgd2l0aA0KPiA+ID4gc21hbGxlcg0KPiA+ID4gPiA+ID4gPiBk
d2VsbC10aW1lLA0KPiA+ID4gPiA+ID4gPiBhbmQsIHdpdGggZmV2ZXIgcHJvYmUtcmVxdWVzdHMg
LSBpbiBmYWN0LCByZWR1Y2luZyB0aGUNCj4gbnVtYmVyDQo+ID4gPiBvZg0KPiA+ID4gPiA+IHBy
b2JlLQ0KPiA+ID4gPiA+ID4gPiByZXF1ZXN0cw0KPiA+ID4gPiA+ID4gPiB0byAyIHNlZW1zIHRv
IGluY3JlYXNlIHRoZSBudW1iZXIgb2YgZm91bmQgcmVzdWx0cy4NCj4gPiA+ID4gPiA+DQo+ID4g
PiA+ID4gPiBJIHRoaW5rIHRoYXQgdGhpcyBkb2VzIG5vdCBtYWtpbmcgYW55IHNlbnNlLiBMZXNz
IHByb2INCj4gcmVxdWVzdHMNCj4gPiA+ID4gPiBzaG91bGQgZ2l2ZSB5b3UgYmFjayBsZXNzIHJl
c3VsdHMuIEFzIGxlc3MgYmVhY29ucy9wcm9iDQo+IHJlc3BvbnNlcw0KPiA+ID4gYXJlDQo+ID4g
PiA+ID4gZ2V0dGluZyBiYWNrIHRvIHRoZSBzdGF0aW9uLg0KPiA+ID4gPiA+ID4gSSB0aGluayBh
bHNvIHRoYXQgb2ZmaWNlIHdpdGggNzAgQVAgaXMgbm90IGEgbm9ybWFsDQo+IGVudmlyb25tZW50
DQo+ID4gPiB0bw0KPiA+ID4gPiA+IHRlc3QgYW5kIG9wdGltaXplIG51bWJlcnMuDQo+ID4gPiA+
ID4gPiBJIHdvdWxkIHN1Z2dlc3QgdG8gcmUtdGVzdCBpbiBhIDEtNiBBUCBlbnZpcm9ubWVudCB3
aGljaCBpcw0KPiA+ID4gbWFraW5nDQo+ID4gPiA+ID4gbW9yZSBzZW5zZSBmb3IgYm90aCBob21l
IGFuZCBlbnRlcnByaXNlIGVudmlyb25tZW50Lg0KPiA+ID4gPiA+DQo+ID4gPiA+ID4gV2UgaGF2
ZSBhY3R1YWxseSBwZXJmb3JtZWQgbW9yZSB0ZXN0aW5nIHRoYW4ganVzdCBtZW50aW9uZWQNCj4g
aGVyZSwNCj4gPiA+IGluDQo+ID4gPiA+ID4gdmFyaWVkIGVudmlyb25tZW50cywgYW5kIGFsbCBv
ZiB0aGUgdGVzdGluZyBzZWVtcyB0byBpbmRpY2F0ZQ0KPiB0aGF0DQo+ID4gPiA+ID4gcmVkdWNp
bmcgdGhlIG51bWJlciBvZiBwcm9iZS1yZXFzIHBlciBjaGFubmVsIGlzIG5vdCByZWR1Y2luZw0K
PiB0aGUNCj4gPiA+ID4gPiBudW1iZXINCj4gPiA+ID4gPiBvZiBhY3F1aXJlZCByZXN1bHRzLiBJ
bnN0ZWFkLCBpbiBzb21lIHNjZW5hcmlvcywgaXQgaXMNCj4gaW5jcmVhc2luZw0KPiA+ID4gdGhl
DQo+ID4gPiA+ID4gbnVtYmVyIG9mIGFjcXVpcmVkIHJlc3VsdHMuDQo+ID4gPiA+ID4NCj4gPiA+
ID4NCj4gPiA+ID4gPj4gIEkgZG9u4oCZdCBrbm93IGlmIHRoYXQgaXMgY29udmVudGlvbmFsIHJl
cXVlc3Q6IGNhbiB5b3Ugc2hhcmUNCj4gdGhlDQo+ID4gPiBmdWxsIHJlc3VsdHMgYW5kIHNldHVw
IGRldGFpbHM/DQo+ID4gPg0KPiA+ID4gTm8sIEkgZG9uJ3QgaGF2ZSBhbnkgZm9ybWFsIGRvY3Vt
ZW50YXRpb24gdG8gc2hhcmUuDQo+ID4gPg0KPiA+ID4gVGhlIHNldHVwIGRldGFpbHMgYXJlIHNp
bXBsZSBlbm91Z2ggdGhvdWdoLiBUaGUgdGVzdGVkIHRoaXMgb24NCj4gY29tbWFuZA0KPiA+ID4g
bGluZSB1c2luZyBhIHNpbXBsZSBzY3JpcHQgdGhhdCBmbHVzaGVzIGV4aXN0aW5nIHNjYW4gcmVz
dWx0cywgdGhlbg0KPiA+ID4gcGVyZm9ybXMgdHdvIG9yIHRocmVlIHNjYW5zIGNvdW50aW5nIHRo
ZSBudW1iZXIgb2Ygc2NhbiByZXN1bHRzIG9uDQo+IHRoZQ0KPiA+ID4gbGFzdCByb3VuZCB1c2lu
ZyBncmVwIGFuZCB3Yy4NCj4gPiA+DQo+ID4gPiBXZSBwZXJmb3JtZWQgdGhlIHRlc3RpbmcgaW4g
b2ZmaWNlIGVudmlyb25tZW50IGFuZCBhIHNoaWVsZGVkDQo+IGNoYW1iZXIsDQo+ID4gPiB3aGlj
aCBvbmx5IGhhcyBzZWxlY3RlZCBBUCdzIHdpdGhpbiBpdC4NCj4gPiA+DQo+ID4gPiBCZXR3ZWVu
IHRlc3Qgcm91bmRzIHdlIG1vZGlmaWVkIHRoZSBkcml2ZXIgcGFyYW1ldGVycyByZWxhdGVkIHRv
DQo+ID4gPiBzY2FubmluZywgaS5lLiB3ZSBtb2RpZmllZCB0aGUgbnVtYmVyIG9mIHByb2JlLXJl
cXMgYW5kIHRoZSBkd2VsbA0KPiB0aW1lDQo+ID4gPiBvbiBlYWNoIGNoYW5uZWwuDQo+ID4gPg0K
PiA+ID4gLUp1dXNvDQo+ID4NCj4gPg0KPiA+IFNvdW5kcyBncmVhdC4gSnVzdCBvbmUgbW9yZTog
d2hpY2ggQVAgYnJhbmRzIChleGNsdWRpbmcgQ2lzY28pID8NCj4gDQo+IEluIHRoZSBvZmZpY2Ug
ZW52aXJvbm1lbnQgd2UgaGF2ZSBhIHZhcmlldHkgb2YgYnJhbmRzLCBpbmNsdWRpbmcgRC0NCj4g
bGluaywNCj4gQnVmZmFsbywgVGVsZXdlbGwsIFRQLWxpbmsgYW5kIGxpbmtzeXMsIGNpc2NvIGV0
Yy4NCj4gDQo+IEluIHRoZSBzaGllbGRlZCBjaGFtYmVyIHdlIGFyZSB1c2luZyBsaW5rc3lzIHdy
dDYxMG4gQVAncy4NCj4gDQo+IC1KdXVzbw0KPiANCg0KDQpQZXJmZWN0Lg0KDQpJZiBzdGlsbCBu
ZWVkZWQsIEkgQUNLIHRoaXMgY2hhbmdlLg0KDQpCZW56eSBHYWJheQ0KDQoNCg0KDQo+ID4NCj4g
Pg0KPiA+ID4NCj4gPiA+ID4gPiBXZSBkaWQgbm90IHNlZSByZWR1Y3Rpb24gaW4gdGhlIHByb2Jh
YmlsaXR5IG9mIGZpbmRpbmcgYQ0KPiBzcGVjaWZpYw0KPiA+ID4gQVAgaW4NCj4gPiA+ID4gPiBh
IGZldyAob25lIG9yIHR3bykgQVAgZW52aXJvbm1lbnQgZWl0aGVyLg0KPiA+ID4gPiA+DQo+ID4g
PiA+ID4gVGhlIGVmZmVjdCBzZWVtcyB0byBiZSB0aGlzIHdheSBiZWNhdXNlIHJlZHVjaW5nIHRo
ZSBudW1iZXIgb2YNCj4gPiA+ID4gPiBwcm9iZS1yZXEncyBkcmFtYXRpY2FsbHkgcmVkdWNlcyB0
aGUgbm9pc2UgZ2VuZXJhdGVkIGJ5IHByb2JlLQ0KPiA+ID4gcmVzcG9uc2VzDQo+ID4gPiA+ID4g
ZnJvbSBBUCdzIG9uIG5laWdoYm91cmluZyBjaGFubmVscy4NCj4gPiA+ID4gPg0KPiA+ID4gPiA+
IC1KdXVzbw0KPiA+ID4gPiA+DQo+ID4gPg0KPiA+DQo+ID4NCj4gBO+/vXsubu+/vSvvv73vv73v
v73vv73vv73vv73vv70rJe+/ve+/vWx6d23vv73vv71i77+966ey77+977+9cu+/ve+/vXpY77+9
77+9HCLvv73vv71e77+9yKfvv70X77+977+93Kh977+977+977+9xqB677+9Jmo6K3bvv73vv73v
v70N77+977+977+977+9eloNCj4gK++/ve+/vSt6Zu+/ve+/ve+/vWjvv73vv73vv71+77+977+9
77+977+9ae+/ve+/ve+/vXrvv70e77+9d++/ve+/ve+/vT/vv73vv73vv73vv70m77+9Kd+iG2YN
Cj4gDQoNCg==
SnV1c28sDQoNCg0KPiAtLS0tLU9yaWdpbmFsIE1lc3NhZ2UtLS0tLQ0KPiBTZW50OiBXZWRuZXNk
YXksIE9jdG9iZXIgMDYsIDIwMTAgMTI6MzYgQU0NCj4gDQo+IE9uIFdlZCwgMjAxMC0xMC0wNiBh
dCAwNzoyNiArMDIwMCwgZXh0IEdhYmF5LCBCZW56eSB3cm90ZToNCj4gPiBKdXVzbyAsDQo+ID4g
SSB0aG91Z2h0IHRoYXQgdGhlcmUgaXMgbm8gLmluaSBpbiB0aGUgMTI3MSBNQUM4MDIuMTEgc29s
dXRpb24uDQo+ID4gQWNjb3JkaW5nIHRvIHRoZSBjb2RlIGJlbG93IHlvdSBhcmUgZGVjaWRpbmcg
aWYgaXQgaXMgImEiIG9yIG5vdA0KPiBhY2NvcmRpbmcgdG8gTlZTIGZpbGUuDQo+ID4NCj4gPiBJ
cyBpdCBhIHR5cG8gaW4geW91ciBoZWFkZXIgZGVzY3JpcHRpb24gb3IgZGlkIEkgZ2V0IGl0IHdy
b25nPw0KPiANCj4gTm8gdHlwbywgdGhlcmUgaXMgYSBjb25maWd1cmF0aW9uIHNlY3Rpb24gaW5z
aWRlIHRoZSB3bDEyNzEtbnZzLmJpbg0KPiAtZmlsZSByZWZlcnJlZCB0byBhcyB0aGUgIklOSS1z
ZWN0aW9uLiIgVGhhdCBpbmkgc2VjdGlvbiBjb25maWd1cmVzDQo+IGdlbmVyYWwgcGFyYW1ldGVy
cyAoaW5jbHVkaW5nIHRoZSBkdWFsLWJhbmQgc3VwcG9ydCkgYW5kIHNldmVyYWwNCj4gcmFkaW8t
cGFyYW1ldGVycy4NCg0KDQoNCkdvdCBpdC4gDQpUaGFua3MgZm9yIHRoZSBwYXRpZW50Lg0KDQpC
ZW56eQ0KDQoNCj4gDQo+IFRoZXNlIElOSS1wYXJhbWV0ZXJzIGFyZSB0aGUgb25seSB3YXkgZm9y
IHRoZSBkcml2ZXIgdG8ga25vdyB3aGV0aGVyDQo+IHRoZXJlIGlzIDExYSBSRiBzdXBwb3J0IGlu
IHRoZSBoYXJkd2FyZSBvciBub3QuDQo+IA0KPiAtSnV1c28NCg0KDQo+IA0KPiA+ID4gU2VudDog
TW9uZGF5LCBTZXB0ZW1iZXIgMjcsIDIwMTAgMzozOCBBTQ0KPiA+ID4NCj4gPiA+IEZyb206IEp1
dXNvIE9pa2FyaW5lbiA8anV1c28ub2lrYXJpbmVuQG5va2lhLmNvbT4NCj4gPiA+DQo+ID4gPiBJ
bnN0ZWFkIG9mIGhhcmRjb2RpbmcgMTFhIHN1cHBvcnQsIGVuYWJsZS9kaXNhYmxlIGRyaXZlciBz
dXBwb3J0DQo+IGJhc2VkDQo+ID4gPiBvbg0KPiA+ID4gdGhlIGR1YWwtbW9kZS1zZWxlY3QgcGFy
YW1ldGVyIGluIHRoZSBudnMtZmlsZSBnZW5lcmFsIHBhcmFtdGVycy4NCj4gPiA+DQo+ID4gPiBT
aWduZWQtb2ZmLWJ5OiBKdXVzbyBPaWthcmluZW4gPGp1dXNvLm9pa2FyaW5lbkBub2tpYS5jb20+
DQo+ID4gPiBSZXZpZXdlZC1ieTogTHVjaWFubyBDb2VsaG8gPGx1Y2lhbm8uY29lbGhvQG5va2lh
LmNvbT4NCj4gPiA+IFNpZ25lZC1vZmYtYnk6IEx1Y2lhbm8gQ29lbGhvIDxsdWNpYW5vLmNvZWxo
b0Bub2tpYS5jb20+DQo+ID4gPiAtLS0NCj4gDQo+IA0KDQo=
Juuso ,
I thought that there is no .ini in the 1271 MAC802.11 solution.
According to the code below you are deciding if it is "a" or not according to NVS file.
Is it a typo in your header description or did I get it wrong?
> Sent: Monday, September 27, 2010 3:38 AM
>
> From: Juuso Oikarinen <[email protected]>
>
> Instead of hardcoding 11a support, enable/disable driver support based
> on
> the dual-mode-select parameter in the nvs-file general paramters.
>
> Signed-off-by: Juuso Oikarinen <[email protected]>
> Reviewed-by: Luciano Coelho <[email protected]>
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
> drivers/net/wireless/wl12xx/wl1271.h | 18 +++--------------
> -
> drivers/net/wireless/wl12xx/wl1271_boot.c | 22
> ++++++++++++++++++++++
> drivers/net/wireless/wl12xx/wl1271_init.c | 2 +-
> drivers/net/wireless/wl12xx/wl1271_main.c | 18 +++--------------
> -
> drivers/net/wireless/wl12xx/wl1271_scan.c | 2 +-
> drivers/net/wireless/wl12xx/wl1271_testmode.c | 14 +-------------
> 6 files changed, 31 insertions(+), 45 deletions(-)
>
> diff --git a/drivers/net/wireless/wl12xx/wl1271.h
> b/drivers/net/wireless/wl12xx/wl1271.h
> index 1098d16..763ece8 100644
> --- a/drivers/net/wireless/wl12xx/wl1271.h
> +++ b/drivers/net/wireless/wl12xx/wl1271.h
> @@ -117,11 +117,6 @@ enum {
> #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
> #define WL1271_TX_SECURITY_HI32(s) ((u32)(((s) >> 16) & 0xffffffff))
>
> -/*
> - * Enable/disable 802.11a support for WL1273
> - */
> -#undef WL1271_80211A_ENABLED
> -
> #define WL1271_BUSY_WORD_CNT 1
> #define WL1271_BUSY_WORD_LEN (WL1271_BUSY_WORD_CNT * sizeof(u32))
>
> @@ -363,6 +358,7 @@ struct wl1271 {
> u8 *fw;
> size_t fw_len;
> struct wl1271_nvs_file *nvs;
> + size_t nvs_len;
>
> s8 hw_pg_ver;
>
> @@ -476,6 +472,8 @@ struct wl1271 {
>
> bool sg_enabled;
>
> + bool enable_11a;
> +
> struct list_head list;
>
> /* Most recently reported noise in dBm */
> @@ -499,14 +497,4 @@ int wl1271_plt_stop(struct wl1271 *wl);
> #define WL1271_PRE_POWER_ON_SLEEP 20 /* in miliseconds */
> #define WL1271_POWER_ON_SLEEP 200 /* in miliseconds */
>
> -static inline bool wl1271_11a_enabled(void)
> -{
> - /* FIXME: this could be determined based on the NVS-INI file */
> -#ifdef WL1271_80211A_ENABLED
> - return true;
> -#else
> - return false;
> -#endif
> -}
> -
> #endif
> diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c
> b/drivers/net/wireless/wl12xx/wl1271_boot.c
> index f750d5a..b910212 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_boot.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
> @@ -225,6 +225,28 @@ static int wl1271_boot_upload_nvs(struct wl1271
> *wl)
> if (wl->nvs == NULL)
> return -ENODEV;
>
> + /*
> + * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
> band
> + * configurations) can be removed when those NVS files stop
> floating
> + * around.
> + */
> + if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
> + wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
> + if (wl->nvs->general_params.dual_mode_select)
> + wl->enable_11a = true;
> + }
> +
> + if (wl->nvs_len != sizeof(struct wl1271_nvs_file) &&
> + (wl->nvs_len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
> + wl->enable_11a)) {
> + wl1271_error("nvs size is not as expected: %zu != %zu",
> + wl->nvs_len, sizeof(struct wl1271_nvs_file));
> + kfree(wl->nvs);
> + wl->nvs = NULL;
> + wl->nvs_len = 0;
> + return -EILSEQ;
> + }
> +
> /* only the first part of the NVS needs to be uploaded */
> nvs_len = sizeof(wl->nvs->nvs);
> nvs_ptr = (u8 *)wl->nvs->nvs;
> diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c
> b/drivers/net/wireless/wl12xx/wl1271_init.c
> index 4447af1..879bae0 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_init.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_init.c
> @@ -61,7 +61,7 @@ int wl1271_init_templates_config(struct wl1271 *wl)
> if (ret < 0)
> return ret;
>
> - if (wl1271_11a_enabled()) {
> + if (wl->enable_11a) {
> size_t size = sizeof(struct wl12xx_probe_req_template);
> ret = wl1271_cmd_template_set(wl,
> CMD_TEMPL_CFG_PROBE_REQ_5,
> NULL, size, 0,
> diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c
> b/drivers/net/wireless/wl12xx/wl1271_main.c
> index bbd075a..11e112f 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_main.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_main.c
> @@ -622,20 +622,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
> return ret;
> }
>
> - /*
> - * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
> band
> - * configurations) can be removed when those NVS files stop
> floating
> - * around.
> - */
> - if (fw->size != sizeof(struct wl1271_nvs_file) &&
> - (fw->size != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
> - wl1271_11a_enabled())) {
> - wl1271_error("nvs size is not as expected: %zu != %zu",
> - fw->size, sizeof(struct wl1271_nvs_file));
> - ret = -EILSEQ;
> - goto out;
> - }
> -
> wl->nvs = kmemdup(fw->data, sizeof(struct wl1271_nvs_file),
> GFP_KERNEL);
>
> if (!wl->nvs) {
> @@ -644,6 +630,8 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
> goto out;
> }
>
> + wl->nvs_len = fw->size;
> +
> out:
> release_firmware(fw);
>
> @@ -2414,7 +2402,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
> wl->hw->wiphy->max_scan_ssids = 1;
> wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
>
> - if (wl1271_11a_enabled())
> + if (wl->enable_11a)
> wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
> &wl1271_band_5ghz;
>
> wl->hw->queues = 4;
> diff --git a/drivers/net/wireless/wl12xx/wl1271_scan.c
> b/drivers/net/wireless/wl12xx/wl1271_scan.c
> index 7f42ca9..8d30150 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_scan.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_scan.c
> @@ -188,7 +188,7 @@ void wl1271_scan_stm(struct wl1271 *wl)
> ret = wl1271_scan_send(wl, IEEE80211_BAND_2GHZ, true,
> wl->conf.tx.basic_rate);
> if (ret == WL1271_NOTHING_TO_SCAN) {
> - if (wl1271_11a_enabled())
> + if (wl->enable_11a)
> wl->scan.state = WL1271_SCAN_STATE_5GHZ_ACTIVE;
> else
> wl->scan.state = WL1271_SCAN_STATE_DONE;
> diff --git a/drivers/net/wireless/wl12xx/wl1271_testmode.c
> b/drivers/net/wireless/wl12xx/wl1271_testmode.c
> index 6e0952f..a3aa843 100644
> --- a/drivers/net/wireless/wl12xx/wl1271_testmode.c
> +++ b/drivers/net/wireless/wl12xx/wl1271_testmode.c
> @@ -199,19 +199,6 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271
> *wl, struct nlattr *tb[])
> buf = nla_data(tb[WL1271_TM_ATTR_DATA]);
> len = nla_len(tb[WL1271_TM_ATTR_DATA]);
>
> - /*
> - * FIXME: the LEGACY NVS image support (NVS's missing the 5GHz
> band
> - * configurations) can be removed when those NVS files stop
> floating
> - * around.
> - */
> - if (len != sizeof(struct wl1271_nvs_file) &&
> - (len != WL1271_INI_LEGACY_NVS_FILE_SIZE ||
> - wl1271_11a_enabled())) {
> - wl1271_error("nvs size is not as expected: %zu != %zu",
> - len, sizeof(struct wl1271_nvs_file));
> - return -EMSGSIZE;
> - }
> -
> mutex_lock(&wl->mutex);
>
> kfree(wl->nvs);
> @@ -224,6 +211,7 @@ static int wl1271_tm_cmd_nvs_push(struct wl1271
> *wl, struct nlattr *tb[])
> }
>
> memcpy(wl->nvs, buf, len);
> + wl->nvs_len = len;
>
> wl1271_debug(DEBUG_TESTMODE, "testmode pushed nvs");
>
> --
>
Benzy Gabay
On Wed, 2010-10-06 at 07:26 +0200, ext Gabay, Benzy wrote:
> Juuso ,
> I thought that there is no .ini in the 1271 MAC802.11 solution.
> According to the code below you are deciding if it is "a" or not according to NVS file.
>
> Is it a typo in your header description or did I get it wrong?
No typo, there is a configuration section inside the wl1271-nvs.bin
-file referred to as the "INI-section." That ini section configures
general parameters (including the dual-band support) and several
radio-parameters.
These INI-parameters are the only way for the driver to know whether
there is 11a RF support in the hardware or not.
-Juuso
> > Sent: Monday, September 27, 2010 3:38 AM
> >
> > From: Juuso Oikarinen <[email protected]>
> >
> > Instead of hardcoding 11a support, enable/disable driver support based
> > on
> > the dual-mode-select parameter in the nvs-file general paramters.
> >
> > Signed-off-by: Juuso Oikarinen <[email protected]>
> > Reviewed-by: Luciano Coelho <[email protected]>
> > Signed-off-by: Luciano Coelho <[email protected]>
> > ---
SnV1c28sDQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogSnV1c28gT2lr
YXJpbmVuIFttYWlsdG86anV1c28ub2lrYXJpbmVuQG5va2lhLmNvbV0NCj4gU2VudDogVHVlc2Rh
eSwgT2N0b2JlciAwNSwgMjAxMCAxMjo0MSBBTQ0KPiBUbzogR2FiYXksIEJlbnp5DQo+IENjOiBD
b2VsaG8gTHVjaWFubyAoTm9raWEtTVMvSGVsc2lua2kpOyBsaW51eC13aXJlbGVzc0B2Z2VyLmtl
cm5lbC5vcmcNCj4gU3ViamVjdDogUkU6IFtQQVRDSCAyNC8yNV0gd2wxMjcxOiBPcHRpbWl6ZSBz
Y2FuIGR1cmF0aW9uDQo+IA0KPiBPbiBUdWUsIDIwMTAtMTAtMDUgYXQgMDc6MzAgKzAyMDAsIGV4
dCBHYWJheSwgQmVuenkgd3JvdGU6DQo+ID4gSnV1c28sDQo+ID4NCj4gPiA+DQo+ID4gPiBGcm9t
OiBKdXVzbyBPaWthcmluZW4gPGp1dXNvLm9pa2FyaW5lbkBub2tpYS5jb20+DQo+ID4gPg0KPiA+
ID4gQ3VycmVudGx5IHRoZW4gZHdlbGwgdGltZXMgZm9yIGVhY2ggY2hhbm5lbCBpbiBzY2FucyBp
cyBzZXQgdG8gYW4NCj4gPiA+IG92ZXJseQ0KPiA+ID4gbG9uZyB2YWx1ZSwgYW5kIGV4Y2Vzc2l2
ZSBudW1iZXIgb2YgcHJvYmUtcmVxdWVzdHMgYXJlIHRyYW5zbWl0dGVkDQo+IG9uDQo+ID4gPiBl
YWNoDQo+ID4gPiBjaGFubmVsIChmb3IgYWN0aXZlIHNjYW5zLikNCj4gPiA+DQo+ID4gPiBCYXNl
ZCBvbiB0ZXN0aW5nLCBjb21wYXJhYmxlIHJlc3VsdHMgY2FuIGJlIHJlY2VpdmVkIHdpdGggc21h
bGxlcg0KPiA+ID4gZHdlbGwtdGltZSwNCj4gPiA+IGFuZCwgd2l0aCBmZXZlciBwcm9iZS1yZXF1
ZXN0cyAtIGluIGZhY3QsIHJlZHVjaW5nIHRoZSBudW1iZXIgb2YNCj4gcHJvYmUtDQo+ID4gPiBy
ZXF1ZXN0cw0KPiA+ID4gdG8gMiBzZWVtcyB0byBpbmNyZWFzZSB0aGUgbnVtYmVyIG9mIGZvdW5k
IHJlc3VsdHMuDQo+ID4NCj4gPiBJIHRoaW5rIHRoYXQgdGhpcyBkb2VzIG5vdCBtYWtpbmcgYW55
IHNlbnNlLiBMZXNzIHByb2IgcmVxdWVzdHMNCj4gc2hvdWxkIGdpdmUgeW91IGJhY2sgbGVzcyBy
ZXN1bHRzLiBBcyBsZXNzIGJlYWNvbnMvcHJvYiByZXNwb25zZXMgYXJlDQo+IGdldHRpbmcgYmFj
ayB0byB0aGUgc3RhdGlvbi4NCj4gPiBJIHRoaW5rIGFsc28gdGhhdCBvZmZpY2Ugd2l0aCA3MCBB
UCBpcyBub3QgYSBub3JtYWwgZW52aXJvbm1lbnQgdG8NCj4gdGVzdCBhbmQgb3B0aW1pemUgbnVt
YmVycy4NCj4gPiBJIHdvdWxkIHN1Z2dlc3QgdG8gcmUtdGVzdCBpbiBhIDEtNiBBUCBlbnZpcm9u
bWVudCB3aGljaCBpcyBtYWtpbmcNCj4gbW9yZSBzZW5zZSBmb3IgYm90aCBob21lIGFuZCBlbnRl
cnByaXNlIGVudmlyb25tZW50Lg0KPiANCj4gV2UgaGF2ZSBhY3R1YWxseSBwZXJmb3JtZWQgbW9y
ZSB0ZXN0aW5nIHRoYW4ganVzdCBtZW50aW9uZWQgaGVyZSwgaW4NCj4gdmFyaWVkIGVudmlyb25t
ZW50cywgYW5kIGFsbCBvZiB0aGUgdGVzdGluZyBzZWVtcyB0byBpbmRpY2F0ZSB0aGF0DQo+IHJl
ZHVjaW5nIHRoZSBudW1iZXIgb2YgcHJvYmUtcmVxcyBwZXIgY2hhbm5lbCBpcyBub3QgcmVkdWNp
bmcgdGhlDQo+IG51bWJlcg0KPiBvZiBhY3F1aXJlZCByZXN1bHRzLiBJbnN0ZWFkLCBpbiBzb21l
IHNjZW5hcmlvcywgaXQgaXMgaW5jcmVhc2luZyB0aGUNCj4gbnVtYmVyIG9mIGFjcXVpcmVkIHJl
c3VsdHMuDQo+IA0KDQo+PiAgSSBkb27igJl0IGtub3cgaWYgdGhhdCBpcyBjb252ZW50aW9uYWwg
cmVxdWVzdDogY2FuIHlvdSBzaGFyZSB0aGUgZnVsbCByZXN1bHRzIGFuZCBzZXR1cCBkZXRhaWxz
Pw0KDQo+IFdlIGRpZCBub3Qgc2VlIHJlZHVjdGlvbiBpbiB0aGUgcHJvYmFiaWxpdHkgb2YgZmlu
ZGluZyBhIHNwZWNpZmljIEFQIGluDQo+IGEgZmV3IChvbmUgb3IgdHdvKSBBUCBlbnZpcm9ubWVu
dCBlaXRoZXIuDQo+IA0KPiBUaGUgZWZmZWN0IHNlZW1zIHRvIGJlIHRoaXMgd2F5IGJlY2F1c2Ug
cmVkdWNpbmcgdGhlIG51bWJlciBvZg0KPiBwcm9iZS1yZXEncyBkcmFtYXRpY2FsbHkgcmVkdWNl
cyB0aGUgbm9pc2UgZ2VuZXJhdGVkIGJ5IHByb2JlLXJlc3BvbnNlcw0KPiBmcm9tIEFQJ3Mgb24g
bmVpZ2hib3VyaW5nIGNoYW5uZWxzLg0KPiANCj4gLUp1dXNvDQo+IA0KDQo+IA0KPiANCj4gPg0K
PiA+ID4NCj4gPiA+IENvbmZpZ3VyZSBtb3JlIG9wdGltYWwgdmFsdWVzIGZvciBwZXIgY2hhbm5l
bCBkd2VsbCB0aW1lcy4NCj4gQ29tcGFyaXNvbg0KPiA+ID4gZm9yIHRoZQ0KPiA+ID4gZGlmZmVy
ZW50IHNjYW4gY29uZmlndXJhdGlvbnMgKGluIG15IGN1cnJlbnQgb2ZmaWNlIGVudmlyb25tZW50
KToNCj4gPiA+DQo+ID4gPiBkd2VsbC10aW1lIDYwMDAwICAgM3ggcHJvYmUtcmVxID09IH42MCBy
ZXN1bHRzDQo+ID4gPiAgICAgICAgICAgIDQwMDAwICAgM3ggcHJvYmUtcmVxID09IH41MCByZXN1
bHRzDQo+ID4gPiAgICAgICAgICAgIDMwMDAwICAgM3ggcHJvYmUtcmVxID09IH40MCByZXN1bHRz
DQo+ID4gPg0KPiA+ID4gZHdlbGwtdGltZSA2MDAwMCAgIDJ4IHByb2JlLXJlcSA9PSB+NzAgcmVz
dWx0cw0KPiA+ID4gICAgICAgICAgICA0MDAwMCAgIDJ4IHByb2JlLXJlcSA9PSB+NjAgcmVzdWx0
cw0KPiA+ID4gICAgICAgICAgICAzMDAwMCAgIDJ4IHByb2JlLXJlcSA9PSB+NTggcmVzdWx0cw0K
PiA+ID4NCj4gPiA+IFRoZSBhYm92ZSBhcmUgcmVzdWx0cyBmb3IgYSBjdW11bGF0aXZlIDMgc2Nh
biBydW4uIEZvciBpbmRpdmlkdWFsDQo+ID4gPiBzY2FucywgdGhlDQo+ID4gPiBudW1iZXIgb2Yg
cmVzdWx0cyBkcm9wIHNsaWdodGx5IG1vcmUuDQo+ID4gPg0KPiA+ID4gU2lnbmVkLW9mZi1ieTog
SnV1c28gT2lrYXJpbmVuIDxqdXVzby5vaWthcmluZW5Abm9raWEuY29tPg0KPiA+ID4gUmV2aWV3
ZWQtYnk6IFRlZW11IFBhYXNpa2l2aSA8ZXh0LXRlZW11LjMucGFhc2lraXZpQG5va2lhLmNvbT4N
Cj4gPiA+IFNpZ25lZC1vZmYtYnk6IEx1Y2lhbm8gQ29lbGhvIDxsdWNpYW5vLmNvZWxob0Bub2tp
YS5jb20+DQo+ID4gPiAtLS0NCj4gPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy93bDEyeHgvd2wx
MjcxX2NvbmYuaCB8ICAgMzkNCj4gPiA+ICsrKysrKysrKysrKysrKysrKysrKysrKysrKysrDQo+
ID4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3dsMTI3MV9tYWluLmMgfCAgICA5ICsr
KysrKy0NCj4gPiA+ICBkcml2ZXJzL25ldC93aXJlbGVzcy93bDEyeHgvd2wxMjcxX3NjYW4uYyB8
ICAgMTggKysrKysrKysrLS0tDQo+ID4gPiAgZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3ds
MTI3MV9zY2FuLmggfCAgICAzIC0tDQo+ID4gPiAgNCBmaWxlcyBjaGFuZ2VkLCA2MCBpbnNlcnRp
b25zKCspLCA5IGRlbGV0aW9ucygtKQ0KPiA+ID4NCj4gPiA+IGRpZmYgLS1naXQgYS9kcml2ZXJz
L25ldC93aXJlbGVzcy93bDEyeHgvd2wxMjcxX2NvbmYuaA0KPiA+ID4gYi9kcml2ZXJzL25ldC93
aXJlbGVzcy93bDEyeHgvd2wxMjcxX2NvbmYuaA0KPiA+ID4gaW5kZXggZmViNDkzZS4uYWI3MTZm
NSAxMDA2NDQNCj4gPiA+IC0tLSBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3dsMTJ4eC93bDEyNzFf
Y29uZi5oDQo+ID4gPiArKysgYi9kcml2ZXJzL25ldC93aXJlbGVzcy93bDEyeHgvd2wxMjcxX2Nv
bmYuaA0KPiA+ID4gQEAgLTEwMTYsNiArMTAxNiw0NCBAQCBzdHJ1Y3QgY29uZl9yb2FtX3RyaWdn
ZXJfc2V0dGluZ3Mgew0KPiA+ID4gIAl1OCBhdmdfd2VpZ2h0X3Nucl9kYXRhOw0KPiA+ID4gIH07
DQo+ID4gPg0KPiA+ID4gK3N0cnVjdCBjb25mX3NjYW5fc2V0dGluZ3Mgew0KPiA+ID4gKwkvKg0K
PiA+ID4gKwkgKiBUaGUgbWluaW11bSB0aW1lIHRvIHdhaXQgb24gZWFjaCBjaGFubmVsIGZvciBh
Y3RpdmUgc2NhbnMNCj4gPiA+ICsJICoNCj4gPiA+ICsJICogUmFuZ2U6IDAgLSA2NTUzNiB0dQ0K
PiA+ID4gKwkgKi8NCj4gPiA+ICsJdTE2IG1pbl9kd2VsbF90aW1lX2FjdGl2ZTsNCj4gPiA+ICsN
Cj4gPiA+ICsJLyoNCj4gPiA+ICsJICogVGhlIG1heGltdW0gdGltZSB0byB3YWl0IG9uIGVhY2gg
Y2hhbm5lbCBmb3IgYWN0aXZlIHNjYW5zDQo+ID4gPiArCSAqDQo+ID4gPiArCSAqIFJhbmdlOiAw
IC0gNjU1MzYgdHUNCj4gPiA+ICsJICovDQo+ID4gPiArCXUxNiBtYXhfZHdlbGxfdGltZV9hY3Rp
dmU7DQo+ID4gPiArDQo+ID4gPiArCS8qDQo+ID4gPiArCSAqIFRoZSBtYXhpbXVtIHRpbWUgdG8g
d2FpdCBvbiBlYWNoIGNoYW5uZWwgZm9yIHBhc3NpdmUgc2NhbnMNCj4gPiA+ICsJICoNCj4gPiA+
ICsJICogUmFuZ2U6IDAgLSA2NTUzNiB0dQ0KPiA+ID4gKwkgKi8NCj4gPiA+ICsJdTE2IG1pbl9k
d2VsbF90aW1lX3Bhc3NpdmU7DQo+ID4gPiArDQo+ID4gPiArCS8qDQo+ID4gPiArCSAqIFRoZSBt
YXhpbXVtIHRpbWUgdG8gd2FpdCBvbiBlYWNoIGNoYW5uZWwgZm9yIHBhc3NpdmUgc2NhbnMNCj4g
PiA+ICsJICoNCj4gPiA+ICsJICogUmFuZ2U6IDAgLSA2NTUzNiB0dQ0KPiA+ID4gKwkgKi8NCj4g
PiA+ICsJdTE2IG1heF9kd2VsbF90aW1lX3Bhc3NpdmU7DQo+ID4gPiArDQo+ID4gPiArCS8qDQo+
ID4gPiArCSAqIE51bWJlciBvZiBwcm9iZSByZXF1ZXN0cyB0byB0cmFuc21pdCBvbiBlYWNoIGFj
dGl2ZSBzY2FuDQo+ID4gPiBjaGFubmVsDQo+ID4gPiArCSAqDQo+ID4gPiArCSAqIFJhbmdlOiB1
OA0KPiA+ID4gKwkgKi8NCj4gPiA+ICsJdTE2IG51bV9wcm9iZV9yZXFzOw0KPiA+ID4gKw0KPiA+
ID4gK307DQo+ID4gPiArDQo+ID4gPiAgc3RydWN0IGNvbmZfZHJ2X3NldHRpbmdzIHsNCj4gPiA+
ICAJc3RydWN0IGNvbmZfc2dfc2V0dGluZ3Mgc2c7DQo+ID4gPiAgCXN0cnVjdCBjb25mX3J4X3Nl
dHRpbmdzIHJ4Ow0KPiA+ID4gQEAgLTEwMjQsNiArMTA2Miw3IEBAIHN0cnVjdCBjb25mX2Rydl9z
ZXR0aW5ncyB7DQo+ID4gPiAgCXN0cnVjdCBjb25mX2l0cmltX3NldHRpbmdzIGl0cmltOw0KPiA+
ID4gIAlzdHJ1Y3QgY29uZl9wbV9jb25maWdfc2V0dGluZ3MgcG1fY29uZmlnOw0KPiA+ID4gIAlz
dHJ1Y3QgY29uZl9yb2FtX3RyaWdnZXJfc2V0dGluZ3Mgcm9hbV90cmlnZ2VyOw0KPiA+ID4gKwlz
dHJ1Y3QgY29uZl9zY2FuX3NldHRpbmdzIHNjYW47DQo+ID4gPiAgfTsNCj4gPiA+DQo+ID4gPiAg
I2VuZGlmDQo+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3ds
MTI3MV9tYWluLmMNCj4gPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3dsMTI3MV9t
YWluLmMNCj4gPiA+IGluZGV4IDNmNGUxNTQuLmRjYmQ2ZjUgMTAwNjQ0DQo+ID4gPiAtLS0gYS9k
cml2ZXJzL25ldC93aXJlbGVzcy93bDEyeHgvd2wxMjcxX21haW4uYw0KPiA+ID4gKysrIGIvZHJp
dmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3dsMTI3MV9tYWluLmMNCj4gPiA+IEBAIC0yMzIsNyAr
MjMyLDE0IEBAIHN0YXRpYyBzdHJ1Y3QgY29uZl9kcnZfc2V0dGluZ3MgZGVmYXVsdF9jb25mID0N
Cj4gew0KPiA+ID4gIAkJLmF2Z193ZWlnaHRfcnNzaV9kYXRhICAgICAgICAgPSAxMCwNCj4gPiA+
ICAJCS5hdmdfd2VpZ2h0X3Nucl9iZWFjb24gICAgICAgID0gMjAsDQo+ID4gPiAgCQkuYXZnX3dl
aWdodF9zbnJfZGF0YSAgICAgICAgICA9IDEwDQo+ID4gPiAtCX0NCj4gPiA+ICsJfSwNCj4gPiA+
ICsJLnNjYW4gPSB7DQo+ID4gPiArCQkubWluX2R3ZWxsX3RpbWVfYWN0aXZlICAgICAgICA9IDc1
MDAsDQo+ID4gPiArCQkubWF4X2R3ZWxsX3RpbWVfYWN0aXZlICAgICAgICA9IDMwMDAwLA0KPiA+
ID4gKwkJLm1pbl9kd2VsbF90aW1lX3Bhc3NpdmUgICAgICAgPSAzMDAwMCwNCj4gPiA+ICsJCS5t
YXhfZHdlbGxfdGltZV9wYXNzaXZlICAgICAgID0gNjAwMDAsDQo+ID4gPiArCQkubnVtX3Byb2Jl
X3JlcXMgICAgICAgICAgICAgICA9IDIsDQo+ID4gPiArCX0sDQo+ID4gPiAgfTsNCj4gPiA+DQo+
ID4gPiAgc3RhdGljIHZvaWQgX193bDEyNzFfb3BfcmVtb3ZlX2ludGVyZmFjZShzdHJ1Y3Qgd2wx
MjcxICp3bCk7DQo+ID4gPiBkaWZmIC0tZ2l0IGEvZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4
L3dsMTI3MV9zY2FuLmMNCj4gPiA+IGIvZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3dsMTI3
MV9zY2FuLmMNCj4gPiA+IGluZGV4IDM3ZjljY2IuLjVjNzZiNzkgMTAwNjQ0DQo+ID4gPiAtLS0g
YS9kcml2ZXJzL25ldC93aXJlbGVzcy93bDEyeHgvd2wxMjcxX3NjYW4uYw0KPiA+ID4gKysrIGIv
ZHJpdmVycy9uZXQvd2lyZWxlc3Mvd2wxMnh4L3dsMTI3MV9zY2FuLmMNCj4gPiA+IEBAIC02NCw2
ICs2NCw3IEBAIHN0YXRpYyBpbnQgd2wxMjcxX2dldF9zY2FuX2NoYW5uZWxzKHN0cnVjdCB3bDEy
NzENCj4gPiA+ICp3bCwNCj4gPiA+ICAJCQkJICAgIHN0cnVjdCBiYXNpY19zY2FuX2NoYW5uZWxf
cGFyYW1zICpjaGFubmVscywNCj4gPiA+ICAJCQkJICAgIGVudW0gaWVlZTgwMjExX2JhbmQgYmFu
ZCwgYm9vbCBwYXNzaXZlKQ0KPiA+ID4gIHsNCj4gPiA+ICsJc3RydWN0IGNvbmZfc2Nhbl9zZXR0
aW5ncyAqYyA9ICZ3bC0+Y29uZi5zY2FuOw0KPiA+ID4gIAlpbnQgaSwgajsNCj4gPiA+ICAJdTMy
IGZsYWdzOw0KPiA+ID4NCj4gPiA+IEBAIC05MSwxMCArOTIsMTcgQEAgc3RhdGljIGludCB3bDEy
NzFfZ2V0X3NjYW5fY2hhbm5lbHMoc3RydWN0DQo+IHdsMTI3MQ0KPiA+ID4gKndsLA0KPiA+ID4g
IAkJCXdsMTI3MV9kZWJ1ZyhERUJVR19TQ0FOLCAiYmVhY29uX2ZvdW5kICVkIiwNCj4gPiA+ICAJ
CQkJICAgICByZXEtPmNoYW5uZWxzW2ldLT5iZWFjb25fZm91bmQpOw0KPiA+ID4NCj4gPiA+IC0J
CQljaGFubmVsc1tqXS5taW5fZHVyYXRpb24gPQ0KPiA+ID4gLQkJCQljcHVfdG9fbGUzMihXTDEy
NzFfU0NBTl9DSEFOX01JTl9EVVJBVElPTik7DQo+ID4gPiAtCQkJY2hhbm5lbHNbal0ubWF4X2R1
cmF0aW9uID0NCj4gPiA+IC0JCQkJY3B1X3RvX2xlMzIoV0wxMjcxX1NDQU5fQ0hBTl9NQVhfRFVS
QVRJT04pOw0KPiA+ID4gKwkJCWlmICghcGFzc2l2ZSkgew0KPiA+ID4gKwkJCQljaGFubmVsc1tq
XS5taW5fZHVyYXRpb24gPQ0KPiA+ID4gKwkJCQkJY3B1X3RvX2xlMzIoYy0+bWluX2R3ZWxsX3Rp
bWVfYWN0aXZlKTsNCj4gPiA+ICsJCQkJY2hhbm5lbHNbal0ubWF4X2R1cmF0aW9uID0NCj4gPiA+
ICsJCQkJCWNwdV90b19sZTMyKGMtPm1heF9kd2VsbF90aW1lX2FjdGl2ZSk7DQo+ID4gPiArCQkJ
fSBlbHNlIHsNCj4gPiA+ICsJCQkJY2hhbm5lbHNbal0ubWluX2R1cmF0aW9uID0NCj4gPiA+ICsJ
CQkJCWNwdV90b19sZTMyKGMtPm1pbl9kd2VsbF90aW1lX3Bhc3NpdmUpOw0KPiA+ID4gKwkJCQlj
aGFubmVsc1tqXS5tYXhfZHVyYXRpb24gPQ0KPiA+ID4gKwkJCQkJY3B1X3RvX2xlMzIoYy0+bWF4
X2R3ZWxsX3RpbWVfcGFzc2l2ZSk7DQo+ID4gPiArCQkJfQ0KPiA+ID4gIAkJCWNoYW5uZWxzW2pd
LmVhcmx5X3Rlcm1pbmF0aW9uID0gMDsNCj4gPiA+ICAJCQljaGFubmVsc1tqXS50eF9wb3dlcl9h
dHQgPSByZXEtPmNoYW5uZWxzW2ldLQ0KPiA+ID4gPm1heF9wb3dlcjsNCj4gPiA+ICAJCQljaGFu
bmVsc1tqXS5jaGFubmVsID0gcmVxLT5jaGFubmVsc1tpXS0+aHdfdmFsdWU7DQo+ID4gPiBAQCAt
MTUxLDcgKzE1OSw3IEBAIHN0YXRpYyBpbnQgd2wxMjcxX3NjYW5fc2VuZChzdHJ1Y3Qgd2wxMjcx
ICp3bCwNCj4gZW51bQ0KPiA+ID4gaWVlZTgwMjExX2JhbmQgYmFuZCwNCj4gPiA+ICAJY21kLT5w
YXJhbXMucnhfZmlsdGVyX29wdGlvbnMgPQ0KPiA+ID4gIAkJY3B1X3RvX2xlMzIoQ0ZHX1JYX1BS
U1BfRU4gfCBDRkdfUlhfTUdNVF9FTiB8DQo+ID4gPiBDRkdfUlhfQkNOX0VOKTsNCj4gPiA+DQo+
ID4gPiAtCWNtZC0+cGFyYW1zLm5fcHJvYmVfcmVxcyA9IFdMMTI3MV9TQ0FOX1BST0JFX1JFUVM7
DQo+ID4gPiArCWNtZC0+cGFyYW1zLm5fcHJvYmVfcmVxcyA9IHdsLT5jb25mLnNjYW4ubnVtX3By
b2JlX3JlcXM7DQo+ID4gPiAgCWNtZC0+cGFyYW1zLnR4X3JhdGUgPSBjcHVfdG9fbGUzMihiYXNp
Y19yYXRlKTsNCj4gPiA+ICAJY21kLT5wYXJhbXMudGlkX3RyaWdnZXIgPSAwOw0KPiA+ID4gIAlj
bWQtPnBhcmFtcy5zY2FuX3RhZyA9IFdMMTI3MV9TQ0FOX0RFRkFVTFRfVEFHOw0KPiA+ID4gZGlm
ZiAtLWdpdCBhL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3dsMTJ4eC93bDEyNzFfc2Nhbi5oDQo+ID4g
PiBiL2RyaXZlcnMvbmV0L3dpcmVsZXNzL3dsMTJ4eC93bDEyNzFfc2Nhbi5oDQo+ID4gPiBpbmRl
eCBiYjdhZjJhLi42ZDU3MTI3IDEwMDY0NA0KPiA+ID4gLS0tIGEvZHJpdmVycy9uZXQvd2lyZWxl
c3Mvd2wxMnh4L3dsMTI3MV9zY2FuLmgNCj4gPiA+ICsrKyBiL2RyaXZlcnMvbmV0L3dpcmVsZXNz
L3dsMTJ4eC93bDEyNzFfc2Nhbi5oDQo+ID4gPiBAQCAtNDAsMTEgKzQwLDggQEAgdm9pZCB3bDEy
NzFfc2Nhbl9jb21wbGV0ZV93b3JrKHN0cnVjdA0KPiB3b3JrX3N0cnVjdA0KPiA+ID4gKndvcmsp
Ow0KPiA+ID4gICNkZWZpbmUgV0wxMjcxX1NDQU5fT1BUX0FDVElWRSAgICAgICAgIDANCj4gPiA+
ICAjZGVmaW5lIFdMMTI3MV9TQ0FOX09QVF9QQVNTSVZFCSAgICAgICAxDQo+ID4gPiAgI2RlZmlu
ZSBXTDEyNzFfU0NBTl9PUFRfUFJJT1JJVFlfSElHSCAgNA0KPiA+ID4gLSNkZWZpbmUgV0wxMjcx
X1NDQU5fQ0hBTl9NSU5fRFVSQVRJT04gIDMwMDAwICAvKiBUVSAqLw0KPiA+ID4gLSNkZWZpbmUg
V0wxMjcxX1NDQU5fQ0hBTl9NQVhfRFVSQVRJT04gIDYwMDAwICAvKiBUVSAqLw0KPiA+ID4gICNk
ZWZpbmUgV0wxMjcxX1NDQU5fQkFORF8yXzRfR0haIDANCj4gPiA+ICAjZGVmaW5lIFdMMTI3MV9T
Q0FOX0JBTkRfNV9HSFogMQ0KPiA+ID4gLSNkZWZpbmUgV0wxMjcxX1NDQU5fUFJPQkVfUkVRUyAz
DQo+ID4gPg0KPiA+ID4gICNkZWZpbmUgV0wxMjcxX1NDQU5fVElNRU9VVCAgICAxMDAwMCAvKiBt
c2VjICovDQo+ID4gPg0KPiA+ID4gLS0NCj4gPg0KPiA+DQo+ID4NCj4gPiBUaGFuayBZb3UNCj4g
PiA9PT09PT09PT0NCj4gPiBCZW56eSBHYWJheQ0KPiA+IE9NQVAtV0xBTiBMZWFkDQo+ID4gVGV4
YXMgSW5zdHJ1bWVudHMNCj4gDQoNCg==