2012-11-26 16:05:56

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 00/11] wlcore fixes for 3.8 (part1)

Various fixes for wlcore, to be applied on top of
Eliad's 18xx API update series.

There are more patches pending - the splitting into smaller
series is meant to ease review.

Arik Nemtsov (2):
wlcore: use new set bandwidth command to adjusting channel BW
wlcore/wl18xx/wl12xx: separate channel count between chips

Eliad Peller (7):
wlcore: configure dwell times according to scan type
wlcore: don't stop fwlog if dbgpins are used
wlcore/wl18xx: allow TX BA on all TIDs
wlcore: use sta_state-based ROCs for AP mode
wlcore: mask out CCK rates when starting GO
wlcore: move ps change handling to .bss_info_changed()
wlcore: don't allow access to FW mem when chip is off

Luciano Coelho (1):
wlcore: gather information about firmware stability

Yair Shapira (1):
wlcore/wl18xx/wl12xx: add recovery settings to conf

drivers/net/wireless/ti/wl12xx/main.c | 11 +-
drivers/net/wireless/ti/wl12xx/scan.c | 7 +-
drivers/net/wireless/ti/wl18xx/acx.c | 31 ++++++
drivers/net/wireless/ti/wl18xx/acx.h | 14 +++
drivers/net/wireless/ti/wl18xx/main.c | 49 ++++++++-
drivers/net/wireless/ti/wl18xx/scan.c | 6 +-
drivers/net/wireless/ti/wl18xx/scan.h | 7 --
drivers/net/wireless/ti/wlcore/cmd.c | 3 +
drivers/net/wireless/ti/wlcore/conf.h | 30 +++---
drivers/net/wireless/ti/wlcore/debugfs.c | 5 +-
drivers/net/wireless/ti/wlcore/hw_ops.h | 8 ++
drivers/net/wireless/ti/wlcore/main.c | 162 ++++++++++++++++++++---------
drivers/net/wireless/ti/wlcore/scan.c | 57 ++++++----
drivers/net/wireless/ti/wlcore/scan.h | 9 +-
drivers/net/wireless/ti/wlcore/wlcore.h | 7 ++
drivers/net/wireless/ti/wlcore/wlcore_i.h | 6 ++
16 files changed, 308 insertions(+), 104 deletions(-)

--
1.7.9.5



2012-11-26 16:06:12

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 08/11] wlcore: move ps change handling to .bss_info_changed()

From: Eliad Peller <[email protected]>

Adapt the new mac80211 BSS_CHANGED_PS notification,
and do the ps handling in mac80211's per-vif
callback (.bss_info_changed), rather than in
the per-device (.config) callback.

Make sure to configure it only after association.

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 70 +++++++++++++++------------------
1 file changed, 32 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 45008fa..a6283df 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2781,46 +2781,8 @@ static void wl1271_set_band_rate(struct wl1271 *wl, struct wl12xx_vif *wlvif)
static int wl12xx_config_vif(struct wl1271 *wl, struct wl12xx_vif *wlvif,
struct ieee80211_conf *conf, u32 changed)
{
- bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
int ret;

- if ((changed & IEEE80211_CONF_CHANGE_PS) && !is_ap) {
-
- if ((conf->flags & IEEE80211_CONF_PS) &&
- test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
- !test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) {
-
- int ps_mode;
- char *ps_mode_str;
-
- if (wl->conf.conn.forced_ps) {
- ps_mode = STATION_POWER_SAVE_MODE;
- ps_mode_str = "forced";
- } else {
- ps_mode = STATION_AUTO_PS_MODE;
- ps_mode_str = "auto";
- }
-
- wl1271_debug(DEBUG_PSM, "%s ps enabled", ps_mode_str);
-
- ret = wl1271_ps_set_mode(wl, wlvif, ps_mode);
-
- if (ret < 0)
- wl1271_warning("enter %s ps failed %d",
- ps_mode_str, ret);
-
- } else if (!(conf->flags & IEEE80211_CONF_PS) &&
- test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) {
-
- wl1271_debug(DEBUG_PSM, "auto ps disabled");
-
- ret = wl1271_ps_set_mode(wl, wlvif,
- STATION_ACTIVE_MODE);
- if (ret < 0)
- wl1271_warning("exit auto ps failed %d", ret);
- }
- }
-
if (conf->power_level != wlvif->power_level) {
ret = wl1271_acx_tx_power(wl, wlvif, conf->power_level);
if (ret < 0)
@@ -4115,6 +4077,38 @@ sta_not_found:
}
}

+ if (changed & BSS_CHANGED_PS) {
+ if ((bss_conf->ps) &&
+ test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags) &&
+ !test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) {
+ int ps_mode;
+ char *ps_mode_str;
+
+ if (wl->conf.conn.forced_ps) {
+ ps_mode = STATION_POWER_SAVE_MODE;
+ ps_mode_str = "forced";
+ } else {
+ ps_mode = STATION_AUTO_PS_MODE;
+ ps_mode_str = "auto";
+ }
+
+ wl1271_debug(DEBUG_PSM, "%s ps enabled", ps_mode_str);
+
+ ret = wl1271_ps_set_mode(wl, wlvif, ps_mode);
+ if (ret < 0)
+ wl1271_warning("enter %s ps failed %d",
+ ps_mode_str, ret);
+ } else if (!bss_conf->ps &&
+ test_bit(WLVIF_FLAG_IN_PS, &wlvif->flags)) {
+ wl1271_debug(DEBUG_PSM, "auto ps disabled");
+
+ ret = wl1271_ps_set_mode(wl, wlvif,
+ STATION_ACTIVE_MODE);
+ if (ret < 0)
+ wl1271_warning("exit auto ps failed %d", ret);
+ }
+ }
+
/* Handle new association with HT. Do this after join. */
if (sta_exists &&
(changed & BSS_CHANGED_HT)) {
--
1.7.9.5


2012-11-26 16:06:20

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 11/11] wlcore/wl18xx/wl12xx: add recovery settings to conf

From: Yair Shapira <[email protected]>

add support for recovery settings including bug_on_recovery and
no_recovery options.

These options can now be set using wl18xx-conf.bin file and wlconf
tool.

Signed-off-by: Yair Shapira <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 4 ++++
drivers/net/wireless/ti/wl18xx/main.c | 4 ++++
drivers/net/wireless/ti/wlcore/conf.h | 11 ++++++++++-
drivers/net/wireless/ti/wlcore/main.c | 21 +++++++++++++++------
4 files changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index dafcdf6..d997cdc 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -370,6 +370,10 @@ static struct wlcore_conf wl12xx_conf = {
.increase_time = 1,
.window_size = 16,
},
+ .recovery = {
+ .bug_on_recovery = 0,
+ .no_recovery = 0,
+ },
};

static struct wl12xx_priv_conf wl12xx_default_priv_conf = {
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 9d2fa91..e71e2cf 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -492,6 +492,10 @@ static struct wlcore_conf wl18xx_conf = {
.increase_time = 1,
.window_size = 16,
},
+ .recovery = {
+ .bug_on_recovery = 0,
+ .no_recovery = 0,
+ },
};

static struct wl18xx_priv_conf wl18xx_default_priv_conf = {
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index e0695e9..b64d6b5 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -1265,12 +1265,20 @@ struct conf_hangover_settings {
u8 window_size;
} __packed;

+struct conf_recovery_settings {
+ /* BUG() on fw recovery */
+ u8 bug_on_recovery;
+
+ /* Prevent HW recovery. FW will remain stuck. */
+ u8 no_recovery;
+} __packed;
+
/*
* The conf version consists of 4 bytes. The two MSB are the wlcore
* version, the two LSB are the lower driver's private conf
* version.
*/
-#define WLCORE_CONF_VERSION (0x0003 << 16)
+#define WLCORE_CONF_VERSION (0x0004 << 16)
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
sizeof(struct wlcore_conf))
@@ -1298,6 +1306,7 @@ struct wlcore_conf {
struct conf_fwlog fwlog;
struct conf_rate_policy_settings rate;
struct conf_hangover_settings hangover;
+ struct conf_recovery_settings recovery;
} __packed;

struct wlcore_conf_file {
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index a48a36c..56f20d6 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -56,8 +56,8 @@
#define WL1271_BOOT_RETRIES 3

static char *fwlog_param;
-static bool bug_on_recovery;
-static bool no_recovery;
+static int bug_on_recovery = -1;
+static int no_recovery = -1;

static void __wl1271_op_remove_interface(struct wl1271 *wl,
struct ieee80211_vif *vif,
@@ -306,6 +306,8 @@ out:
static void wlcore_adjust_conf(struct wl1271 *wl)
{
/* Adjust settings according to optional module parameters */
+
+ /* Firmware Log Settings */
if (fwlog_param) {
if (!strcmp(fwlog_param, "continuous")) {
wl->conf.fwlog.mode = WL12XX_FWLOG_CONTINUOUS;
@@ -321,6 +323,13 @@ static void wlcore_adjust_conf(struct wl1271 *wl)
wl1271_error("Unknown fwlog parameter %s", fwlog_param);
}
}
+
+ /* Recovery Settings */
+ if (bug_on_recovery != -1)
+ wl->conf.recovery.bug_on_recovery = (u8) bug_on_recovery;
+
+ if (no_recovery != -1)
+ wl->conf.recovery.no_recovery = (u8) no_recovery;
}

static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl,
@@ -903,10 +912,10 @@ static void wl1271_recovery_work(struct work_struct *work)
wlcore_print_recovery(wl);
}

- BUG_ON(bug_on_recovery &&
+ BUG_ON(wl->conf.recovery.bug_on_recovery &&
!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags));

- if (no_recovery) {
+ if (wl->conf.recovery.no_recovery) {
wl1271_info("No recovery (chosen on module load). Fw will remain stuck.");
goto out_unlock;
}
@@ -6013,10 +6022,10 @@ module_param_named(fwlog, fwlog_param, charp, 0);
MODULE_PARM_DESC(fwlog,
"FW logger options: continuous, ondemand, dbgpins or disable");

-module_param(bug_on_recovery, bool, S_IRUSR | S_IWUSR);
+module_param(bug_on_recovery, int, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(bug_on_recovery, "BUG() on fw recovery");

-module_param(no_recovery, bool, S_IRUSR | S_IWUSR);
+module_param(no_recovery, int, S_IRUSR | S_IWUSR);
MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck.");

MODULE_LICENSE("GPL");
--
1.7.9.5


2012-11-27 08:55:33

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 01/11] wlcore: configure dwell times according to scan type

On Mon, 2012-11-26 at 18:05 +0200, Arik Nemtsov wrote:
> From: Eliad Peller <[email protected]>
>
> Allow configuring different dwell times to the different
> scan types (regular and scheduled).
>
> Add new configuration entry (dwell_time_dfs) to
> conf_scan_settings, in order to allow setting
> different values for normal scan and scheduled scan.
>
> Signed-off-by: Eliad Peller <[email protected]>
> Signed-off-by: Arik Nemtsov <[email protected]>
> ---

This patch changes the semantics of two values in the middle of the conf
struct, so WLCORE_CONF_VERSION should be increased. Also, the wlconf
tool should be updated.

--
Luca.


2012-11-26 16:05:58

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 01/11] wlcore: configure dwell times according to scan type

From: Eliad Peller <[email protected]>

Allow configuring different dwell times to the different
scan types (regular and scheduled).

Add new configuration entry (dwell_time_dfs) to
conf_scan_settings, in order to allow setting
different values for normal scan and scheduled scan.

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 4 +--
drivers/net/wireless/ti/wl12xx/scan.c | 7 ++--
drivers/net/wireless/ti/wl18xx/main.c | 4 +--
drivers/net/wireless/ti/wl18xx/scan.c | 6 ++--
drivers/net/wireless/ti/wl18xx/scan.h | 7 ----
drivers/net/wireless/ti/wlcore/conf.h | 18 +++--------
drivers/net/wireless/ti/wlcore/scan.c | 57 ++++++++++++++++++++++-----------
drivers/net/wireless/ti/wlcore/scan.h | 9 +++++-
8 files changed, 64 insertions(+), 48 deletions(-)

diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 7138fe4..17ee0fd 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -267,8 +267,8 @@ static struct wlcore_conf wl12xx_conf = {
.scan = {
.min_dwell_time_active = 7500,
.max_dwell_time_active = 30000,
- .min_dwell_time_passive = 100000,
- .max_dwell_time_passive = 100000,
+ .dwell_time_passive = 100000,
+ .dwell_time_dfs = 150000,
.num_probe_reqs = 2,
.split_scan_timeout = 50000,
},
diff --git a/drivers/net/wireless/ti/wl12xx/scan.c b/drivers/net/wireless/ti/wl12xx/scan.c
index a99e876..affdb3e 100644
--- a/drivers/net/wireless/ti/wl12xx/scan.c
+++ b/drivers/net/wireless/ti/wl12xx/scan.c
@@ -68,9 +68,9 @@ static int wl1271_get_scan_channels(struct wl1271 *wl,
cpu_to_le32(c->max_dwell_time_active);
} else {
channels[j].min_duration =
- cpu_to_le32(c->min_dwell_time_passive);
+ cpu_to_le32(c->dwell_time_passive);
channels[j].max_duration =
- cpu_to_le32(c->max_dwell_time_passive);
+ cpu_to_le32(c->dwell_time_passive);
}
channels[j].early_termination = 0;
channels[j].tx_power_att = req->channels[i]->max_power;
@@ -364,7 +364,8 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl,
}

if (!wlcore_set_scan_chan_params(wl, cfg_channels, req->channels,
- req->n_channels, req->n_ssids)) {
+ req->n_channels, req->n_ssids,
+ SCAN_TYPE_PERIODIC)) {
wl1271_error("scan channel list is empty");
ret = -EINVAL;
goto out;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index bb67d70..c015231 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -394,8 +394,8 @@ static struct wlcore_conf wl18xx_conf = {
.scan = {
.min_dwell_time_active = 7500,
.max_dwell_time_active = 30000,
- .min_dwell_time_passive = 100000,
- .max_dwell_time_passive = 100000,
+ .dwell_time_passive = 100000,
+ .dwell_time_dfs = 150000,
.num_probe_reqs = 2,
.split_scan_timeout = 50000,
},
diff --git a/drivers/net/wireless/ti/wl18xx/scan.c b/drivers/net/wireless/ti/wl18xx/scan.c
index f31d0d4..daaebad 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.c
+++ b/drivers/net/wireless/ti/wl18xx/scan.c
@@ -84,7 +84,8 @@ static int wl18xx_scan_send(struct wl1271 *wl, struct wl12xx_vif *wlvif,
}

wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
- req->n_channels, req->n_ssids);
+ req->n_channels, req->n_ssids,
+ SCAN_TYPE_SEARCH);
wl18xx_adjust_channels(cmd, cmd_channels);

/*
@@ -214,7 +215,8 @@ int wl18xx_scan_sched_scan_config(struct wl1271 *wl,

/* configure channels */
wlcore_set_scan_chan_params(wl, cmd_channels, req->channels,
- req->n_channels, req->n_ssids);
+ req->n_channels, req->n_ssids,
+ SCAN_TYPE_PERIODIC);
wl18xx_adjust_channels(cmd, cmd_channels);

cmd->short_cycles_sec = 0;
diff --git a/drivers/net/wireless/ti/wl18xx/scan.h b/drivers/net/wireless/ti/wl18xx/scan.h
index 0e026ec..5eb8c7f 100644
--- a/drivers/net/wireless/ti/wl18xx/scan.h
+++ b/drivers/net/wireless/ti/wl18xx/scan.h
@@ -35,13 +35,6 @@ struct tracking_ch_params {
u8 padding[2];
} __packed;

-enum
-{
- SCAN_TYPE_SEARCH = 0,
- SCAN_TYPE_PERIODIC = 1,
- SCAN_TYPE_TRACKING = 2,
-};
-
/* probe request rate */
enum
{
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index a5d1908..c9de4d5 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -1059,19 +1059,11 @@ struct conf_scan_settings {
*/
u32 max_dwell_time_active;

- /*
- * The minimum time to wait on each channel for passive scans
- *
- * Range: u32 tu/1000
- */
- u32 min_dwell_time_passive;
+ /* time to wait on the channel for passive scans (in TU/1000) */
+ u32 dwell_time_passive;

- /*
- * The maximum time to wait on each channel for passive scans
- *
- * Range: u32 tu/1000
- */
- u32 max_dwell_time_passive;
+ /* time to wait on the channel for DFS scans (in TU/1000) */
+ u32 dwell_time_dfs;

/*
* Number of probe requests to transmit on each active scan channel
@@ -1281,7 +1273,7 @@ struct conf_hangover_settings {
* version, the two LSB are the lower driver's private conf
* version.
*/
-#define WLCORE_CONF_VERSION (0x0002 << 16)
+#define WLCORE_CONF_VERSION (0x0003 << 16)
#define WLCORE_CONF_MASK 0xffff0000
#define WLCORE_CONF_SIZE (sizeof(struct wlcore_conf_header) + \
sizeof(struct wlcore_conf))
diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c
index c913700..7f42f8a 100644
--- a/drivers/net/wireless/ti/wlcore/scan.c
+++ b/drivers/net/wireless/ti/wlcore/scan.c
@@ -97,29 +97,44 @@ wlcore_scan_get_channels(struct wl1271 *wl,
struct conn_scan_ch_params *channels,
u32 band, bool radar, bool passive,
int start, int max_channels,
- u8 *n_pactive_ch)
+ u8 *n_pactive_ch,
+ int scan_type)
{
- struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
int i, j;
u32 flags;
bool force_passive = !n_ssids;
- u32 min_dwell_time_active, max_dwell_time_active, delta_per_probe;
+ u32 min_dwell_time_active, max_dwell_time_active;
u32 dwell_time_passive, dwell_time_dfs;

- if (band == IEEE80211_BAND_5GHZ)
- delta_per_probe = c->dwell_time_delta_per_probe_5;
- else
- delta_per_probe = c->dwell_time_delta_per_probe;
+ /* configure dwell times according to scan type */
+ if (scan_type == SCAN_TYPE_SEARCH) {
+ struct conf_scan_settings *c = &wl->conf.scan;

- min_dwell_time_active = c->base_dwell_time +
- n_ssids * c->num_probe_reqs * delta_per_probe;
+ min_dwell_time_active = c->min_dwell_time_active;
+ max_dwell_time_active = c->max_dwell_time_active;
+ dwell_time_passive = c->dwell_time_passive;
+ dwell_time_dfs = c->dwell_time_dfs;
+ } else {
+ struct conf_sched_scan_settings *c = &wl->conf.sched_scan;
+ u32 delta_per_probe;
+
+ if (band == IEEE80211_BAND_5GHZ)
+ delta_per_probe = c->dwell_time_delta_per_probe_5;
+ else
+ delta_per_probe = c->dwell_time_delta_per_probe;

- max_dwell_time_active = min_dwell_time_active + c->max_dwell_time_delta;
+ min_dwell_time_active = c->base_dwell_time +
+ n_ssids * c->num_probe_reqs * delta_per_probe;

+ max_dwell_time_active = min_dwell_time_active +
+ c->max_dwell_time_delta;
+ dwell_time_passive = c->dwell_time_passive;
+ dwell_time_dfs = c->dwell_time_dfs;
+ }
min_dwell_time_active = DIV_ROUND_UP(min_dwell_time_active, 1000);
max_dwell_time_active = DIV_ROUND_UP(max_dwell_time_active, 1000);
- dwell_time_passive = DIV_ROUND_UP(c->dwell_time_passive, 1000);
- dwell_time_dfs = DIV_ROUND_UP(c->dwell_time_dfs, 1000);
+ dwell_time_passive = DIV_ROUND_UP(dwell_time_passive, 1000);
+ dwell_time_dfs = DIV_ROUND_UP(dwell_time_dfs, 1000);

for (i = 0, j = start;
i < n_channels && j < max_channels;
@@ -195,7 +210,8 @@ wlcore_set_scan_chan_params(struct wl1271 *wl,
struct wlcore_scan_channels *cfg,
struct ieee80211_channel *channels[],
u32 n_channels,
- u32 n_ssids)
+ u32 n_ssids,
+ int scan_type)
{
u8 n_pactive_ch = 0;

@@ -208,7 +224,8 @@ wlcore_set_scan_chan_params(struct wl1271 *wl,
IEEE80211_BAND_2GHZ,
false, true, 0,
MAX_CHANNELS_2GHZ,
- &n_pactive_ch);
+ &n_pactive_ch,
+ scan_type);
cfg->active[0] =
wlcore_scan_get_channels(wl,
channels,
@@ -219,7 +236,8 @@ wlcore_set_scan_chan_params(struct wl1271 *wl,
false, false,
cfg->passive[0],
MAX_CHANNELS_2GHZ,
- &n_pactive_ch);
+ &n_pactive_ch,
+ scan_type);
cfg->passive[1] =
wlcore_scan_get_channels(wl,
channels,
@@ -229,7 +247,8 @@ wlcore_set_scan_chan_params(struct wl1271 *wl,
IEEE80211_BAND_5GHZ,
false, true, 0,
wl->max_channels_5,
- &n_pactive_ch);
+ &n_pactive_ch,
+ scan_type);
cfg->dfs =
wlcore_scan_get_channels(wl,
channels,
@@ -240,7 +259,8 @@ wlcore_set_scan_chan_params(struct wl1271 *wl,
true, true,
cfg->passive[1],
wl->max_channels_5,
- &n_pactive_ch);
+ &n_pactive_ch,
+ scan_type);
cfg->active[1] =
wlcore_scan_get_channels(wl,
channels,
@@ -251,7 +271,8 @@ wlcore_set_scan_chan_params(struct wl1271 *wl,
false, false,
cfg->passive[1] + cfg->dfs,
wl->max_channels_5,
- &n_pactive_ch);
+ &n_pactive_ch,
+ scan_type);

/* 802.11j channels are not supported yet */
cfg->passive[2] = 0;
diff --git a/drivers/net/wireless/ti/wlcore/scan.h b/drivers/net/wireless/ti/wlcore/scan.h
index 8465f35..9ae6065 100644
--- a/drivers/net/wireless/ti/wlcore/scan.h
+++ b/drivers/net/wireless/ti/wlcore/scan.h
@@ -150,12 +150,19 @@ struct wlcore_scan_channels {
struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
};

+enum {
+ SCAN_TYPE_SEARCH = 0,
+ SCAN_TYPE_PERIODIC = 1,
+ SCAN_TYPE_TRACKING = 2,
+};
+
bool
wlcore_set_scan_chan_params(struct wl1271 *wl,
struct wlcore_scan_channels *cfg,
struct ieee80211_channel *channels[],
u32 n_channels,
- u32 n_ssids);
+ u32 n_ssids,
+ int scan_type);

int
wlcore_scan_sched_scan_ssid_list(struct wl1271 *wl,
--
1.7.9.5


2012-11-27 09:13:54

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 11/11] wlcore/wl18xx/wl12xx: add recovery settings to conf

On Mon, 2012-11-26 at 18:05 +0200, Arik Nemtsov wrote:
> From: Yair Shapira <[email protected]>
>
> add support for recovery settings including bug_on_recovery and
> no_recovery options.
>
> These options can now be set using wl18xx-conf.bin file and wlconf
> tool.
>
> Signed-off-by: Yair Shapira <[email protected]>
> Signed-off-by: Arik Nemtsov <[email protected]>
> ---

[...]

> diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
> index a48a36c..56f20d6 100644
> --- a/drivers/net/wireless/ti/wlcore/main.c
> +++ b/drivers/net/wireless/ti/wlcore/main.c
[...]
> @@ -306,6 +306,8 @@ out:
> static void wlcore_adjust_conf(struct wl1271 *wl)
> {
> /* Adjust settings according to optional module parameters */
> +
> + /* Firmware Log Settings */

This comment is useless and doesn't follow the coding style. I'll
remove it when applying.

> @@ -321,6 +323,13 @@ static void wlcore_adjust_conf(struct wl1271 *wl)
> wl1271_error("Unknown fwlog parameter %s", fwlog_param);
> }
> }
> +
> + /* Recovery Settings */

Same here.

--
Luca.


2012-11-26 16:06:03

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 03/11] wlcore: don't stop fwlog if dbgpins are used

From: Eliad Peller <[email protected]>

Due to a bug, the fw asserts on fw log stop when dbg-pins are used.
Don't stop the fw log in this case.

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 475d0cd..49ff7ee 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -805,11 +805,13 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)

/*
* Make sure the chip is awake and the logger isn't active.
- * Do not send a stop fwlog command if the fw is hanged.
+ * Do not send a stop fwlog command if the fw is hanged or if
+ * dbgpins are used (due to some fw bug).
*/
if (wl1271_ps_elp_wakeup(wl))
goto out;
- if (!wl->watchdog_recovery)
+ if (!wl->watchdog_recovery &&
+ wl->conf.fwlog.output != WL12XX_FWLOG_OUTPUT_DBG_PINS)
wl12xx_cmd_stop_fwlog(wl);

/* Read the first memory block address */
--
1.7.9.5


2012-11-26 16:06:08

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 06/11] wlcore: use sta_state-based ROCs for AP mode

From: Eliad Peller <[email protected]>

Try an opportunistic ROC when a STA is first added and stop the ROC when
the STA is removed or successfully authenticated. This would ensure we
don't miss auth/assoc/EAPOL packets during connection

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/main.c | 45 +++++++++++++++++++++++++++++
drivers/net/wireless/ti/wlcore/wlcore_i.h | 4 +++
2 files changed, 49 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index f628297c..45008fa 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4486,6 +4486,45 @@ static int wl12xx_sta_remove(struct wl1271 *wl,
return ret;
}

+static void wlcore_roc_if_possible(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif)
+{
+ if (find_first_bit(wl->roc_map,
+ WL12XX_MAX_ROLES) < WL12XX_MAX_ROLES)
+ return;
+
+ if (WARN_ON(wlvif->role_id == WL12XX_INVALID_ROLE_ID))
+ return;
+
+ wl12xx_roc(wl, wlvif, wlvif->role_id, wlvif->band, wlvif->channel);
+}
+
+static void wlcore_update_inconn_sta(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ struct wl1271_station *wl_sta,
+ bool in_connection)
+{
+ if (in_connection) {
+ if (WARN_ON(wl_sta->in_connection))
+ return;
+ wl_sta->in_connection = true;
+ if (!wlvif->inconn_count++)
+ wlcore_roc_if_possible(wl, wlvif);
+ } else {
+ if (!wl_sta->in_connection)
+ return;
+
+ wl_sta->in_connection = false;
+ wlvif->inconn_count--;
+ if (WARN_ON(wlvif->inconn_count < 0))
+ return;
+
+ if (!wlvif->inconn_count)
+ if (test_bit(wlvif->role_id, wl->roc_map))
+ wl12xx_croc(wl, wlvif->role_id);
+ }
+}
+
static int wl12xx_update_sta_state(struct wl1271 *wl,
struct wl12xx_vif *wlvif,
struct ieee80211_sta *sta,
@@ -4508,6 +4547,8 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
ret = wl12xx_sta_add(wl, wlvif, sta);
if (ret)
return ret;
+
+ wlcore_update_inconn_sta(wl, wlvif, wl_sta, true);
}

/* Remove station (AP mode) */
@@ -4516,6 +4557,8 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
new_state == IEEE80211_STA_NOTEXIST) {
/* must not fail */
wl12xx_sta_remove(wl, wlvif, sta);
+
+ wlcore_update_inconn_sta(wl, wlvif, wl_sta, false);
}

/* Authorize station (AP mode) */
@@ -4529,6 +4572,8 @@ static int wl12xx_update_sta_state(struct wl1271 *wl,
hlid);
if (ret)
return ret;
+
+ wlcore_update_inconn_sta(wl, wlvif, wl_sta, false);
}

/* Authorize station */
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index e3a77aa..5a92cb2 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -315,6 +315,7 @@ struct wl12xx_rx_filter {

struct wl1271_station {
u8 hlid;
+ bool in_connection;
};

struct wl12xx_vif {
@@ -425,6 +426,9 @@ struct wl12xx_vif {
struct delayed_work channel_switch_work;
struct delayed_work connection_loss_work;

+ /* number of in connection stations */
+ int inconn_count;
+
/*
* This struct must be last!
* data that has to be saved acrossed reconfigs (e.g. recovery)
--
1.7.9.5


2012-11-27 09:08:13

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 01/11] wlcore: configure dwell times according to scan type

On Tue, 2012-11-27 at 10:54 +0200, Luciano Coelho wrote:
> On Mon, 2012-11-26 at 18:05 +0200, Arik Nemtsov wrote:
> > From: Eliad Peller <[email protected]>
> >
> > Allow configuring different dwell times to the different
> > scan types (regular and scheduled).
> >
> > Add new configuration entry (dwell_time_dfs) to
> > conf_scan_settings, in order to allow setting
> > different values for normal scan and scheduled scan.
> >
> > Signed-off-by: Eliad Peller <[email protected]>
> > Signed-off-by: Arik Nemtsov <[email protected]>
> > ---
>
> This patch changes the semantics of two values in the middle of the conf
> struct, so WLCORE_CONF_VERSION should be increased. Also, the wlconf
> tool should be updated.

Oops! Ignore this comment. For some reason I missed the change in the
WLCORE_CONF_VERSION in this patch. Now I see it has changed from 2 to
3.

--
Luca.


2012-11-26 16:06:16

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 09/11] wlcore: don't allow access to FW mem when chip is off

From: Eliad Peller <[email protected]>

Don't allow read/writes to FW memory when the FW is not powered on.

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/debugfs.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index 1cf2cdb..7fbab3c 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -1062,7 +1062,7 @@ static ssize_t dev_mem_read(struct file *file,

mutex_lock(&wl->mutex);

- if (unlikely(wl->state == WLCORE_STATE_OFF)) {
+ if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EFAULT;
goto skip_read;
}
@@ -1149,7 +1149,7 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf,

mutex_lock(&wl->mutex);

- if (unlikely(wl->state == WLCORE_STATE_OFF)) {
+ if (unlikely(wl->state != WLCORE_STATE_ON)) {
ret = -EFAULT;
goto skip_write;
}
--
1.7.9.5


2012-11-27 12:46:37

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 09/11] wlcore: don't allow access to FW mem when chip is off

On Mon, 2012-11-26 at 18:05 +0200, Arik Nemtsov wrote:
> From: Eliad Peller <[email protected]>
>
> Don't allow read/writes to FW memory when the FW is not powered on.
>
> Signed-off-by: Eliad Peller <[email protected]>
> Signed-off-by: Arik Nemtsov <[email protected]>
> ---

As discussed in the other thread, I'll ignore this patch.

--
Luca.


2012-11-26 16:06:18

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 10/11] wlcore: gather information about firmware stability

From: Luciano Coelho <[email protected]>

It's sometimes useful to gather information about the firmware
stability in long test runs, especially to see if problems are
recurring frequently or not. With this commit we count the number of
times a hardware recovery was issued and print it out during recovery
and in the driver_state in debugfs.

Signed-off-by: Luciano Coelho <[email protected]>
Signed-off-by: Igal Chernobelsky <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/debugfs.c | 1 +
drivers/net/wireless/ti/wlcore/main.c | 4 +++-
drivers/net/wireless/ti/wlcore/wlcore.h | 2 ++
3 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c
index 7fbab3c..78d2eb3 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.c
+++ b/drivers/net/wireless/ti/wlcore/debugfs.c
@@ -490,6 +490,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
DRIVER_STATE_PRINT_HEX(chip.id);
DRIVER_STATE_PRINT_STR(chip.fw_ver_str);
DRIVER_STATE_PRINT_STR(chip.phy_fw_ver_str);
+ DRIVER_STATE_PRINT_INT(recovery_count);

#undef DRIVER_STATE_PRINT_INT
#undef DRIVER_STATE_PRINT_LONG
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index a6283df..a48a36c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -879,7 +879,8 @@ static void wlcore_print_recovery(struct wl1271 *wl)
if (ret < 0)
return;

- wl1271_info("pc: 0x%x, hint_sts: 0x%08x", pc, hint_sts);
+ wl1271_info("pc: 0x%x, hint_sts: 0x%08x count: %d",
+ pc, hint_sts, ++wl->recovery_count);

wlcore_set_partition(wl, &wl->ptable[PART_WORK]);
}
@@ -5685,6 +5686,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size,
wl->flags = 0;
wl->sg_enabled = true;
wl->sleep_auth = WL1271_PSM_ILLEGAL;
+ wl->recovery_count = 0;
wl->hw_pg_ver = -1;
wl->ap_ps_map = 0;
wl->ap_fw_ps_map = 0;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 5f580e5..4d5c69e 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -337,6 +337,8 @@ struct wl1271 {

bool enable_11a;

+ int recovery_count;
+
/* Most recently reported noise in dBm */
s8 noise;

--
1.7.9.5


2012-11-28 09:55:30

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 00/11] wlcore fixes for 3.8 (part1)

On Mon, 2012-11-26 at 18:05 +0200, Arik Nemtsov wrote:
> Various fixes for wlcore, to be applied on top of
> Eliad's 18xx API update series.
>
> There are more patches pending - the splitting into smaller
> series is meant to ease review.
>
> Arik Nemtsov (2):
> wlcore: use new set bandwidth command to adjusting channel BW
> wlcore/wl18xx/wl12xx: separate channel count between chips
>
> Eliad Peller (7):
> wlcore: configure dwell times according to scan type
> wlcore: don't stop fwlog if dbgpins are used
> wlcore/wl18xx: allow TX BA on all TIDs
> wlcore: use sta_state-based ROCs for AP mode
> wlcore: mask out CCK rates when starting GO
> wlcore: move ps change handling to .bss_info_changed()
> wlcore: don't allow access to FW mem when chip is off
>
> Luciano Coelho (1):
> wlcore: gather information about firmware stability
>
> Yair Shapira (1):
> wlcore/wl18xx/wl12xx: add recovery settings to conf

Applied this set, except for 09/11. Thanks!

--
Luca.


2012-11-26 16:06:04

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 04/11] wlcore/wl18xx: allow TX BA on all TIDs

From: Eliad Peller <[email protected]>

In 12xx cards a FW limitation prevents us from from starting TX BA
sessions on TIDs 6/7. This restriction does not exist for 18xx cards.
Enable TX BA on all TIDs for them

[Arik - split Tx BA parameter between chip families. Don't change this
setting for 12xx]

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 2 +-
drivers/net/wireless/ti/wl18xx/main.c | 2 +-
drivers/net/wireless/ti/wlcore/conf.h | 3 ---
3 files changed, 2 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 17ee0fd..032a639 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -293,7 +293,7 @@ static struct wlcore_conf wl12xx_conf = {
.rx_ba_win_size = 8,
.tx_ba_win_size = 64,
.inactivity_timeout = 10000,
- .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
+ .tx_ba_tid_bitmap = 0x3f,
},
/*
* Memory config for wl127x chips is given in the
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index c616c21..5e81d9c 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -420,7 +420,7 @@ static struct wlcore_conf wl18xx_conf = {
.rx_ba_win_size = 32,
.tx_ba_win_size = 64,
.inactivity_timeout = 10000,
- .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
+ .tx_ba_tid_bitmap = 0xff,
},
.mem = {
.num_stations = 1,
diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h
index c9de4d5..e0695e9 100644
--- a/drivers/net/wireless/ti/wlcore/conf.h
+++ b/drivers/net/wireless/ti/wlcore/conf.h
@@ -561,9 +561,6 @@ struct conf_tx_ac_category {

#define CONF_TX_MAX_TID_COUNT 8

-/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */
-#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F
-
enum {
CONF_CHANNEL_TYPE_DCF = 0, /* DC/LEGACY*/
CONF_CHANNEL_TYPE_EDCF = 1, /* EDCA*/
--
1.7.9.5


2012-11-26 16:06:07

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 05/11] wlcore/wl18xx/wl12xx: separate channel count between chips

18xx chips are capable of staying on 2 channels at the same time.
Introduce a chip-family specific parameter to set the number of channels
in the interface-combinations published by the driver.

Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl12xx/main.c | 1 +
drivers/net/wireless/ti/wl18xx/main.c | 1 +
drivers/net/wireless/ti/wlcore/main.c | 4 ++--
drivers/net/wireless/ti/wlcore/wlcore.h | 3 +++
4 files changed, 7 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c
index 032a639..dafcdf6 100644
--- a/drivers/net/wireless/ti/wl12xx/main.c
+++ b/drivers/net/wireless/ti/wl12xx/main.c
@@ -1676,6 +1676,7 @@ static int wl12xx_setup(struct wl1271 *wl)
wl->rtable = wl12xx_rtable;
wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS;
wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS;
+ wl->num_channels = 1;
wl->num_mac_addr = WL12XX_NUM_MAC_ADDRESSES;
wl->band_rate_to_idx = wl12xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX;
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index 5e81d9c..9d2fa91 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1456,6 +1456,7 @@ static int wl18xx_setup(struct wl1271 *wl)
wl->rtable = wl18xx_rtable;
wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS;
wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS;
+ wl->num_channels = 2;
wl->num_mac_addr = WL18XX_NUM_MAC_ADDRESSES;
wl->band_rate_to_idx = wl18xx_band_rate_to_idx;
wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX;
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 49ff7ee..f628297c 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -5464,10 +5464,9 @@ static const struct ieee80211_iface_limit wlcore_iface_limits[] = {
},
};

-static const struct ieee80211_iface_combination
+static struct ieee80211_iface_combination
wlcore_iface_combinations[] = {
{
- .num_different_channels = 1,
.max_interfaces = 3,
.limits = wlcore_iface_limits,
.n_limits = ARRAY_SIZE(wlcore_iface_limits),
@@ -5570,6 +5569,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;

/* allowed interface combinations */
+ wlcore_iface_combinations[0].num_different_channels = wl->num_channels;
wl->hw->wiphy->iface_combinations = wlcore_iface_combinations;
wl->hw->wiphy->n_iface_combinations =
ARRAY_SIZE(wlcore_iface_combinations);
diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index 037c56e..5f580e5 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -441,6 +441,9 @@ struct wl1271 {
unsigned int min_fw_ver[NUM_FW_VER];

struct completion nvs_loading_complete;
+
+ /* number of concurrent channels the HW supports */
+ u32 num_channels;
};

int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev);
--
1.7.9.5


2012-11-26 16:06:01

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 02/11] wlcore: use new set bandwidth command to adjusting channel BW

We support changing the channel BW when we started the STA role on
a 40Mhz bandwidth. Otherwise a reconnection is required.
Save the started channel width and use it when channel width updates
arrive.

Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wl18xx/acx.c | 31 +++++++++++++++++++++++
drivers/net/wireless/ti/wl18xx/acx.h | 14 +++++++++++
drivers/net/wireless/ti/wl18xx/main.c | 38 +++++++++++++++++++++++++++++
drivers/net/wireless/ti/wlcore/cmd.c | 1 +
drivers/net/wireless/ti/wlcore/hw_ops.h | 8 ++++++
drivers/net/wireless/ti/wlcore/main.c | 12 +++++++++
drivers/net/wireless/ti/wlcore/wlcore.h | 2 ++
drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 ++
8 files changed, 108 insertions(+)

diff --git a/drivers/net/wireless/ti/wl18xx/acx.c b/drivers/net/wireless/ti/wl18xx/acx.c
index adff9cd..801d8af 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.c
+++ b/drivers/net/wireless/ti/wl18xx/acx.c
@@ -109,3 +109,34 @@ out:
kfree(acx);
return ret;
}
+
+int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide)
+{
+ struct wlcore_peer_ht_operation_mode *acx;
+ int ret;
+
+ wl1271_debug(DEBUG_ACX, "acx peer ht operation mode hlid %d bw %d",
+ hlid, wide);
+
+ acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+ if (!acx) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ acx->hlid = hlid;
+ acx->bandwidth = wide ? WLCORE_BANDWIDTH_40MHZ : WLCORE_BANDWIDTH_20MHZ;
+
+ ret = wl1271_cmd_configure(wl, ACX_PEER_HT_OPERATION_MODE_CFG, acx,
+ sizeof(*acx));
+
+ if (ret < 0) {
+ wl1271_warning("acx peer ht operation mode failed: %d", ret);
+ goto out;
+ }
+
+out:
+ kfree(acx);
+ return ret;
+
+}
diff --git a/drivers/net/wireless/ti/wl18xx/acx.h b/drivers/net/wireless/ti/wl18xx/acx.h
index 394d125..b57e348 100644
--- a/drivers/net/wireless/ti/wl18xx/acx.h
+++ b/drivers/net/wireless/ti/wl18xx/acx.h
@@ -284,10 +284,24 @@ struct wl18xx_acx_clear_statistics {
struct acx_header header;
};

+enum wlcore_bandwidth {
+ WLCORE_BANDWIDTH_20MHZ,
+ WLCORE_BANDWIDTH_40MHZ,
+};
+
+struct wlcore_peer_ht_operation_mode {
+ struct acx_header header;
+
+ u8 hlid;
+ u8 bandwidth; /* enum wlcore_bandwidth */
+ u8 padding[2];
+};
+
int wl18xx_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap,
u32 sdio_blk_size, u32 extra_mem_blks,
u32 len_field_size);
int wl18xx_acx_set_checksum_state(struct wl1271 *wl);
int wl18xx_acx_clear_statistics(struct wl1271 *wl);
+int wl18xx_acx_peer_ht_operation_mode(struct wl1271 *wl, u8 hlid, bool wide);

#endif /* __WL18XX_ACX_H__ */
diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c
index c015231..c616c21 100644
--- a/drivers/net/wireless/ti/wl18xx/main.c
+++ b/drivers/net/wireless/ti/wl18xx/main.c
@@ -1319,6 +1319,43 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl,
return buf_offset;
}

+static void wl18xx_sta_rc_update(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta,
+ u32 changed)
+{
+ bool wide = sta->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+
+ wl1271_debug(DEBUG_MAC80211, "mac80211 sta_rc_update wide %d", wide);
+
+ if (!(changed & IEEE80211_RC_BW_CHANGED))
+ return;
+
+ mutex_lock(&wl->mutex);
+
+ /* sanity */
+ if (WARN_ON(wlvif->bss_type != BSS_TYPE_STA_BSS))
+ goto out;
+
+ /* ignore the change before association */
+ if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags))
+ goto out;
+
+ /*
+ * If we started out as wide, we can change the operation mode. If we
+ * thought this was a 20mhz AP, we have to reconnect
+ */
+ if (wlvif->sta.role_chan_type == NL80211_CHAN_HT40MINUS ||
+ wlvif->sta.role_chan_type == NL80211_CHAN_HT40PLUS)
+ wl18xx_acx_peer_ht_operation_mode(wl, wlvif->sta.hlid, wide);
+ else
+ ieee80211_connection_loss(wl12xx_wlvif_to_vif(wlvif));
+
+out:
+ mutex_unlock(&wl->mutex);
+}
+
+
static int wl18xx_setup(struct wl1271 *wl);

static struct wlcore_ops wl18xx_ops = {
@@ -1354,6 +1391,7 @@ static struct wlcore_ops wl18xx_ops = {
.set_key = wl18xx_set_key,
.channel_switch = wl18xx_cmd_channel_switch,
.pre_pkt_send = wl18xx_pre_pkt_send,
+ .sta_rc_update = wl18xx_sta_rc_update,
};

/* HT cap appropriate for wide channels in 2Ghz */
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 599c006..65f071d 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -480,6 +480,7 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl, struct wl12xx_vif *wlvif)
goto err_hlid;
}

+ wlvif->sta.role_chan_type = wlvif->channel_type;
goto out_free;

err_hlid:
diff --git a/drivers/net/wireless/ti/wlcore/hw_ops.h b/drivers/net/wireless/ti/wlcore/hw_ops.h
index 2673d78..0e0b656 100644
--- a/drivers/net/wireless/ti/wlcore/hw_ops.h
+++ b/drivers/net/wireless/ti/wlcore/hw_ops.h
@@ -201,4 +201,12 @@ wlcore_hw_pre_pkt_send(struct wl1271 *wl, u32 buf_offset, u32 last_len)
return buf_offset;
}

+static inline void
+wlcore_hw_sta_rc_update(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta, u32 changed)
+{
+ if (wl->ops->sta_rc_update)
+ wl->ops->sta_rc_update(wl, wlvif, sta, changed);
+}
+
#endif
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 0ed7f10..475d0cd 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4948,6 +4948,17 @@ static int wlcore_op_cancel_remain_on_channel(struct ieee80211_hw *hw)
return 0;
}

+static void wlcore_op_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u32 changed)
+{
+ struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
+ struct wl1271 *wl = hw->priv;
+
+ wlcore_hw_sta_rc_update(wl, wlvif, sta, changed);
+}
+
static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw)
{
struct wl1271 *wl = hw->priv;
@@ -5146,6 +5157,7 @@ static const struct ieee80211_ops wl1271_ops = {
.change_chanctx = wlcore_op_change_chanctx,
.assign_vif_chanctx = wlcore_op_assign_vif_chanctx,
.unassign_vif_chanctx = wlcore_op_unassign_vif_chanctx,
+ .sta_rc_update = wlcore_op_sta_rc_update,
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};

diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h
index b315897..037c56e 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore.h
@@ -101,6 +101,8 @@ struct wlcore_ops {
struct wl12xx_vif *wlvif,
struct ieee80211_channel_switch *ch_switch);
u32 (*pre_pkt_send)(struct wl1271 *wl, u32 buf_offset, u32 last_len);
+ void (*sta_rc_update)(struct wl1271 *wl, struct wl12xx_vif *wlvif,
+ struct ieee80211_sta *sta, u32 changed);
};

enum wlcore_partitions {
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 6be1e8e..e3a77aa 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -341,6 +341,8 @@ struct wl12xx_vif {
u8 klv_template_id;

bool qos;
+ /* channel type we started the STA role with */
+ enum nl80211_channel_type role_chan_type;
} sta;
struct {
u8 global_hlid;
--
1.7.9.5


2012-11-26 16:06:10

by Arik Nemtsov

[permalink] [raw]
Subject: [PATCH 07/11] wlcore: mask out CCK rates when starting GO

From: Eliad Peller <[email protected]>

mask out CCK rates from the AP's local rates
when the interace is p2p interface (GO).

Signed-off-by: Eliad Peller <[email protected]>
Signed-off-by: Arik Nemtsov <[email protected]>
---
drivers/net/wireless/ti/wlcore/cmd.c | 2 ++
1 file changed, 2 insertions(+)

diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c
index 65f071d..fc508ee 100644
--- a/drivers/net/wireless/ti/wlcore/cmd.c
+++ b/drivers/net/wireless/ti/wlcore/cmd.c
@@ -591,6 +591,8 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl, struct wl12xx_vif *wlvif)

supported_rates = CONF_TX_ENABLED_RATES | CONF_TX_MCS_RATES |
wlcore_hw_ap_get_mimo_wide_rate_mask(wl, wlvif);
+ if (wlvif->p2p)
+ supported_rates &= ~CONF_TX_CCK_RATES;

wl1271_debug(DEBUG_CMD, "cmd role start ap with supported_rates 0x%08x",
supported_rates);
--
1.7.9.5


2012-12-04 14:53:41

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH 04/11] wlcore/wl18xx: allow TX BA on all TIDs

On Mon, 2012-11-26 at 18:05 +0200, Arik Nemtsov wrote:
> From: Eliad Peller <[email protected]>
>
> In 12xx cards a FW limitation prevents us from from starting TX BA
> sessions on TIDs 6/7. This restriction does not exist for 18xx cards.
> Enable TX BA on all TIDs for them
>
> [Arik - split Tx BA parameter between chip families. Don't change this
> setting for 12xx]
>
> Signed-off-by: Eliad Peller <[email protected]>
> Signed-off-by: Arik Nemtsov <[email protected]>
> ---

I have dropped this patch. After some internal discussions, we decided
that it doesn't make sense to use BA on TIDs that require low latency.

--
Luca.