2010-04-01 08:38:48

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 0/8] wl1271: patches of the week

Hi John,

We have a few more patches to be applied upstream. These patches have just
been added to our internal tree, so they're as hot as we can make them at the
moment. ;)

Please apply them.

And, no, it's not an April Fool's joke that I'm sending a smaller and more
recent bunch this time! :D

Cheers,
Luca.

Juuso Oikarinen (6):
wl1271: Fix keep-alive related command error
wl1271: Use minimum rate for each band for control messages
wl1271: Configure rates for templates
wl1271: Configure a higher listen interval to AP upon association
wl1271: Fix debug prints for beacon-loss and psm-entry-fail scenarios
wl1271: Fix tx queue flushing

Luciano Coelho (2):
wl1271: fix sdio driver name in wl1271_sdio_driver
wl1271: added missing command header in wl1271_cmd_disconnect

drivers/net/wireless/wl12xx/wl1271.h | 1 +
drivers/net/wireless/wl12xx/wl1271_acx.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_cmd.c | 48 ++++++------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 6 +-
drivers/net/wireless/wl12xx/wl1271_conf.h | 20 +++++
drivers/net/wireless/wl12xx/wl1271_event.c | 4 +-
drivers/net/wireless/wl12xx/wl1271_init.c | 18 +++--
drivers/net/wireless/wl12xx/wl1271_main.c | 122 +++++++++++++++++++++++-----
drivers/net/wireless/wl12xx/wl1271_sdio.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_tx.c | 20 +----
drivers/net/wireless/wl12xx/wl1271_tx.h | 1 +
11 files changed, 167 insertions(+), 77 deletions(-)



2010-04-01 08:38:50

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 2/8] wl1271: added missing command header in wl1271_cmd_disconnect

The command header was missing in the wl1271_cmd_disconnect structure. It
was working fine by sheer luck, because the parameters are not critical and
because our wl1271_cmd_send() function was overwriting the rx_config_options
with the actual header.

This patch adds the header to the command structure.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index e1131bc..d61f339 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -518,6 +518,8 @@ enum wl1271_disconnect_type {
};

struct wl1271_cmd_disconnect {
+ struct wl1271_cmd_header header;
+
__le32 rx_config_options;
__le32 rx_filter_options;

--
1.6.3.3


2010-04-01 08:39:03

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 8/8] wl1271: Fix tx queue flushing

From: Juuso Oikarinen <[email protected]>

This patch modifies tx-queue flushing to correspond with tx-path - i.e.
also frames for which no ack was requested are forwarded to the mac80211
for disposal.

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 | 18 +-----------------
1 files changed, 1 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 0b8cdb4..62db795 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -416,35 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl)
{
int i;
struct sk_buff *skb;
- struct ieee80211_tx_info *info;

/* TX failure */
/* control->flags = 0; FIXME */

while ((skb = skb_dequeue(&wl->tx_queue))) {
- info = IEEE80211_SKB_CB(skb);
-
wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
-
- if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
- kfree_skb(skb);
- continue;
- }
-
ieee80211_tx_status(wl->hw, skb);
}

for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
if (wl->tx_frames[i] != NULL) {
skb = wl->tx_frames[i];
- info = IEEE80211_SKB_CB(skb);
-
- if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)) {
- kfree_skb(skb);
- continue;
- }
-
- ieee80211_tx_status(wl->hw, skb);
wl->tx_frames[i] = NULL;
+ ieee80211_tx_status(wl->hw, skb);
}
}
--
1.6.3.3


2010-04-01 08:38:50

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 3/8] wl1271: Fix keep-alive related command error

From: Juuso Oikarinen <[email protected]>

The firmware does not like the host configuring the keep-alive after it has
been once configured after a join-operation. Instead, it will complain about
invalid parameters, which do not break functionality, but do not look nice
in the syslog either.

This patch prevents the complaints by only configuring the keep-alive once
for an association, after the first time join is performed with the correct
bssid.

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 | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 033cef0..2494c96 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1569,6 +1569,7 @@ 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");
@@ -1685,6 +1686,14 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
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)
@@ -1763,6 +1772,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
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;
--
1.6.3.3


2010-04-01 08:39:12

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 4/8] wl1271: Use minimum rate for each band for control messages

From: Juuso Oikarinen <[email protected]>

Currently the mac80211 is not telling a hardware rate controlled driver a
rate to use for association frames etc. So to be safe, use the lowest rate
of each band for communication.

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_acx.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_cmd.c | 27 +++-----
drivers/net/wireless/wl12xx/wl1271_conf.h | 13 ++++
drivers/net/wireless/wl12xx/wl1271_main.c | 98 +++++++++++++++++++++++-----
drivers/net/wireless/wl12xx/wl1271_tx.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_tx.h | 1 +
7 files changed, 108 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index c5559ef..a29969e 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -447,6 +447,7 @@ struct wl1271 {
/* currently configured rate set */
u32 sta_rate_set;
u32 basic_rate_set;
+ u32 basic_rate;
u32 rate_set;

/* The current band */
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 8f0bd5b..621c946 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -802,7 +802,7 @@ int wl1271_acx_rate_policies(struct wl1271 *wl)

/* configure one basic rate class */
idx = ACX_TX_BASIC_RATE;
- acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate_set);
+ acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
acx->rate_class[idx].aflags = c->aflags;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index f11f9f4..5cee59f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -317,18 +317,10 @@ 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;

- if (wl->band == IEEE80211_BAND_2GHZ)
- join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS |
- CONF_HW_BIT_RATE_2MBPS |
- CONF_HW_BIT_RATE_5_5MBPS |
- CONF_HW_BIT_RATE_11MBPS);
- else {
+ if (wl->band == IEEE80211_BAND_5GHZ)
join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
- join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_6MBPS |
- CONF_HW_BIT_RATE_12MBPS |
- CONF_HW_BIT_RATE_24MBPS);
- }

join->beacon_interval = cpu_to_le16(wl->beacon_int);
join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
@@ -581,17 +573,21 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
struct wl1271_cmd_trigger_scan_to *trigger = NULL;
struct wl1271_cmd_scan *params = NULL;
struct ieee80211_channel *channels;
+ u32 rate;
int i, j, n_ch, ret;
u16 scan_options = 0;
u8 ieee_band;

- if (band == WL1271_SCAN_BAND_2_4_GHZ)
+ if (band == WL1271_SCAN_BAND_2_4_GHZ) {
ieee_band = IEEE80211_BAND_2GHZ;
- else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled())
+ rate = wl->conf.tx.basic_rate;
+ } else if (band == WL1271_SCAN_BAND_DUAL && wl1271_11a_enabled()) {
ieee_band = IEEE80211_BAND_2GHZ;
- else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled())
+ rate = wl->conf.tx.basic_rate;
+ } else if (band == WL1271_SCAN_BAND_5_GHZ && wl1271_11a_enabled()) {
ieee_band = IEEE80211_BAND_5GHZ;
- else
+ rate = wl->conf.tx.basic_rate_5;
+ } else
return -EINVAL;

if (wl->hw->wiphy->bands[ieee_band]->channels == NULL)
@@ -618,8 +614,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;
- /* Let the fw autodetect suitable tx_rate for probes */
- params->params.tx_rate = 0;
+ params->params.tx_rate = 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 82b5dab..0b34b62 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -674,6 +674,19 @@ struct conf_tx_settings {
*/
u16 tx_compl_threshold;

+ /*
+ * The rate used for control messages and scanning on the 2.4GHz band
+ *
+ * Range: CONF_HW_BIT_RATE_* bit mask
+ */
+ u32 basic_rate;
+
+ /*
+ * The rate used for control messages and scanning on the 5GHz band
+ *
+ * Range: CONF_HW_BIT_RATE_* bit mask
+ */
+ u32 basic_rate_5;
};

enum {
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 2494c96..ca5cd32 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -116,8 +116,7 @@ static struct conf_drv_settings default_conf = {
.tx = {
.tx_energy_detection = 0,
.rc_conf = {
- .enabled_rates = CONF_HW_BIT_RATE_1MBPS |
- CONF_HW_BIT_RATE_2MBPS,
+ .enabled_rates = 0,
.short_retry_limit = 10,
.long_retry_limit = 10,
.aflags = 0
@@ -214,7 +213,9 @@ static struct conf_drv_settings default_conf = {
},
.frag_threshold = IEEE80211_MAX_FRAG_THRESHOLD,
.tx_compl_timeout = 700,
- .tx_compl_threshold = 4
+ .tx_compl_threshold = 4,
+ .basic_rate = CONF_HW_BIT_RATE_1MBPS,
+ .basic_rate_5 = CONF_HW_BIT_RATE_6MBPS,
},
.conn = {
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
@@ -1171,6 +1172,32 @@ out:
return ret;
}

+static void wl1271_set_band_rate(struct wl1271 *wl)
+{
+ if (wl->band == IEEE80211_BAND_2GHZ)
+ wl->basic_rate_set = wl->conf.tx.basic_rate;
+ else
+ wl->basic_rate_set = wl->conf.tx.basic_rate_5;
+}
+
+static u32 wl1271_min_rate_get(struct wl1271 *wl)
+{
+ int i;
+ u32 rate = 0;
+
+ if (!wl->basic_rate_set) {
+ WARN_ON(1);
+ wl->basic_rate_set = wl->conf.tx.basic_rate;
+ }
+
+ for (i = 0; !rate; i++) {
+ if ((wl->basic_rate_set >> i) & 0x1)
+ rate = 1 << i;
+ }
+
+ return rate;
+}
+
static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
{
struct wl1271 *wl = hw->priv;
@@ -1187,12 +1214,38 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)

mutex_lock(&wl->mutex);

- wl->band = conf->channel->band;
-
ret = wl1271_ps_elp_wakeup(wl, false);
if (ret < 0)
goto out;

+ /* if the channel changes while joined, join again */
+ if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
+ wl->band = conf->channel->band;
+ wl->channel = channel;
+
+ /*
+ * FIXME: the mac80211 should really provide a fixed rate
+ * to use here. for now, just use the smallest possible rate
+ * for the band as a fixed rate for association frames and
+ * other control messages.
+ */
+ if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+ wl1271_set_band_rate(wl);
+
+ wl->basic_rate = wl1271_min_rate_get(wl);
+ ret = wl1271_acx_rate_policies(wl);
+ if (ret < 0)
+ wl1271_warning("rate policy for update channel "
+ "failed %d", ret);
+
+ if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+ ret = wl1271_cmd_join(wl, wl->set_bss_type);
+ if (ret < 0)
+ wl1271_warning("cmd join to update channel "
+ "failed %d", ret);
+ }
+ }
+
if (changed & IEEE80211_CONF_CHANGE_IDLE) {
if (conf->flags & IEEE80211_CONF_IDLE &&
test_bit(WL1271_FLAG_JOINED, &wl->flags))
@@ -1201,7 +1254,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
wl1271_join_channel(wl, channel);

if (conf->flags & IEEE80211_CONF_IDLE) {
- wl->rate_set = CONF_TX_RATE_MASK_BASIC;
+ wl->rate_set = wl1271_min_rate_get(wl);
wl->sta_rate_set = 0;
wl1271_acx_rate_policies(wl);
wl1271_acx_keep_alive_config(
@@ -1210,18 +1263,6 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
}
}

- /* if the channel changes while joined, join again */
- if (channel != wl->channel &&
- test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
- wl->channel = channel;
- /* FIXME: maybe use CMD_CHANNEL_SWITCH for this? */
- ret = wl1271_cmd_join(wl, wl->set_bss_type);
- if (ret < 0)
- wl1271_warning("cmd join to update channel failed %d",
- ret);
- } else
- wl->channel = channel;
-
if (conf->flags & IEEE80211_CONF_PS &&
!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags)) {
set_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags);
@@ -1659,10 +1700,23 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,

if (changed & BSS_CHANGED_ASSOC) {
if (bss_conf->assoc) {
+ u32 rates;
wl->aid = bss_conf->aid;
set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);

/*
+ * use basic rates from AP, and determine lowest rate
+ * to use with control frames.
+ */
+ rates = bss_conf->basic_rates;
+ wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
+ rates);
+ wl->basic_rate = wl1271_min_rate_get(wl);
+ ret = wl1271_acx_rate_policies(wl);
+ if (ret < 0)
+ goto out_sleep;
+
+ /*
* with wl1271, we don't need to update the
* beacon_int and dtim_period, because the firmware
* updates it by itself when the first beacon is
@@ -1712,6 +1766,13 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
clear_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
wl->aid = 0;

+ /* revert back to minimum rates for the current band */
+ wl1271_set_band_rate(wl);
+ wl->basic_rate = wl1271_min_rate_get(wl);
+ ret = wl1271_acx_rate_policies(wl);
+ if (ret < 0)
+ goto out_sleep;
+
/* disable connection monitor features */
ret = wl1271_acx_conn_monit_params(wl, false);

@@ -2261,6 +2322,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->psm_entry_retry = 0;
wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
+ wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->sta_rate_set = 0;
wl->band = IEEE80211_BAND_2GHZ;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 66b48b7..0b8cdb4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -220,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
return ret;
}

-static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
+u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
{
struct ieee80211_supported_band *band;
u32 enabled_rates = 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index b03c95d..3b8b7ac 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -160,5 +160,6 @@ void wl1271_tx_work(struct work_struct *work);
void wl1271_tx_complete(struct wl1271 *wl);
void wl1271_tx_flush(struct wl1271 *wl);
u8 wl1271_rate_to_idx(struct wl1271 *wl, int rate);
+u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);

#endif
--
1.6.3.3


2010-04-01 08:39:00

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 5/8] wl1271: Configure rates for templates

From: Juuso Oikarinen <[email protected]>

Configure meaningful rates to be used with the templates. For control frames,
use the determined basic rates (currently the lowest rate for the band) and
for data-frames (null-funcs) let the firmware use the current rate policy to
determine the rate.

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 | 21 +++++++++++++--------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 4 +++-
drivers/net/wireless/wl12xx/wl1271_init.c | 18 ++++++++++--------
drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++--
4 files changed, 30 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 5cee59f..b190903 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -700,7 +700,7 @@ out:
}

int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
- void *buf, size_t buf_len, int index)
+ void *buf, size_t buf_len, int index, u32 rates)
{
struct wl1271_cmd_template_set *cmd;
int ret = 0;
@@ -718,7 +718,7 @@ int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,

cmd->len = cpu_to_le16(buf_len);
cmd->template_type = template_id;
- cmd->enabled_rates = cpu_to_le32(wl->conf.tx.rc_conf.enabled_rates);
+ cmd->enabled_rates = cpu_to_le32(rates);
cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit;
cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit;
cmd->index = index;
@@ -758,7 +758,8 @@ int wl1271_cmd_build_null_data(struct wl1271 *wl)
ptr = skb->data;
}

- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0);
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size, 0,
+ WL1271_RATE_AUTOMATIC);

out:
dev_kfree_skb(skb);
@@ -780,7 +781,8 @@ 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);
+ CMD_TEMPL_KLV_IDX_NULL_DATA,
+ WL1271_RATE_AUTOMATIC);

out:
dev_kfree_skb(skb);
@@ -801,7 +803,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
goto out;

ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data,
- skb->len, 0);
+ skb->len, 0, wl->basic_rate);

out:
dev_kfree_skb(skb);
@@ -826,10 +828,12 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,

if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
- skb->data, skb->len, 0);
+ skb->data, skb->len, 0,
+ wl->conf.tx.basic_rate);
else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- skb->data, skb->len, 0);
+ skb->data, skb->len, 0,
+ wl->conf.tx.basic_rate_5);

out:
dev_kfree_skb(skb);
@@ -854,7 +858,8 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
template.qos_ctrl = cpu_to_le16(0);

return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
- sizeof(template), 0);
+ sizeof(template), 0,
+ WL1271_RATE_AUTOMATIC);
}

int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index d61f339..00f78b7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -45,7 +45,7 @@ int wl1271_cmd_scan(struct wl1271 *wl, const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 active_scan,
u8 high_prio, u8 band, u8 probe_requests);
int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
- void *buf, size_t buf_len, int index);
+ void *buf, size_t buf_len, int index, u32 rates);
int wl1271_cmd_build_null_data(struct wl1271 *wl);
int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
int wl1271_cmd_build_probe_req(struct wl1271 *wl,
@@ -252,6 +252,8 @@ struct cmd_enabledisable_path {
u8 padding[3];
} __attribute__ ((packed));

+#define WL1271_RATE_AUTOMATIC 0
+
struct wl1271_cmd_template_set {
struct wl1271_cmd_header header;

diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 8ec94ac..9ab3368 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -56,54 +56,56 @@ int wl1271_init_templates_config(struct wl1271 *wl)
/* send empty templates for fw memory reservation */
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
sizeof(struct wl12xx_probe_req_template),
- 0);
+ 0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;

if (wl1271_11a_enabled()) {
size_t size = sizeof(struct wl12xx_probe_req_template);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- NULL, size, 0);
+ 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),
- 0);
+ 0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;

ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, NULL,
sizeof(struct wl12xx_ps_poll_template),
- 0);
+ 0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;

ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
sizeof
(struct wl12xx_qos_null_data_template),
- 0);
+ 0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;

ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
sizeof
(struct wl12xx_probe_resp_template),
- 0);
+ 0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;

ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
sizeof
(struct wl12xx_beacon_template),
- 0);
+ 0, WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;

for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
- WL1271_CMD_TEMPL_MAX_SIZE, i);
+ WL1271_CMD_TEMPL_MAX_SIZE, i,
+ WL1271_RATE_AUTOMATIC);
if (ret < 0)
return ret;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index ca5cd32..247f407 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1642,7 +1642,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
wl1271_ssid_set(wl, beacon);
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
beacon->data,
- beacon->len, 0);
+ beacon->len, 0,
+ wl1271_min_rate_get(wl));

if (ret < 0) {
dev_kfree_skb(beacon);
@@ -1657,7 +1658,8 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
ret = wl1271_cmd_template_set(wl,
CMD_TEMPL_PROBE_RESPONSE,
beacon->data,
- beacon->len, 0);
+ beacon->len, 0,
+ wl1271_min_rate_get(wl));
dev_kfree_skb(beacon);
if (ret < 0)
goto out_sleep;
--
1.6.3.3


2010-04-01 08:38:54

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 7/8] wl1271: Fix debug prints for beacon-loss and psm-entry-fail scenarios

From: Juuso Oikarinen <[email protected]>

Remove ERROR print from psm-entry-fail scenario, instead use an INFO print.
Also, add INFO print to the beacon-loss scenario.

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 | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 4fc212a..daacf17 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -81,7 +81,7 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE,
true);
} else {
- wl1271_error("PSM entry failed, giving up.\n");
+ wl1271_info("No ack to nullfunc from AP.");
wl->psm_entry_retry = 0;
*beacon_loss = true;
}
@@ -160,7 +160,7 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
*
*/
if (vector & BSS_LOSE_EVENT_ID) {
- wl1271_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
+ wl1271_info("Beacon loss detected.");

/* indicate to the stack, that beacons have been lost */
beacon_loss = true;
--
1.6.3.3


2010-04-01 08:39:04

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 6/8] wl1271: Configure a higher listen interval to AP upon association

From: Juuso Oikarinen <[email protected]>

Increase the fixed listen-interval max value configured to the mac80211 on
driver init. This value will allow a larger value to be configured to the
AP, which means the AP will buffer our frames longer.

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 | 7 +++++++
drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++++--
2 files changed, 11 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 0b34b62..d76ae03 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -977,6 +977,13 @@ struct conf_conn_settings {
* Range: 1000 - 3600000
*/
u32 keep_alive_interval;
+
+ /*
+ * Maximum listen interval supported by the driver in units of beacons.
+ *
+ * Range: u16
+ */
+ u8 max_listen_interval;
};

enum {
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 247f407..5c32d8d 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -219,7 +219,7 @@ static struct conf_drv_settings default_conf = {
},
.conn = {
.wake_up_event = CONF_WAKE_UP_EVENT_DTIM,
- .listen_interval = 0,
+ .listen_interval = 1,
.bcn_filt_mode = CONF_BCN_FILT_MODE_ENABLED,
.bcn_filt_ie_count = 1,
.bcn_filt_ie = {
@@ -266,7 +266,8 @@ static struct conf_drv_settings default_conf = {
.bet_enable = CONF_BET_MODE_ENABLE,
.bet_max_consecutive = 10,
.psm_entry_retries = 3,
- .keep_alive_interval = 55000
+ .keep_alive_interval = 55000,
+ .max_listen_interval = 20,
},
.init = {
.radioparam = {
@@ -2253,6 +2254,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
/* unit us */
/* FIXME: find a proper value */
wl->hw->channel_change_time = 10000;
+ wl->hw->max_listen_interval = wl->conf.conn.max_listen_interval;

wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_NOISE_DBM |
--
1.6.3.3


2010-04-01 08:38:43

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH 1/8] wl1271: fix sdio driver name in wl1271_sdio_driver

Our SPI driver is called "wl1271_spi" in the driver information structure.
Let's use the same for SDIO so that things are aligned.

Signed-off-by: Luciano Coelho <[email protected]>
Reviewed-by: Teemu Paasikivi <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index abfe75b..d3d6f30 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -255,7 +255,7 @@ static void __devexit wl1271_remove(struct sdio_func *func)
}

static struct sdio_driver wl1271_sdio_driver = {
- .name = "wl1271",
+ .name = "wl1271_sdio",
.id_table = wl1271_devices,
.probe = wl1271_probe,
.remove = __devexit_p(wl1271_remove),
--
1.6.3.3