Hi John,
It has been a while since I last sent patches for wl1271, but there hasn't been too much going on with the wl1271 driver itself. Most of our work is going to mac80211 at the moment.
Anyway, it's time to send them so that we catch up.
Cheers,
Luca.
Juuso Oikarinen (2):
wl1271: Improve command polling
wl1271: Rewrite hardware keep-alive handling
Luciano Coelho (1):
wl1271: fix a bunch of sparse warnings
Saravanan Dhanabal (1):
wl1271: Configure QOS nullfunc template for U-APSD
drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_boot.c | 8 +-
drivers/net/wireless/wl12xx/wl1271_cmd.c | 14 ++--
drivers/net/wireless/wl12xx/wl1271_conf.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 95 +++++++++++++++--------------
5 files changed, 63 insertions(+), 58 deletions(-)
From: Saravanan Dhanabal <[email protected]>
When U-APSD is enabled, device is not sending power save
state notifications to AP using QOS nullfunc frames.
This patch configures nullfunc templates needed for U-APSD.
Signed-off-by: Saravanan Dhanabal <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index e53dfc9..26e8fb1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1708,6 +1708,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out_sleep;
+ ret = wl1271_build_qos_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
+
/* filter out all packets not from this BSSID */
wl1271_configure_filters(wl, 0);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
In testing I noticed that the wl1271 commands fall into two categories. In the
first category are "fast" commands, these mostly take only 0 or 1 polls to
complete, but occasionally upto 50 (giving a 0.5ms execution time.) In the
second category, the command completion takes well more than 0.5ms (from
1.5ms upwards.)
This patch fixes command polling such that it is optimal for the fast commands,
but also allows sleep for the longer ones.
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 | 10 +++++-----
1 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 6b5ba8e..61fb774 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -37,7 +37,7 @@
#include "wl1271_cmd.h"
#include "wl1271_event.h"
-#define WL1271_CMD_POLL_COUNT 5
+#define WL1271_CMD_FAST_POLL_COUNT 50
/*
* send command to firmware
@@ -77,11 +77,11 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
goto out;
}
- udelay(10);
poll_count++;
- if (poll_count == WL1271_CMD_POLL_COUNT)
- wl1271_info("cmd polling took over %d cycles",
- poll_count);
+ if (poll_count < WL1271_CMD_FAST_POLL_COUNT)
+ udelay(10);
+ else
+ msleep(1);
intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
}
--
1.6.3.3
A couple of sparse warnings in some rate settings (missing cpu_to_le32) were
fixed. Changed the conf_sg_settings struct from le to native endianess. The
values are converted to le when copying them to the acx command instead.
Reported-by: Johannes Berg <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ++++----
drivers/net/wireless/wl12xx/wl1271_cmd.c | 4 ++--
drivers/net/wireless/wl12xx/wl1271_conf.h | 2 +-
4 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 2ad086e..e19e2f8 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -590,7 +590,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
/* BT-WLAN coext parameters */
for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
- param->params[i] = c->params[i];
+ param->params[i] = cpu_to_le32(c->params[i]);
param->param_idx = CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index 8087dc1..acb1d9e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -351,7 +351,7 @@ static int wl1271_boot_soft_reset(struct wl1271 *wl)
static int wl1271_boot_run_firmware(struct wl1271 *wl)
{
int loop, ret;
- u32 chip_id, interrupt;
+ u32 chip_id, intr;
wl1271_boot_set_ecpu_ctrl(wl, ECPU_CONTROL_HALT);
@@ -368,15 +368,15 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
loop = 0;
while (loop++ < INIT_LOOP) {
udelay(INIT_LOOP_DELAY);
- interrupt = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
+ intr = wl1271_read32(wl, ACX_REG_INTERRUPT_NO_CLEAR);
- if (interrupt == 0xffffffff) {
+ if (intr == 0xffffffff) {
wl1271_error("error reading hardware complete "
"init indication");
return -EIO;
}
/* check that ACX_INTR_INIT_COMPLETE is enabled */
- else if (interrupt & WL1271_ACX_INTR_INIT_COMPLETE) {
+ else if (intr & WL1271_ACX_INTR_INIT_COMPLETE) {
wl1271_write32(wl, ACX_REG_INTERRUPT_ACK,
WL1271_ACX_INTR_INIT_COMPLETE);
break;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 61fb774..62c11af 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -318,7 +318,7 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
join->rx_config_options = cpu_to_le32(wl->rx_config);
join->rx_filter_options = cpu_to_le32(wl->rx_filter);
join->bss_type = bss_type;
- join->basic_rate_set = wl->basic_rate_set;
+ join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
if (wl->band == IEEE80211_BAND_5GHZ)
join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -615,7 +615,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
params->params.scan_options = cpu_to_le16(scan_options);
params->params.num_probe_requests = probe_requests;
- params->params.tx_rate = rate;
+ params->params.tx_rate = cpu_to_le32(rate);
params->params.tid_trigger = 0;
params->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index c44307c..d046d04 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -401,7 +401,7 @@ enum {
};
struct conf_sg_settings {
- __le32 params[CONF_SG_PARAMS_MAX];
+ u32 params[CONF_SG_PARAMS_MAX];
u8 state;
};
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The driver had a join command without keep-alive restart procedures in the
channel changing code. After associated scans, the mac80211 does re-set the
current channel, causing the join to occur. This would stop the hardware
keep alive.
To make the joins safer in this respect, this patch adds a join function that
does the hardware-keep-alive magic along the join. This is now invoked in the
above mentioned scenario, and also other scenarios.
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 | 91 +++++++++++++++--------------
1 files changed, 46 insertions(+), 45 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 26e8fb1..466106e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1118,14 +1118,13 @@ static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
}
}
-static int wl1271_join_channel(struct wl1271 *wl, int channel)
+static int wl1271_dummy_join(struct wl1271 *wl)
{
int ret = 0;
/* we need to use a dummy BSSID for now */
static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
0xad, 0xbe, 0xef };
- wl->channel = channel;
memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
/* pass through frames from all BSS */
@@ -1141,7 +1140,47 @@ out:
return ret;
}
-static int wl1271_unjoin_channel(struct wl1271 *wl)
+static int wl1271_join(struct wl1271 *wl)
+{
+ int ret;
+
+ ret = wl1271_cmd_join(wl, wl->set_bss_type);
+ if (ret < 0)
+ goto out;
+
+ set_bit(WL1271_FLAG_JOINED, &wl->flags);
+
+ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ goto out;
+
+ /*
+ * The join command disable the keep-alive mode, shut down its process,
+ * and also clear the template config, so we need to reset it all after
+ * the join. The acx_aid starts the keep-alive process, and the order
+ * of the commands below is relevant.
+ */
+ ret = wl1271_acx_keep_alive_mode(wl, true);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_aid(wl, wl->aid);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_cmd_build_klv_null_data(wl);
+ if (ret < 0)
+ goto out;
+
+ ret = wl1271_acx_keep_alive_config(wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
+ ACX_KEEP_ALIVE_TPL_VALID);
+ if (ret < 0)
+ goto out;
+
+out:
+ return ret;
+}
+
+static int wl1271_unjoin(struct wl1271 *wl)
{
int ret;
@@ -1231,7 +1270,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
"failed %d", ret);
if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
+ ret = wl1271_join(wl);
if (ret < 0)
wl1271_warning("cmd join to update channel "
"failed %d", ret);
@@ -1241,9 +1280,9 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
if (conf->flags & IEEE80211_CONF_IDLE &&
test_bit(WL1271_FLAG_JOINED, &wl->flags))
- wl1271_unjoin_channel(wl);
+ wl1271_unjoin(wl);
else if (!(conf->flags & IEEE80211_CONF_IDLE))
- wl1271_join_channel(wl, channel);
+ wl1271_dummy_join(wl);
if (conf->flags & IEEE80211_CONF_IDLE) {
wl->rate_set = wl1271_min_rate_get(wl);
@@ -1613,7 +1652,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
enum wl1271_cmd_ps_mode mode;
struct wl1271 *wl = hw->priv;
bool do_join = false;
- bool do_keepalive = false;
int ret;
wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
@@ -1756,19 +1794,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
ret = wl1271_cmd_build_probe_req(wl, NULL, 0,
NULL, 0, wl->band);
- /* Enable the keep-alive feature */
- ret = wl1271_acx_keep_alive_mode(wl, true);
- if (ret < 0)
- goto out_sleep;
-
- /*
- * This is awkward. The keep-alive configs must be done
- * *after* the join command, because otherwise it will
- * not work, but it must only be done *once* because
- * otherwise the firmware will start complaining.
- */
- do_keepalive = true;
-
/* enable the connection monitoring feature */
ret = wl1271_acx_conn_monit_params(wl, true);
if (ret < 0)
@@ -1836,35 +1861,11 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
}
if (do_join) {
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
+ ret = wl1271_join(wl);
if (ret < 0) {
wl1271_warning("cmd join failed %d", ret);
goto out_sleep;
}
- set_bit(WL1271_FLAG_JOINED, &wl->flags);
- }
-
- /*
- * The JOIN operation shuts down the firmware keep-alive as a side
- * effect, and the ACX_AID will start the keep-alive as a side effect.
- * Hence, for non-IBSS, the ACX_AID must always happen *after* the
- * JOIN operation, and the template config after the ACX_AID.
- */
- if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
- ret = wl1271_acx_aid(wl, wl->aid);
- if (ret < 0)
- goto out_sleep;
- }
-
- if (do_keepalive) {
- ret = wl1271_cmd_build_klv_null_data(wl);
- if (ret < 0)
- goto out_sleep;
- ret = wl1271_acx_keep_alive_config(
- wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
- ACX_KEEP_ALIVE_TPL_VALID);
- if (ret < 0)
- goto out_sleep;
}
out_sleep:
--
1.6.3.3