Hi John,
Here's another set of patches that have been pending for a while in our
internal tree. This is the last bomb and hopefully we'll be able to send them
more frequently from now on.
There are some SDIO fixes and improvements, some WMM and U-APSD stuff and the
usual bunch of general improvements and bugfixes.
Cheers,
Luca.
Juuso Oikarinen (10):
wl1271: Fix configuration of the TX opportunity value
wl1271: Fix SG configuration message structures
wl1271: Add proper WLAN-BT co-ex configuration, and enable co-ex.
wl1271: Move platform device registration from _spi to _main
wl1271: Add sysfs file to control BT co-ex state
wl1271: Fix MAC address handling
wl1271: Remove deprecated interface config function
wl1271: Update filters properly
wl1271: Don't generate null func template for ad-hoc
wl1271: Remove circular interlocking related to the inetaddr notifier
chain
Kalle Valo (6):
wl1271: enable WMM
wl1271: get pspoll and nullfunc templates from mac80211
wl1271: get probe request template from mac80211
wl1271: create qos nullfunc template
wl1271: fix ps scheme in wl1271_op_conf_tx()
wl1271: enable U-APSD
Teemu Paasikivi (5):
wl1271: Cleaned up wlan power on/off functions
wl1271: Changed SDIO MMC host claiming
wl1271: Added DEBUG_SDIO flag
wl1271: Removed duplicate code from module remove function.
wl1271: Changed platform_device to be dynamically allocated
drivers/net/wireless/wl12xx/wl1271.h | 7 +
drivers/net/wireless/wl12xx/wl1271_acx.c | 25 +-
drivers/net/wireless/wl12xx/wl1271_acx.h | 68 +----
drivers/net/wireless/wl12xx/wl1271_boot.c | 8 +
drivers/net/wireless/wl12xx/wl1271_cmd.c | 218 ++++-------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 12 +-
drivers/net/wireless/wl12xx/wl1271_conf.h | 330 ++++++++++++++----
drivers/net/wireless/wl12xx/wl1271_debugfs.c | 12 +-
drivers/net/wireless/wl12xx/wl1271_event.c | 2 +
drivers/net/wireless/wl12xx/wl1271_init.c | 4 +-
drivers/net/wireless/wl12xx/wl1271_io.h | 13 +
drivers/net/wireless/wl12xx/wl1271_main.c | 496 ++++++++++++++++----------
drivers/net/wireless/wl12xx/wl1271_sdio.c | 74 ++---
drivers/net/wireless/wl12xx/wl1271_spi.c | 35 +--
drivers/net/wireless/wl12xx/wl1271_tx.h | 3 -
15 files changed, 748 insertions(+), 559 deletions(-)
From: Juuso Oikarinen <[email protected]>
The null func template is not needed for ad-hoc, and it's generation is not
supported for ad-hoc (mac80211 will WARN about 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_cmd.c | 26 +++++++++++++++++++-------
drivers/net/wireless/wl12xx/wl1271_main.c | 6 ++----
2 files changed, 21 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 035ddc0..d005729 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -709,18 +709,30 @@ out:
int wl1271_cmd_build_null_data(struct wl1271 *wl)
{
- struct sk_buff *skb;
- int ret = 0;
+ struct sk_buff *skb = NULL;
+ int size;
+ void *ptr;
+ int ret = -ENOMEM;
- skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
- if (!skb)
- goto out;
- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, skb->data,
- skb->len);
+ if (wl->bss_type == BSS_TYPE_IBSS) {
+ size = sizeof(struct wl12xx_null_data_template);
+ ptr = NULL;
+ } else {
+ skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
+ if (!skb)
+ goto out;
+ size = skb->len;
+ ptr = skb->data;
+ }
+
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, ptr, size);
out:
dev_kfree_skb(skb);
+ if (ret)
+ wl1271_warning("cmd buld null data failed %d", ret);
+
return ret;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index befc2e9..6f6d366 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1619,12 +1619,10 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
*/
memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
+
ret = wl1271_cmd_build_null_data(wl);
- if (ret < 0) {
- wl1271_warning("cmd buld null data failed %d",
- ret);
+ 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]>
The bluetooth coexistence (SG) configuration messages have changed and
were completely wrong. For instance, intending to enable the SG, it was
instead disabled.
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_acx.c | 17 +----
drivers/net/wireless/wl12xx/wl1271_acx.h | 120 ++++++++++++++++--------------
2 files changed, 66 insertions(+), 71 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 60e2087..405ae1b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -547,7 +547,7 @@ int wl1271_acx_sg_enable(struct wl1271 *wl)
goto out;
}
- pta->enable = SG_ENABLE;
+ pta->enable = ACX_SG_DISABLE;
ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
if (ret < 0) {
@@ -575,19 +575,8 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
}
/* BT-WLAN coext parameters */
- param->per_threshold = cpu_to_le32(c->per_threshold);
- param->max_scan_compensation_time =
- cpu_to_le32(c->max_scan_compensation_time);
- param->nfs_sample_interval = cpu_to_le16(c->nfs_sample_interval);
- param->load_ratio = c->load_ratio;
- param->auto_ps_mode = c->auto_ps_mode;
- param->probe_req_compensation = c->probe_req_compensation;
- param->scan_window_compensation = c->scan_window_compensation;
- param->antenna_config = c->antenna_config;
- param->beacon_miss_threshold = c->beacon_miss_threshold;
- param->rate_adaptation_threshold =
- cpu_to_le32(c->rate_adaptation_threshold);
- param->rate_adaptation_snr = c->rate_adaptation_snr;
+ param->params[ACX_SG_BT_PER_THRESHOLD] = c->per_threshold;
+ param->param_idx = ACX_SG_BT_PER_THRESHOLD;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index aeccc98..88a05cb 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -393,80 +393,86 @@ struct acx_conn_monit_params {
} __attribute__ ((packed));
enum {
- SG_ENABLE = 0,
- SG_DISABLE,
- SG_SENSE_NO_ACTIVITY,
- SG_SENSE_ACTIVE
+ ACX_SG_DISABLE = 0,
+ ACX_SG_PROTECTIVE,
+ ACX_SG_OPPORTUNISTIC
};
struct acx_bt_wlan_coex {
struct acx_header header;
- /*
- * 0 -> PTA enabled
- * 1 -> PTA disabled
- * 2 -> sense no active mode, i.e.
- * an interrupt is sent upon
- * BT activity.
- * 3 -> PTA is switched on in response
- * to the interrupt sending.
- */
u8 enable;
u8 pad[3];
} __attribute__ ((packed));
-struct acx_dco_itrim_params {
+enum {
+ ACX_SG_BT_PER_THRESHOLD = 0,
+ ACX_SG_HV3_MAX_OVERRIDE,
+ ACX_SG_BT_NFS_SAMPLE_INTERVAL,
+ ACX_SG_BT_LOAD_RATIO,
+ ACX_SG_AUTO_PS_MODE,
+ ACX_SG_AUTO_SCAN_PROBE_REQ,
+ ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
+ ACX_SG_ANTENNA_CONFIGURATION,
+ ACX_SG_BEACON_MISS_PERCENT,
+ ACX_SG_RATE_ADAPT_THRESH,
+ ACX_SG_RATE_ADAPT_SNR,
+ ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
+ ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
+ ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
+ ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
+ ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
+ ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
+ ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
+ ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
+ ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
+ ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
+ ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
+ ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
+ ACX_SG_RXT,
+ ACX_SG_TXT,
+ ACX_SG_ADAPTIVE_RXT_TXT,
+ ACX_SG_PS_POLL_TIMEOUT,
+ ACX_SG_UPSD_TIMEOUT,
+ ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
+ ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
+ ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR,
+ ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
+ ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
+ ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
+ ACX_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
+ ACX_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
+ ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
+ ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
+ ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
+ ACX_SG_PASSIVE_SCAN_A2DP_BT_TIME,
+ ACX_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
+ ACX_SG_HV3_MAX_SERVED,
+ ACX_SG_DHCP_TIME,
+ ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
+ ACX_SG_TEMP_PARAM_1,
+ ACX_SG_TEMP_PARAM_2,
+ ACX_SG_TEMP_PARAM_3,
+ ACX_SG_TEMP_PARAM_4,
+ ACX_SG_TEMP_PARAM_5,
+ ACX_SG_PARAMS_MAX,
+ ACX_SG_PARAMS_ALL = 0xff
+};
+
+struct acx_bt_wlan_coex_param {
struct acx_header header;
- u8 enable;
+ __le32 params[ACX_SG_PARAMS_MAX];
+ u8 param_idx;
u8 padding[3];
- __le32 timeout;
} __attribute__ ((packed));
-#define PTA_ANTENNA_TYPE_DEF (0)
-#define PTA_BT_HP_MAXTIME_DEF (2000)
-#define PTA_WLAN_HP_MAX_TIME_DEF (5000)
-#define PTA_SENSE_DISABLE_TIMER_DEF (1350)
-#define PTA_PROTECTIVE_RX_TIME_DEF (1500)
-#define PTA_PROTECTIVE_TX_TIME_DEF (1500)
-#define PTA_TIMEOUT_NEXT_BT_LP_PACKET_DEF (3000)
-#define PTA_SIGNALING_TYPE_DEF (1)
-#define PTA_AFH_LEVERAGE_ON_DEF (0)
-#define PTA_NUMBER_QUIET_CYCLE_DEF (0)
-#define PTA_MAX_NUM_CTS_DEF (3)
-#define PTA_NUMBER_OF_WLAN_PACKETS_DEF (2)
-#define PTA_NUMBER_OF_BT_PACKETS_DEF (2)
-#define PTA_PROTECTIVE_RX_TIME_FAST_DEF (1500)
-#define PTA_PROTECTIVE_TX_TIME_FAST_DEF (3000)
-#define PTA_CYCLE_TIME_FAST_DEF (8700)
-#define PTA_RX_FOR_AVALANCHE_DEF (5)
-#define PTA_ELP_HP_DEF (0)
-#define PTA_ANTI_STARVE_PERIOD_DEF (500)
-#define PTA_ANTI_STARVE_NUM_CYCLE_DEF (4)
-#define PTA_ALLOW_PA_SD_DEF (1)
-#define PTA_TIME_BEFORE_BEACON_DEF (6300)
-#define PTA_HPDM_MAX_TIME_DEF (1600)
-#define PTA_TIME_OUT_NEXT_WLAN_DEF (2550)
-#define PTA_AUTO_MODE_NO_CTS_DEF (0)
-#define PTA_BT_HP_RESPECTED_DEF (3)
-#define PTA_WLAN_RX_MIN_RATE_DEF (24)
-#define PTA_ACK_MODE_DEF (1)
-
-struct acx_bt_wlan_coex_param {
+struct acx_dco_itrim_params {
struct acx_header header;
- __le32 per_threshold;
- __le32 max_scan_compensation_time;
- __le16 nfs_sample_interval;
- u8 load_ratio;
- u8 auto_ps_mode;
- u8 probe_req_compensation;
- u8 scan_window_compensation;
- u8 antenna_config;
- u8 beacon_miss_threshold;
- __le32 rate_adaptation_threshold;
- s8 rate_adaptation_snr;
+ u8 enable;
u8 padding[3];
+ __le32 timeout;
} __attribute__ ((packed));
struct acx_energy_detection {
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Added separate flag for SDIO debugging. Previously it has used
DEBUG_SPI flag. This patch also includes couple indentation fixes.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 1 +
drivers/net/wireless/wl12xx/wl1271_sdio.c | 20 ++++++++++++--------
2 files changed, 13 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 23a0c7e..4e60806 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -53,6 +53,7 @@ enum {
DEBUG_MAC80211 = BIT(11),
DEBUG_CMD = BIT(12),
DEBUG_ACX = BIT(13),
+ DEBUG_SDIO = BIT(14),
DEBUG_ALL = ~0,
};
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index d9183b6..0478919 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -102,14 +102,14 @@ static void wl1271_sdio_init(struct wl1271 *wl)
}
static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
+ size_t len, bool fixed)
{
int ret;
struct sdio_func *func = wl_to_func(wl);
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
- wl1271_debug(DEBUG_SPI, "sdio read 52 addr 0x%x, byte 0x%02x",
+ wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
addr, ((u8 *)buf)[0]);
} else {
if (fixed)
@@ -117,9 +117,9 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
else
ret = sdio_memcpy_fromio(func, buf, addr, len);
- wl1271_debug(DEBUG_SPI, "sdio read 53 addr 0x%x, %d bytes",
+ wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %d bytes",
addr, len);
- wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len);
+ wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
}
if (ret)
@@ -128,19 +128,19 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
}
static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
- size_t len, bool fixed)
+ size_t len, bool fixed)
{
int ret;
struct sdio_func *func = wl_to_func(wl);
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
- wl1271_debug(DEBUG_SPI, "sdio write 52 addr 0x%x, byte 0x%02x",
+ wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
addr, ((u8 *)buf)[0]);
} else {
- wl1271_debug(DEBUG_SPI, "sdio write 53 addr 0x%x, %d bytes",
+ wl1271_debug(DEBUG_SDIO, "sdio write 53 addr 0x%x, %d bytes",
addr, len);
- wl1271_dump_ascii(DEBUG_SPI, "data: ", buf, len);
+ wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
if (fixed)
ret = sdio_writesb(func, addr, buf, len);
@@ -156,6 +156,10 @@ static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
{
struct sdio_func *func = wl_to_func(wl);
+ /* Let the SDIO stack handle wlan_enable control, so we
+ * keep host claimed while wlan is in use to keep wl1271
+ * alive.
+ */
if (enable) {
sdio_claim_host(func);
sdio_enable_func(func);
--
1.6.3.3
From: Kalle Valo <[email protected]>
wl1271 supports U-APSD similarly as wl1251, so let's enable it.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 2a2e584..037a4f4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1781,6 +1781,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params)
{
struct wl1271 *wl = hw->priv;
+ u8 ps_scheme;
int ret;
mutex_lock(&wl->mutex);
@@ -1798,11 +1799,15 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
if (ret < 0)
goto out_sleep;
+ if (params->uapsd)
+ ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER;
+ else
+ ps_scheme = CONF_PS_SCHEME_LEGACY;
+
ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
CONF_CHANNEL_TYPE_EDCF,
wl1271_tx_get_queue(queue),
- CONF_PS_SCHEME_LEGACY,
- CONF_ACK_POLICY_LEGACY, 0, 0);
+ ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0);
if (ret < 0)
goto out_sleep;
@@ -2083,6 +2088,7 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
IEEE80211_HW_NOISE_DBM |
IEEE80211_HW_BEACON_FILTER |
IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_SUPPORTS_UAPSD |
IEEE80211_HW_HAS_RATE_CONTROL;
wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch adds support for the filters configured by the mac80211 stack.
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 | 2 +
drivers/net/wireless/wl12xx/wl1271_cmd.c | 9 ----
drivers/net/wireless/wl12xx/wl1271_main.c | 58 ++++++++++++++++++++++++----
3 files changed, 51 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 4e60806..a0262b7 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -54,6 +54,7 @@ enum {
DEBUG_CMD = BIT(12),
DEBUG_ACX = BIT(13),
DEBUG_SDIO = BIT(14),
+ DEBUG_FILTERS = BIT(15),
DEBUG_ALL = ~0,
};
@@ -458,6 +459,7 @@ struct wl1271 {
/* Default key (for WEP) */
u32 default_key;
+ unsigned int filters;
unsigned int rx_config;
unsigned int rx_filter;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 0cbb0e1..035ddc0 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -281,15 +281,6 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
join->rx_filter_options = cpu_to_le32(wl->rx_filter);
join->bss_type = bss_type;
- /*
- * FIXME: disable temporarily all filters because after commit
- * 9cef8737 "mac80211: fix managed mode BSSID handling" broke
- * association. The filter logic needs to be implemented properly
- * and once that is done, this hack can be removed.
- */
- join->rx_config_options = cpu_to_le32(0);
- join->rx_filter_options = cpu_to_le32(WL1271_DEFAULT_RX_FILTER);
-
if (wl->band == IEEE80211_BAND_2GHZ)
join->basic_rate_set = cpu_to_le32(CONF_HW_BIT_RATE_1MBPS |
CONF_HW_BIT_RATE_2MBPS |
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 688009b..befc2e9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1080,6 +1080,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
wl->sta_rate_set = 0;
wl->flags = 0;
wl->vif = NULL;
+ wl->filters = 0;
for (i = 0; i < NUM_TX_QUEUES; i++)
wl->tx_blocks_freed[i] = 0;
@@ -1088,6 +1089,40 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
+static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
+{
+ wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+ wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+
+ /* combine requested filters with current filter config */
+ filters = wl->filters | filters;
+
+ wl1271_debug(DEBUG_FILTERS, "RX filters set: ");
+
+ if (filters & FIF_PROMISC_IN_BSS) {
+ wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS");
+ wl->rx_config &= ~CFG_UNI_FILTER_EN;
+ wl->rx_config |= CFG_BSSID_FILTER_EN;
+ }
+ if (filters & FIF_BCN_PRBRESP_PROMISC) {
+ wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC");
+ wl->rx_config &= ~CFG_BSSID_FILTER_EN;
+ wl->rx_config &= ~CFG_SSID_FILTER_EN;
+ }
+ if (filters & FIF_OTHER_BSS) {
+ wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS");
+ wl->rx_config &= ~CFG_BSSID_FILTER_EN;
+ }
+ if (filters & FIF_CONTROL) {
+ wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL");
+ wl->rx_filter |= CFG_RX_CTL_EN;
+ }
+ if (filters & FIF_FCSFAIL) {
+ wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL");
+ wl->rx_filter |= CFG_RX_FCS_ERROR;
+ }
+}
+
static int wl1271_join_channel(struct wl1271 *wl, int channel)
{
int ret = 0;
@@ -1095,12 +1130,12 @@ static int wl1271_join_channel(struct wl1271 *wl, int channel)
static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
0xad, 0xbe, 0xef };
- /* disable mac filter, so we hear everything */
- wl->rx_config &= ~CFG_BSSID_FILTER_EN;
-
wl->channel = channel;
memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
+ /* pass through frames from all BSS */
+ wl1271_configure_filters(wl, FIF_OTHER_BSS);
+
/* the dummy join is performed always with STATION BSS type to allow
also ad-hoc mode to listen to the surroundings without sending any
beacons yet. */
@@ -1126,7 +1161,9 @@ static int wl1271_unjoin_channel(struct wl1271 *wl)
clear_bit(WL1271_FLAG_JOINED, &wl->flags);
wl->channel = 0;
memset(wl->bssid, 0, ETH_ALEN);
- wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
+
+ /* stop filterting packets based on bssid */
+ wl1271_configure_filters(wl, FIF_OTHER_BSS);
out:
return ret;
@@ -1299,14 +1336,14 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
if (ret < 0)
goto out_sleep;
- kfree(fp);
-
- /* FIXME: We still need to set our filters properly */
-
/* determine, whether supported filter values have changed */
if (changed == 0)
goto out_sleep;
+ /* configure filters */
+ wl->filters = *total;
+ wl1271_configure_filters(wl, 0);
+
/* apply configured filters */
ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
if (ret < 0)
@@ -1317,6 +1354,7 @@ out_sleep:
out:
mutex_unlock(&wl->mutex);
+ kfree(fp);
}
static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
@@ -1580,7 +1618,6 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
* and enable the BSSID filter
*/
memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
- wl->rx_config |= CFG_BSSID_FILTER_EN;
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
ret = wl1271_cmd_build_null_data(wl);
if (ret < 0) {
@@ -1589,6 +1626,9 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
goto out_sleep;
}
+ /* filter out all packets not from this BSSID */
+ wl1271_configure_filters(wl, 0);
+
/* Need to update the BSSID (for filtering etc) */
do_join = true;
}
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
The per-queue TX opportunity value is configured by the mac80211 in units
of 32us. The firmware however wants it in us, so add the conversion.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 0a4ff7b..0de337f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1745,9 +1745,10 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
if (ret < 0)
goto out;
+ /* the txop is confed in units of 32us by the mac80211, we need us */
ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
params->cw_min, params->cw_max,
- params->aifs, params->txop);
+ params->aifs, params->txop << 5);
if (ret < 0)
goto out_sleep;
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Changed platform_device to be allocated dynamically from the
wl1271_alloc_hw function. Also cleaned up error handling in the
wl1271_alloc_hw function and module probe functions.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 1 +
drivers/net/wireless/wl12xx/wl1271_io.h | 1 +
drivers/net/wireless/wl12xx/wl1271_main.c | 42 ++++++++++++++++++++++------
drivers/net/wireless/wl12xx/wl1271_sdio.c | 3 +-
drivers/net/wireless/wl12xx/wl1271_spi.c | 3 +-
5 files changed, 39 insertions(+), 11 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index a0262b7..8f11506 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -353,6 +353,7 @@ struct wl1271_if_operations {
};
struct wl1271 {
+ struct platform_device *plat_dev;
struct ieee80211_hw *hw;
bool mac80211_registered;
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index 3ff88d9..d8837ef 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -161,6 +161,7 @@ int wl1271_set_partition(struct wl1271 *wl,
/* Functions from wl1271_main.c */
int wl1271_register_hw(struct wl1271 *wl);
+void wl1271_unregister_hw(struct wl1271 *wl);
int wl1271_init_ieee80211(struct wl1271 *wl);
struct ieee80211_hw *wl1271_alloc_hw(void);
int wl1271_free_hw(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 0bebc45..3daba6c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -2008,6 +2008,14 @@ int wl1271_register_hw(struct wl1271 *wl)
}
EXPORT_SYMBOL_GPL(wl1271_register_hw);
+void wl1271_unregister_hw(struct wl1271 *wl)
+{
+ ieee80211_unregister_hw(wl->hw);
+ wl->mac80211_registered = false;
+
+}
+EXPORT_SYMBOL_GPL(wl1271_unregister_hw);
+
int wl1271_init_ieee80211(struct wl1271 *wl)
{
/* The tx descriptor buffer and the TKIP space. */
@@ -2046,6 +2054,7 @@ EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
struct ieee80211_hw *wl1271_alloc_hw(void)
{
struct ieee80211_hw *hw;
+ struct platform_device *plat_dev = NULL;
struct wl1271 *wl;
int i, ret;
static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
@@ -2054,15 +2063,25 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
if (!hw) {
wl1271_error("could not alloc ieee80211_hw");
ret = -ENOMEM;
- goto err;
+ goto err_hw_alloc;
+ }
+
+ plat_dev = kmalloc(sizeof(wl1271_device), GFP_KERNEL);
+ if (!plat_dev) {
+ wl1271_error("could not allocate platform_device");
+ ret = -ENOMEM;
+ goto err_plat_alloc;
}
+ memcpy(plat_dev, &wl1271_device, sizeof(wl1271_device));
+
wl = hw->priv;
memset(wl, 0, sizeof(*wl));
INIT_LIST_HEAD(&wl->list);
wl->hw = hw;
+ wl->plat_dev = plat_dev;
skb_queue_head_init(&wl->tx_queue);
@@ -2103,15 +2122,15 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl1271_debugfs_init(wl);
/* Register platform device */
- ret = platform_device_register(&wl1271_device);
+ ret = platform_device_register(wl->plat_dev);
if (ret) {
wl1271_error("couldn't register platform device");
goto err_hw;
}
- dev_set_drvdata(&wl1271_device.dev, wl);
+ dev_set_drvdata(&wl->plat_dev->dev, wl);
/* Create sysfs file to control bt coex state */
- ret = device_create_file(&wl1271_device.dev, &dev_attr_bt_coex_state);
+ ret = device_create_file(&wl->plat_dev->dev, &dev_attr_bt_coex_state);
if (ret < 0) {
wl1271_error("failed to create sysfs file bt_coex_state");
goto err_platform;
@@ -2120,20 +2139,25 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
return hw;
err_platform:
- platform_device_unregister(&wl1271_device);
+ platform_device_unregister(wl->plat_dev);
err_hw:
- ieee80211_unregister_hw(wl->hw);
+ wl1271_debugfs_exit(wl);
+ kfree(plat_dev);
+
+err_plat_alloc:
+ ieee80211_free_hw(hw);
+
+err_hw_alloc:
-err:
return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int wl1271_free_hw(struct wl1271 *wl)
{
- platform_device_unregister(&wl1271_device);
- ieee80211_unregister_hw(wl->hw);
+ platform_device_unregister(wl->plat_dev);
+ kfree(wl->plat_dev);
wl1271_debugfs_exit(wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 99b5b3f..3c03de7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -239,7 +239,7 @@ static int __devinit wl1271_probe(struct sdio_func *func,
out_free:
- ieee80211_free_hw(hw);
+ wl1271_free_hw(wl);
return ret;
}
@@ -250,6 +250,7 @@ static void __devexit wl1271_remove(struct sdio_func *func)
free_irq(wl->irq, wl);
+ wl1271_unregister_hw(wl);
wl1271_free_hw(wl);
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 4c129c7..f44b05a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -422,7 +422,7 @@ static int __devinit wl1271_probe(struct spi_device *spi)
free_irq(wl->irq, wl);
out_free:
- ieee80211_free_hw(hw);
+ wl1271_free_hw(wl);
return ret;
}
@@ -433,6 +433,7 @@ static int __devexit wl1271_remove(struct spi_device *spi)
free_irq(wl->irq, wl);
+ wl1271_unregister_hw(wl);
wl1271_free_hw(wl);
return 0;
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Add a sysfs file to control the state of the BT co-ex (enable or disable it.)
By default, the BT co-ex is enabled.
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 | 2 +
drivers/net/wireless/wl12xx/wl1271_acx.c | 7 ++-
drivers/net/wireless/wl12xx/wl1271_acx.h | 2 +-
drivers/net/wireless/wl12xx/wl1271_init.c | 2 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 72 +++++++++++++++++++++++++++++
5 files changed, 81 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 7397999..23a0c7e 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -484,6 +484,8 @@ struct wl1271 {
/* Current chipset configuration */
struct conf_drv_settings conf;
+ bool sg_enabled;
+
struct list_head list;
};
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index e7c22d3..7e337ce 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -534,7 +534,7 @@ out:
}
-int wl1271_acx_sg_enable(struct wl1271 *wl)
+int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable)
{
struct acx_bt_wlan_coex *pta;
int ret;
@@ -547,7 +547,10 @@ int wl1271_acx_sg_enable(struct wl1271 *wl)
goto out;
}
- pta->enable = wl->conf.sg.state;
+ if (enable)
+ pta->enable = wl->conf.sg.state;
+ else
+ pta->enable = CONF_SG_DISABLE;
ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index dee3c06..8e5870f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -1005,7 +1005,7 @@ int wl1271_acx_dco_itrim_params(struct wl1271 *wl);
int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
int wl1271_acx_conn_monit_params(struct wl1271 *wl);
-int wl1271_acx_sg_enable(struct wl1271 *wl);
+int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
int wl1271_acx_sg_cfg(struct wl1271 *wl);
int wl1271_acx_cca_threshold(struct wl1271 *wl);
int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index d68445c..d9335fc 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -164,7 +164,7 @@ int wl1271_init_pta(struct wl1271 *wl)
if (ret < 0)
return ret;
- ret = wl1271_acx_sg_enable(wl);
+ ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index ad9c491..abf9f22 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1982,6 +1982,68 @@ static const struct ieee80211_ops wl1271_ops = {
CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
};
+static ssize_t wl1271_sysfs_show_bt_coex_state(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct wl1271 *wl = dev_get_drvdata(dev);
+ ssize_t len;
+
+ /* FIXME: what's the maximum length of buf? page size?*/
+ len = 500;
+
+ mutex_lock(&wl->mutex);
+ len = snprintf(buf, len, "%d\n\n0 - off\n1 - on\n",
+ wl->sg_enabled);
+ mutex_unlock(&wl->mutex);
+
+ return len;
+
+}
+
+static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct wl1271 *wl = dev_get_drvdata(dev);
+ unsigned long res;
+ int ret;
+
+ ret = strict_strtoul(buf, 10, &res);
+
+ if (ret < 0) {
+ wl1271_warning("incorrect value written to bt_coex_mode");
+ return count;
+ }
+
+ mutex_lock(&wl->mutex);
+
+ res = !!res;
+
+ if (res == wl->sg_enabled)
+ goto out;
+
+ wl->sg_enabled = res;
+
+ if (wl->state == WL1271_STATE_OFF)
+ goto out;
+
+ ret = wl1271_ps_elp_wakeup(wl, false);
+ if (ret < 0)
+ goto out;
+
+ wl1271_acx_sg_enable(wl, wl->sg_enabled);
+ wl1271_ps_elp_sleep(wl);
+
+ out:
+ mutex_unlock(&wl->mutex);
+ return count;
+}
+
+static DEVICE_ATTR(bt_coex_state, S_IRUGO | S_IWUSR,
+ wl1271_sysfs_show_bt_coex_state,
+ wl1271_sysfs_store_bt_coex_state);
+
int wl1271_register_hw(struct wl1271 *wl)
{
int ret;
@@ -2073,6 +2135,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->band = IEEE80211_BAND_2GHZ;
wl->vif = NULL;
wl->flags = 0;
+ wl->sg_enabled = true;
for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
wl->tx_frames[i] = NULL;
@@ -2095,9 +2158,18 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
}
dev_set_drvdata(&wl1271_device.dev, wl);
+ /* Create sysfs file to control bt coex state */
+ ret = device_create_file(&wl1271_device.dev, &dev_attr_bt_coex_state);
+ if (ret < 0) {
+ wl1271_error("failed to create sysfs file bt_coex_state");
+ goto err_platform;
+ }
return hw;
+err_platform:
+ platform_device_unregister(&wl1271_device);
+
err_hw:
ieee80211_unregister_hw(wl->hw);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
In order to get the platform device for both SPI and SDIO, move the platform
device registration to wl1271_main.c from wl1271_spi.c.
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 | 37 +++++++++++++++++++++++++++-
drivers/net/wireless/wl12xx/wl1271_spi.c | 31 +----------------------
2 files changed, 37 insertions(+), 31 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 6501d6e..ad9c491 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -29,6 +29,7 @@
#include <linux/etherdevice.h>
#include <linux/vmalloc.h>
#include <linux/inetdevice.h>
+#include <linux/platform_device.h>
#include "wl1271.h"
#include "wl12xx_80211.h"
@@ -280,6 +281,21 @@ static struct conf_drv_settings default_conf = {
}
};
+static void wl1271_device_release(struct device *dev)
+{
+
+}
+
+static struct platform_device wl1271_device = {
+ .name = "wl1271",
+ .id = -1,
+
+ /* device model insists to have a release function */
+ .dev = {
+ .release = wl1271_device_release,
+ },
+};
+
static LIST_HEAD(wl_list);
static void wl1271_conf_init(struct wl1271 *wl)
@@ -2025,12 +2041,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
{
struct ieee80211_hw *hw;
struct wl1271 *wl;
- int i;
+ int i, ret;
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
wl1271_error("could not alloc ieee80211_hw");
- return ERR_PTR(-ENOMEM);
+ ret = -ENOMEM;
+ goto err;
}
wl = hw->priv;
@@ -2070,12 +2087,28 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl1271_debugfs_init(wl);
+ /* Register platform device */
+ ret = platform_device_register(&wl1271_device);
+ if (ret) {
+ wl1271_error("couldn't register platform device");
+ goto err_hw;
+ }
+ dev_set_drvdata(&wl1271_device.dev, wl);
+
+
return hw;
+
+err_hw:
+ ieee80211_unregister_hw(wl->hw);
+
+err:
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(wl1271_alloc_hw);
int wl1271_free_hw(struct wl1271 *wl)
{
+ platform_device_unregister(&wl1271_device);
ieee80211_unregister_hw(wl->hw);
wl1271_debugfs_exit(wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index 0eea733..4c129c7 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -23,7 +23,6 @@
#include <linux/irq.h>
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/spi/wl12xx.h>
@@ -332,21 +331,6 @@ static irqreturn_t wl1271_irq(int irq, void *cookie)
return IRQ_HANDLED;
}
-static void wl1271_device_release(struct device *dev)
-{
-
-}
-
-static struct platform_device wl1271_device = {
- .name = "wl1271",
- .id = -1,
-
- /* device model insists to have a release function */
- .dev = {
- .release = wl1271_device_release,
- },
-};
-
static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
{
if (wl->set_power)
@@ -422,28 +406,18 @@ static int __devinit wl1271_probe(struct spi_device *spi)
disable_irq(wl->irq);
- ret = platform_device_register(&wl1271_device);
- if (ret) {
- wl1271_error("couldn't register platform device");
- goto out_irq;
- }
- dev_set_drvdata(&wl1271_device.dev, wl);
-
ret = wl1271_init_ieee80211(wl);
if (ret)
- goto out_platform;
+ goto out_irq;
ret = wl1271_register_hw(wl);
if (ret)
- goto out_platform;
+ goto out_irq;
wl1271_notice("initialized");
return 0;
- out_platform:
- platform_device_unregister(&wl1271_device);
-
out_irq:
free_irq(wl->irq, wl);
@@ -457,7 +431,6 @@ static int __devexit wl1271_remove(struct spi_device *spi)
{
struct wl1271 *wl = dev_get_drvdata(&spi->dev);
- platform_device_unregister(&wl1271_device);
free_irq(wl->irq, wl);
wl1271_free_hw(wl);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Add configuration values for the varous WLAN-BT co-ex configuration parameters,
and finally enable WLAN-BT co-ex. Based on preliminary measurements, it
appears the co-ex feature is not increasing WLAN power consumption, if BT
is not activated.
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_acx.c | 9 +-
drivers/net/wireless/wl12xx/wl1271_acx.h | 62 +------
drivers/net/wireless/wl12xx/wl1271_conf.h | 330 +++++++++++++++++++++++------
drivers/net/wireless/wl12xx/wl1271_init.c | 4 +-
drivers/net/wireless/wl12xx/wl1271_main.c | 62 +++++-
5 files changed, 328 insertions(+), 139 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.c b/drivers/net/wireless/wl12xx/wl1271_acx.c
index 405ae1b..e7c22d3 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.c
@@ -547,7 +547,7 @@ int wl1271_acx_sg_enable(struct wl1271 *wl)
goto out;
}
- pta->enable = ACX_SG_DISABLE;
+ pta->enable = wl->conf.sg.state;
ret = wl1271_cmd_configure(wl, ACX_SG_ENABLE, pta, sizeof(*pta));
if (ret < 0) {
@@ -564,7 +564,7 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
{
struct acx_bt_wlan_coex_param *param;
struct conf_sg_settings *c = &wl->conf.sg;
- int ret;
+ int i, ret;
wl1271_debug(DEBUG_ACX, "acx sg cfg");
@@ -575,8 +575,9 @@ int wl1271_acx_sg_cfg(struct wl1271 *wl)
}
/* BT-WLAN coext parameters */
- param->params[ACX_SG_BT_PER_THRESHOLD] = c->per_threshold;
- param->param_idx = ACX_SG_BT_PER_THRESHOLD;
+ for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
+ param->params[i] = c->params[i];
+ param->param_idx = CONF_SG_PARAMS_ALL;
ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
if (ret < 0) {
diff --git a/drivers/net/wireless/wl12xx/wl1271_acx.h b/drivers/net/wireless/wl12xx/wl1271_acx.h
index 88a05cb..dee3c06 100644
--- a/drivers/net/wireless/wl12xx/wl1271_acx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_acx.h
@@ -392,12 +392,6 @@ struct acx_conn_monit_params {
__le32 bss_lose_timeout; /* number of TU's from synch fail */
} __attribute__ ((packed));
-enum {
- ACX_SG_DISABLE = 0,
- ACX_SG_PROTECTIVE,
- ACX_SG_OPPORTUNISTIC
-};
-
struct acx_bt_wlan_coex {
struct acx_header header;
@@ -405,64 +399,10 @@ struct acx_bt_wlan_coex {
u8 pad[3];
} __attribute__ ((packed));
-enum {
- ACX_SG_BT_PER_THRESHOLD = 0,
- ACX_SG_HV3_MAX_OVERRIDE,
- ACX_SG_BT_NFS_SAMPLE_INTERVAL,
- ACX_SG_BT_LOAD_RATIO,
- ACX_SG_AUTO_PS_MODE,
- ACX_SG_AUTO_SCAN_PROBE_REQ,
- ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
- ACX_SG_ANTENNA_CONFIGURATION,
- ACX_SG_BEACON_MISS_PERCENT,
- ACX_SG_RATE_ADAPT_THRESH,
- ACX_SG_RATE_ADAPT_SNR,
- ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
- ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
- ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
- ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
- ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
- ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
- ACX_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
- ACX_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
- ACX_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
- ACX_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
- ACX_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
- ACX_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
- ACX_SG_RXT,
- ACX_SG_TXT,
- ACX_SG_ADAPTIVE_RXT_TXT,
- ACX_SG_PS_POLL_TIMEOUT,
- ACX_SG_UPSD_TIMEOUT,
- ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
- ACX_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
- ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR,
- ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
- ACX_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
- ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
- ACX_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
- ACX_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
- ACX_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
- ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
- ACX_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
- ACX_SG_PASSIVE_SCAN_A2DP_BT_TIME,
- ACX_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
- ACX_SG_HV3_MAX_SERVED,
- ACX_SG_DHCP_TIME,
- ACX_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
- ACX_SG_TEMP_PARAM_1,
- ACX_SG_TEMP_PARAM_2,
- ACX_SG_TEMP_PARAM_3,
- ACX_SG_TEMP_PARAM_4,
- ACX_SG_TEMP_PARAM_5,
- ACX_SG_PARAMS_MAX,
- ACX_SG_PARAMS_ALL = 0xff
-};
-
struct acx_bt_wlan_coex_param {
struct acx_header header;
- __le32 params[ACX_SG_PARAMS_MAX];
+ __le32 params[CONF_SG_PARAMS_MAX];
u8 param_idx;
u8 padding[3];
} __attribute__ ((packed));
diff --git a/drivers/net/wireless/wl12xx/wl1271_conf.h b/drivers/net/wireless/wl12xx/wl1271_conf.h
index 6f9e75c..7fcfe06 100644
--- a/drivers/net/wireless/wl12xx/wl1271_conf.h
+++ b/drivers/net/wireless/wl12xx/wl1271_conf.h
@@ -65,110 +65,318 @@ enum {
CONF_HW_RATE_INDEX_MAX = CONF_HW_RATE_INDEX_54MBPS,
};
-struct conf_sg_settings {
+enum {
+ CONF_SG_DISABLE = 0,
+ CONF_SG_PROTECTIVE,
+ CONF_SG_OPPORTUNISTIC
+};
+
+enum {
/*
- * Defines the PER threshold in PPM of the BT voice of which reaching
- * this value will trigger raising the priority of the BT voice by
- * the BT IP until next NFS sample interval time as defined in
- * nfs_sample_interval.
+ * PER threshold in PPM of the BT voice
*
- * Unit: PER value in PPM (parts per million)
- * #Error_packets / #Total_packets
+ * Range: 0 - 10000000
+ */
+ CONF_SG_BT_PER_THRESHOLD = 0,
- * Range: u32
+ /*
+ * Number of consequent RX_ACTIVE activities to override BT voice
+ * frames to ensure WLAN connection
+ *
+ * Range: 0 - 100
+ */
+ CONF_SG_HV3_MAX_OVERRIDE,
+
+ /*
+ * Defines the PER threshold of the BT voice
+ *
+ * Range: 0 - 65000
+ */
+ CONF_SG_BT_NFS_SAMPLE_INTERVAL,
+
+ /*
+ * Defines the load ratio of BT
+ *
+ * Range: 0 - 100 (%)
+ */
+ CONF_SG_BT_LOAD_RATIO,
+
+ /*
+ * Defines whether the SG will force WLAN host to enter/exit PSM
+ *
+ * Range: 1 - SG can force, 0 - host handles PSM
+ */
+ CONF_SG_AUTO_PS_MODE,
+
+ /*
+ * Compensation percentage of probe requests when scan initiated
+ * during BT voice/ACL link.
+ *
+ * Range: 0 - 255 (%)
+ */
+ CONF_SG_AUTO_SCAN_PROBE_REQ,
+
+ /*
+ * Compensation percentage of probe requests when active scan initiated
+ * during BT voice
+ *
+ * Range: 0 - 255 (%)
+ */
+ CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
+
+ /*
+ * Defines antenna configuration (single/dual antenna)
+ *
+ * Range: 0 - single antenna, 1 - dual antenna
+ */
+ CONF_SG_ANTENNA_CONFIGURATION,
+
+ /*
+ * The threshold (percent) of max consequtive beacon misses before
+ * increasing priority of beacon reception.
+ *
+ * Range: 0 - 100 (%)
+ */
+ CONF_SG_BEACON_MISS_PERCENT,
+
+ /*
+ * The rate threshold below which receiving a data frame from the AP
+ * will increase the priority of the data frame above BT traffic.
+ *
+ * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54
+ */
+ CONF_SG_RATE_ADAPT_THRESH,
+
+ /*
+ * Not used currently.
+ *
+ * Range: 0
+ */
+ CONF_SG_RATE_ADAPT_SNR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN PSM / BT master basic rate
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
+ CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
+
+ /*
+ * The time after it expires no new WLAN trigger frame is trasmitted
+ * in WLAN PSM / BT master basic rate
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN PSM / BT slave basic rate
+ *
+ * Range: 0 - 255 (ms)
*/
- u32 per_threshold;
+ CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
+ CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
/*
- * This value is an absolute time in micro-seconds to limit the
- * maximum scan duration compensation while in SG
+ * The time after it expires no new WLAN trigger frame is trasmitted
+ * in WLAN PSM / BT slave basic rate
+ *
+ * Range: 0 - 255 (ms)
*/
- u32 max_scan_compensation_time;
+ CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
- /* Defines the PER threshold of the BT voice of which reaching this
- * value will trigger raising the priority of the BT voice until next
- * NFS sample interval time as defined in sample_interval.
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN PSM / BT master EDR
*
- * Unit: msec
- * Range: 1-65000
+ * Range: 0 - 255 (ms)
*/
- u16 nfs_sample_interval;
+ CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
+ CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
/*
- * Defines the load ratio for the BT.
- * The WLAN ratio is: 100 - load_ratio
+ * The time after it expires no new WLAN trigger frame is trasmitted
+ * in WLAN PSM / BT master EDR
*
- * Unit: Percent
- * Range: 0-100
+ * Range: 0 - 255 (ms)
*/
- u8 load_ratio;
+ CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
/*
- * true - Co-ex is allowed to enter/exit P.S automatically and
- * transparently to the host
+ * Configure the min and max time BT gains the antenna
+ * in WLAN PSM / BT slave EDR
*
- * false - Co-ex is disallowed to enter/exit P.S and will trigger an
- * event to the host to notify for the need to enter/exit P.S
- * due to BT change state
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
+ CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
+
+ /*
+ * The time after it expires no new WLAN trigger frame is trasmitted
+ * in WLAN PSM / BT slave EDR
*
+ * Range: 0 - 255 (ms)
*/
- u8 auto_ps_mode;
+ CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
/*
- * This parameter defines the compensation percentage of num of probe
- * requests in case scan is initiated during BT voice/BT ACL
- * guaranteed link.
+ * RX guard time before the beginning of a new BT voice frame during
+ * which no new WLAN trigger frame is transmitted.
*
- * Unit: Percent
- * Range: 0-255 (0 - No compensation)
+ * Range: 0 - 100000 (us)
*/
- u8 probe_req_compensation;
+ CONF_SG_RXT,
/*
- * This parameter defines the compensation percentage of scan window
- * size in case scan is initiated during BT voice/BT ACL Guaranteed
- * link.
+ * TX guard time before the beginning of a new BT voice frame during
+ * which no new WLAN frame is transmitted.
*
- * Unit: Percent
- * Range: 0-255 (0 - No compensation)
+ * Range: 0 - 100000 (us)
*/
- u8 scan_window_compensation;
+
+ CONF_SG_TXT,
/*
- * Defines the antenna configuration.
+ * Enable adaptive RXT/TXT algorithm. If disabled, the host values
+ * will be utilized.
*
- * Range: 0 - Single Antenna; 1 - Dual Antenna
+ * Range: 0 - disable, 1 - enable
*/
- u8 antenna_config;
+ CONF_SG_ADAPTIVE_RXT_TXT,
/*
- * The percent out of the Max consecutive beacon miss roaming trigger
- * which is the threshold for raising the priority of beacon
- * reception.
+ * The used WLAN legacy service period during active BT ACL link
*
- * Range: 1-100
- * N = MaxConsecutiveBeaconMiss
- * P = coexMaxConsecutiveBeaconMissPrecent
- * Threshold = MIN( N-1, round(N * P / 100))
+ * Range: 0 - 255 (ms)
*/
- u8 beacon_miss_threshold;
+ CONF_SG_PS_POLL_TIMEOUT,
/*
- * The RX rate threshold below which rate adaptation is assumed to be
- * occurring at the AP which will raise priority for ACTIVE_RX and RX
- * SP.
+ * The used WLAN UPSD service period during active BT ACL link
*
- * Range: HW_BIT_RATE_*
+ * Range: 0 - 255 (ms)
*/
- u32 rate_adaptation_threshold;
+ CONF_SG_UPSD_TIMEOUT,
/*
- * The SNR above which the RX rate threshold indicating AP rate
- * adaptation is valid
+ * Configure the min and max time BT gains the antenna
+ * in WLAN Active / BT master EDR
*
- * Range: -128 - 127
+ * Range: 0 - 255 (ms)
*/
- s8 rate_adaptation_snr;
+ CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
+ CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
+
+ /*
+ * The maximum time WLAN can gain the antenna for
+ * in WLAN Active / BT master EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN Active / BT slave EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
+ CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
+
+ /*
+ * The maximum time WLAN can gain the antenna for
+ * in WLAN Active / BT slave EDR
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
+
+ /*
+ * Configure the min and max time BT gains the antenna
+ * in WLAN Active / BT basic rate
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
+ CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
+
+ /*
+ * The maximum time WLAN can gain the antenna for
+ * in WLAN Active / BT basic rate
+ *
+ * Range: 0 - 255 (ms)
+ */
+ CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
+
+ /*
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT voice
+ *
+ * Range: 0 - 1000 (%)
+ */
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
+
+ /*
+ * Compensation percentage of WLAN passive scan window if initiated
+ * during BT A2DP
+ *
+ * Range: 0 - 1000 (%)
+ */
+ CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
+
+ /*
+ * Fixed time ensured for BT traffic to gain the antenna during WLAN
+ * passive scan.
+ *
+ * Range: 0 - 1000 ms
+ */
+ CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME,
+
+ /*
+ * Fixed time ensured for WLAN traffic to gain the antenna during WLAN
+ * passive scan.
+ *
+ * Range: 0 - 1000 ms
+ */
+ CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
+
+ /*
+ * Number of consequent BT voice frames not interrupted by WLAN
+ *
+ * Range: 0 - 100
+ */
+ CONF_SG_HV3_MAX_SERVED,
+
+ /*
+ * Protection time of the DHCP procedure.
+ *
+ * Range: 0 - 100000 (ms)
+ */
+ CONF_SG_DHCP_TIME,
+
+ /*
+ * Compensation percentage of WLAN active scan window if initiated
+ * during BT A2DP
+ *
+ * Range: 0 - 1000 (%)
+ */
+ CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
+ CONF_SG_TEMP_PARAM_1,
+ CONF_SG_TEMP_PARAM_2,
+ CONF_SG_TEMP_PARAM_3,
+ CONF_SG_TEMP_PARAM_4,
+ CONF_SG_TEMP_PARAM_5,
+ CONF_SG_PARAMS_MAX,
+ CONF_SG_PARAMS_ALL = 0xff
+};
+
+struct conf_sg_settings {
+ __le32 params[CONF_SG_PARAMS_MAX];
+ u8 state;
};
enum conf_rx_queue_type {
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 86c30a8..d68445c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -160,11 +160,11 @@ int wl1271_init_pta(struct wl1271 *wl)
{
int ret;
- ret = wl1271_acx_sg_enable(wl);
+ ret = wl1271_acx_sg_cfg(wl);
if (ret < 0)
return ret;
- ret = wl1271_acx_sg_cfg(wl);
+ ret = wl1271_acx_sg_enable(wl);
if (ret < 0)
return ret;
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index b3abb45..6501d6e 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -48,17 +48,57 @@
static struct conf_drv_settings default_conf = {
.sg = {
- .per_threshold = 7500,
- .max_scan_compensation_time = 120000,
- .nfs_sample_interval = 400,
- .load_ratio = 50,
- .auto_ps_mode = 0,
- .probe_req_compensation = 170,
- .scan_window_compensation = 50,
- .antenna_config = 0,
- .beacon_miss_threshold = 60,
- .rate_adaptation_threshold = CONF_HW_BIT_RATE_12MBPS,
- .rate_adaptation_snr = 0
+ .params = {
+ [CONF_SG_BT_PER_THRESHOLD] = 7500,
+ [CONF_SG_HV3_MAX_OVERRIDE] = 0,
+ [CONF_SG_BT_NFS_SAMPLE_INTERVAL] = 400,
+ [CONF_SG_BT_LOAD_RATIO] = 50,
+ [CONF_SG_AUTO_PS_MODE] = 0,
+ [CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+ [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+ [CONF_SG_ANTENNA_CONFIGURATION] = 0,
+ [CONF_SG_BEACON_MISS_PERCENT] = 60,
+ [CONF_SG_RATE_ADAPT_THRESH] = 12,
+ [CONF_SG_RATE_ADAPT_SNR] = 0,
+ [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR] = 10,
+ [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR] = 30,
+ [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR] = 8,
+ [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR] = 20,
+ [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR] = 50,
+ /* Note: with UPSD, this should be 4 */
+ [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR] = 8,
+ [CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR] = 7,
+ [CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR] = 25,
+ [CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR] = 20,
+ /* Note: with UPDS, this should be 15 */
+ [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR] = 8,
+ /* Note: with UPDS, this should be 50 */
+ [CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR] = 40,
+ /* Note: with UPDS, this should be 10 */
+ [CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR] = 20,
+ [CONF_SG_RXT] = 1200,
+ [CONF_SG_TXT] = 1000,
+ [CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+ [CONF_SG_PS_POLL_TIMEOUT] = 10,
+ [CONF_SG_UPSD_TIMEOUT] = 10,
+ [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
+ [CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
+ [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
+ [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR] = 8,
+ [CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR] = 20,
+ [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR] = 15,
+ [CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR] = 20,
+ [CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR] = 50,
+ [CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR] = 10,
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+ [CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
+ [CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME] = 75,
+ [CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME] = 15,
+ [CONF_SG_HV3_MAX_SERVED] = 6,
+ [CONF_SG_DHCP_TIME] = 5000,
+ [CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
+ },
+ .state = CONF_SG_PROTECTIVE,
},
.rx = {
.rx_msdu_life_time = 512000,
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
This patch fixes MAC address handling. To achieve this, firmware booting had
to be delayed from the previous op_start to op_add_interface, which is the point
when the driver gets to know the configured MAC address. As the wl1271 only
supports one virtual interface, this even seems quite logical.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_boot.c | 8 ++
drivers/net/wireless/wl12xx/wl1271_main.c | 149 ++++++++++++-----------------
2 files changed, 68 insertions(+), 89 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_boot.c b/drivers/net/wireless/wl12xx/wl1271_boot.c
index f88d52e..41c6aff 100644
--- a/drivers/net/wireless/wl12xx/wl1271_boot.c
+++ b/drivers/net/wireless/wl12xx/wl1271_boot.c
@@ -228,6 +228,14 @@ static int wl1271_boot_upload_nvs(struct wl1271 *wl)
nvs_len = sizeof(wl->nvs->nvs);
nvs_ptr = (u8 *)wl->nvs->nvs;
+ /* update current MAC address to NVS */
+ nvs_ptr[11] = wl->mac_addr[0];
+ nvs_ptr[10] = wl->mac_addr[1];
+ nvs_ptr[6] = wl->mac_addr[2];
+ nvs_ptr[5] = wl->mac_addr[3];
+ nvs_ptr[4] = wl->mac_addr[4];
+ nvs_ptr[3] = wl->mac_addr[5];
+
/*
* Layout before the actual NVS tables:
* 1 byte : burst length.
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 037a4f4..d8cb514 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -570,40 +570,6 @@ out:
return ret;
}
-static int wl1271_update_mac_addr(struct wl1271 *wl)
-{
- int ret = 0;
- u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
-
- /* get mac address from the NVS */
- wl->mac_addr[0] = nvs_ptr[11];
- wl->mac_addr[1] = nvs_ptr[10];
- wl->mac_addr[2] = nvs_ptr[6];
- wl->mac_addr[3] = nvs_ptr[5];
- wl->mac_addr[4] = nvs_ptr[4];
- wl->mac_addr[5] = nvs_ptr[3];
-
- /* FIXME: if it is a zero-address, we should bail out. Now, instead,
- we randomize an address */
- if (is_zero_ether_addr(wl->mac_addr)) {
- static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
- memcpy(wl->mac_addr, nokia_oui, 3);
- get_random_bytes(wl->mac_addr + 3, 3);
-
- /* update this address to the NVS */
- nvs_ptr[11] = wl->mac_addr[0];
- nvs_ptr[10] = wl->mac_addr[1];
- nvs_ptr[6] = wl->mac_addr[2];
- nvs_ptr[5] = wl->mac_addr[3];
- nvs_ptr[4] = wl->mac_addr[4];
- nvs_ptr[3] = wl->mac_addr[5];
- }
-
- SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
-
- return ret;
-}
-
static int wl1271_fetch_nvs(struct wl1271 *wl)
{
const struct firmware *fw;
@@ -633,8 +599,6 @@ static int wl1271_fetch_nvs(struct wl1271 *wl)
memcpy(wl->nvs, fw->data, sizeof(struct wl1271_nvs_file));
- ret = wl1271_update_mac_addr(wl);
-
out:
release_firmware(fw);
@@ -952,13 +916,58 @@ static struct notifier_block wl1271_dev_notifier = {
static int wl1271_op_start(struct ieee80211_hw *hw)
{
+ wl1271_debug(DEBUG_MAC80211, "mac80211 start");
+
+ /*
+ * We have to delay the booting of the hardware because
+ * we need to know the local MAC address before downloading and
+ * initializing the firmware. The MAC address cannot be changed
+ * after boot, and without the proper MAC address, the firmware
+ * will not function properly.
+ *
+ * The MAC address is first known when the corresponding interface
+ * is added. That is where we will initialize the hardware.
+ */
+
+ return 0;
+}
+
+static void wl1271_op_stop(struct ieee80211_hw *hw)
+{
+ wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
+}
+
+static int wl1271_op_add_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
+{
struct wl1271 *wl = hw->priv;
int retries = WL1271_BOOT_RETRIES;
int ret = 0;
- wl1271_debug(DEBUG_MAC80211, "mac80211 start");
+ wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
+ vif->type, vif->addr);
mutex_lock(&wl->mutex);
+ if (wl->vif) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ wl->vif = vif;
+
+ switch (vif->type) {
+ case NL80211_IFTYPE_STATION:
+ wl->bss_type = BSS_TYPE_STA_BSS;
+ break;
+ case NL80211_IFTYPE_ADHOC:
+ wl->bss_type = BSS_TYPE_IBSS;
+ break;
+ default:
+ ret = -EOPNOTSUPP;
+ goto out;
+ }
+
+ memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
if (wl->state != WL1271_STATE_OFF) {
wl1271_error("cannot start because not in off state: %d",
@@ -1014,20 +1023,20 @@ out:
return ret;
}
-static void wl1271_op_stop(struct ieee80211_hw *hw)
+static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif)
{
struct wl1271 *wl = hw->priv;
int i;
- wl1271_info("down");
+ mutex_lock(&wl->mutex);
+ wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
- wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
+ wl1271_info("down");
unregister_inetaddr_notifier(&wl1271_dev_notifier);
list_del(&wl->list);
- mutex_lock(&wl->mutex);
-
WARN_ON(wl->state != WL1271_STATE_ON);
if (test_and_clear_bit(WL1271_FLAG_SCANNING, &wl->flags)) {
@@ -1070,6 +1079,7 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
wl->rate_set = CONF_TX_RATE_MASK_BASIC;
wl->sta_rate_set = 0;
wl->flags = 0;
+ wl->vif = NULL;
for (i = 0; i < NUM_TX_QUEUES; i++)
wl->tx_blocks_freed[i] = 0;
@@ -1078,53 +1088,6 @@ static void wl1271_op_stop(struct ieee80211_hw *hw)
mutex_unlock(&wl->mutex);
}
-static int wl1271_op_add_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct wl1271 *wl = hw->priv;
- int ret = 0;
-
- wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
- vif->type, vif->addr);
-
- mutex_lock(&wl->mutex);
- if (wl->vif) {
- ret = -EBUSY;
- goto out;
- }
-
- wl->vif = vif;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- wl->bss_type = BSS_TYPE_STA_BSS;
- break;
- case NL80211_IFTYPE_ADHOC:
- wl->bss_type = BSS_TYPE_IBSS;
- break;
- default:
- ret = -EOPNOTSUPP;
- goto out;
- }
-
- /* FIXME: what if conf->mac_addr changes? */
-
-out:
- mutex_unlock(&wl->mutex);
- return ret;
-}
-
-static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct wl1271 *wl = hw->priv;
-
- mutex_lock(&wl->mutex);
- wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
- wl->vif = NULL;
- mutex_unlock(&wl->mutex);
-}
-
#if 0
static int wl1271_op_config_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -2114,6 +2077,7 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
struct ieee80211_hw *hw;
struct wl1271 *wl;
int i, ret;
+ static const u8 nokia_oui[3] = {0x00, 0x1f, 0xdf};
hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
if (!hw) {
@@ -2155,6 +2119,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
wl->state = WL1271_STATE_OFF;
mutex_init(&wl->mutex);
+ /*
+ * FIXME: we should use a zero MAC address here, but for now we
+ * generate a random Nokia address.
+ */
+ memcpy(wl->mac_addr, nokia_oui, 3);
+ get_random_bytes(wl->mac_addr + 3, 3);
+
/* Apply default driver configuration. */
wl1271_conf_init(wl);
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
Removing the wl1271 from the inet addr notifier chain sometimes causes the
registered handler to be called - causing locking problems if the removing
function is called from within the mutex.
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 | 3 ++-
1 files changed, 2 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 6f6d366..0bebc45 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1029,12 +1029,13 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
struct wl1271 *wl = hw->priv;
int i;
+ unregister_inetaddr_notifier(&wl1271_dev_notifier);
+
mutex_lock(&wl->mutex);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
wl1271_info("down");
- unregister_inetaddr_notifier(&wl1271_dev_notifier);
list_del(&wl->list);
WARN_ON(wl->state != WL1271_STATE_ON);
--
1.6.3.3
From: Kalle Valo <[email protected]>
mac80211 now can create pspoll and nullfunc templates, better to use those.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 44 +++++++++++++----------------
1 files changed, 20 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index d59b383..3a615fa 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -776,41 +776,37 @@ static int wl1271_build_extended_rates(u8 *rates, u8 band)
int wl1271_cmd_build_null_data(struct wl1271 *wl)
{
- struct wl12xx_null_data_template template;
+ struct sk_buff *skb;
+ int ret = 0;
- if (!is_zero_ether_addr(wl->bssid)) {
- memcpy(template.header.da, wl->bssid, ETH_ALEN);
- memcpy(template.header.bssid, wl->bssid, ETH_ALEN);
- } else {
- memset(template.header.da, 0xff, ETH_ALEN);
- memset(template.header.bssid, 0xff, ETH_ALEN);
- }
+ skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
+ if (!skb)
+ goto out;
- memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
- template.header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_DATA |
- IEEE80211_STYPE_NULLFUNC |
- IEEE80211_FCTL_TODS);
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, skb->data,
+ skb->len);
- return wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, &template,
- sizeof(template));
+out:
+ dev_kfree_skb(skb);
+ return ret;
}
int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid)
{
- struct wl12xx_ps_poll_template template;
-
- memcpy(template.bssid, wl->bssid, ETH_ALEN);
- memcpy(template.ta, wl->mac_addr, ETH_ALEN);
-
- /* aid in PS-Poll has its two MSBs each set to 1 */
- template.aid = cpu_to_le16(1 << 15 | 1 << 14 | aid);
+ struct sk_buff *skb;
+ int ret = 0;
- template.fc = cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_PSPOLL);
+ skb = ieee80211_pspoll_get(wl->hw, wl->vif);
+ if (!skb)
+ goto out;
- return wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, &template,
- sizeof(template));
+ ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PS_POLL, skb->data,
+ skb->len);
+out:
+ dev_kfree_skb(skb);
+ return ret;
}
int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len,
--
1.6.3.3
From: Juuso Oikarinen <[email protected]>
It's no longer needed.
Signed-off-by: Juuso Oikarinen <[email protected]>
Reviewed-by: Kalle Valo <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 68 -----------------------------
1 files changed, 0 insertions(+), 68 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d8cb514..688009b 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1088,73 +1088,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-#if 0
-static int wl1271_op_config_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_if_conf *conf)
-{
- struct wl1271 *wl = hw->priv;
- struct sk_buff *beacon;
- int ret;
-
- wl1271_debug(DEBUG_MAC80211, "mac80211 config_interface bssid %pM",
- conf->bssid);
- wl1271_dump_ascii(DEBUG_MAC80211, "ssid: ", conf->ssid,
- conf->ssid_len);
-
- mutex_lock(&wl->mutex);
-
- ret = wl1271_ps_elp_wakeup(wl, false);
- if (ret < 0)
- goto out;
-
- if (memcmp(wl->bssid, conf->bssid, ETH_ALEN)) {
- wl1271_debug(DEBUG_MAC80211, "bssid changed");
-
- memcpy(wl->bssid, conf->bssid, ETH_ALEN);
-
- ret = wl1271_cmd_join(wl, wl->bss_type);
- if (ret < 0)
- goto out_sleep;
-
- ret = wl1271_cmd_build_null_data(wl);
- if (ret < 0)
- goto out_sleep;
- }
-
- wl->ssid_len = conf->ssid_len;
- if (wl->ssid_len)
- memcpy(wl->ssid, conf->ssid, wl->ssid_len);
-
- if (conf->changed & IEEE80211_IFCC_BEACON) {
- beacon = ieee80211_beacon_get(hw, vif);
- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
- beacon->data, beacon->len);
-
- if (ret < 0) {
- dev_kfree_skb(beacon);
- goto out_sleep;
- }
-
- ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE,
- beacon->data, beacon->len);
-
- dev_kfree_skb(beacon);
-
- if (ret < 0)
- goto out_sleep;
- }
-
-out_sleep:
- wl1271_ps_elp_sleep(wl);
-
-out:
- mutex_unlock(&wl->mutex);
-
- return ret;
-}
-#endif
-
static int wl1271_join_channel(struct wl1271 *wl, int channel)
{
int ret = 0;
@@ -1940,7 +1873,6 @@ static const struct ieee80211_ops wl1271_ops = {
.add_interface = wl1271_op_add_interface,
.remove_interface = wl1271_op_remove_interface,
.config = wl1271_op_config,
-/* .config_interface = wl1271_op_config_interface, */
.prepare_multicast = wl1271_op_prepare_multicast,
.configure_filter = wl1271_op_configure_filter,
.tx = wl1271_op_tx,
--
1.6.3.3
From: Kalle Valo <[email protected]>
Commit "wl1271: implement WMM" accidentally used CONF_PS_SCHEME_LEGACY_PSPOLL,
but instead CONF_PS_SCHEME_LEGACY should be used as earlier.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index fbc42ce..2a2e584 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1801,7 +1801,7 @@ static int wl1271_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
CONF_CHANNEL_TYPE_EDCF,
wl1271_tx_get_queue(queue),
- CONF_PS_SCHEME_LEGACY_PSPOLL,
+ CONF_PS_SCHEME_LEGACY,
CONF_ACK_POLICY_LEGACY, 0, 0);
if (ret < 0)
goto out_sleep;
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Removed duplicate code from wl1271_sdio module remove function. For
freeing stuff in the remove function wl1271_free_hw function is now
used.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 13 +------------
1 files changed, 1 insertions(+), 12 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 0478919..99b5b3f 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -248,20 +248,9 @@ static void __devexit wl1271_remove(struct sdio_func *func)
{
struct wl1271 *wl = sdio_get_drvdata(func);
- ieee80211_unregister_hw(wl->hw);
-
free_irq(wl->irq, wl);
- kfree(wl->target_mem_map);
- vfree(wl->fw);
- wl->fw = NULL;
- kfree(wl->nvs);
- wl->nvs = NULL;
-
- kfree(wl->fw_status);
- kfree(wl->tx_res_if);
-
- ieee80211_free_hw(wl->hw);
+ wl1271_free_hw(wl);
}
static struct sdio_driver wl1271_sdio_driver = {
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Added method for wlan power control to io_ops struct and moved
wl1271_power_on and wl1271_power_off functions to wl1271_io.h.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271.h | 1 +
drivers/net/wireless/wl12xx/wl1271_debugfs.c | 12 +++++-------
drivers/net/wireless/wl12xx/wl1271_io.h | 12 ++++++++++++
drivers/net/wireless/wl12xx/wl1271_main.c | 12 ------------
drivers/net/wireless/wl12xx/wl1271_sdio.c | 11 +++++------
drivers/net/wireless/wl12xx/wl1271_spi.c | 7 +++++++
6 files changed, 30 insertions(+), 25 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271.h b/drivers/net/wireless/wl12xx/wl1271.h
index 0deb4fd..7397999 100644
--- a/drivers/net/wireless/wl12xx/wl1271.h
+++ b/drivers/net/wireless/wl12xx/wl1271.h
@@ -344,6 +344,7 @@ struct wl1271_if_operations {
bool fixed);
void (*reset)(struct wl1271 *wl);
void (*init)(struct wl1271 *wl);
+ void (*power)(struct wl1271 *wl, bool enable);
struct device* (*dev)(struct wl1271 *wl);
void (*enable_irq)(struct wl1271 *wl);
void (*disable_irq)(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/wl1271_debugfs.c b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
index 8d7588c..3c0f5b1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_debugfs.c
+++ b/drivers/net/wireless/wl12xx/wl1271_debugfs.c
@@ -28,6 +28,7 @@
#include "wl1271.h"
#include "wl1271_acx.h"
#include "wl1271_ps.h"
+#include "wl1271_io.h"
/* ms */
#define WL1271_DEBUGFS_STATS_LIFETIME 1000
@@ -276,13 +277,10 @@ static ssize_t gpio_power_write(struct file *file,
goto out;
}
- if (value) {
- wl->set_power(true);
- set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
- } else {
- wl->set_power(false);
- clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
- }
+ if (value)
+ wl1271_power_on(wl);
+ else
+ wl1271_power_off(wl);
out:
mutex_unlock(&wl->mutex);
diff --git a/drivers/net/wireless/wl12xx/wl1271_io.h b/drivers/net/wireless/wl12xx/wl1271_io.h
index 95d2168..3ff88d9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_io.h
+++ b/drivers/net/wireless/wl12xx/wl1271_io.h
@@ -138,6 +138,18 @@ static inline void wl1271_write32(struct wl1271 *wl, int addr, u32 val)
wl1271_raw_write32(wl, wl1271_translate_addr(wl, addr), val);
}
+static inline void wl1271_power_off(struct wl1271 *wl)
+{
+ wl->if_ops->power(wl, false);
+ clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+}
+
+static inline void wl1271_power_on(struct wl1271 *wl)
+{
+ wl->if_ops->power(wl, true);
+ set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
+}
+
/* Top Register IO */
void wl1271_top_reg_write(struct wl1271 *wl, int addr, u16 val);
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 0de337f..b3abb45 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -359,18 +359,6 @@ static int wl1271_plt_init(struct wl1271 *wl)
return ret;
}
-static void wl1271_power_off(struct wl1271 *wl)
-{
- wl->set_power(false);
- clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
-}
-
-static void wl1271_power_on(struct wl1271 *wl)
-{
- wl->set_power(true);
- set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
-}
-
static void wl1271_fw_status(struct wl1271 *wl,
struct wl1271_fw_status *status)
{
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index 1f204db..d43e0d4 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -156,20 +156,21 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
sdio_release_host(func);
}
+static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
+{
+}
+
static struct wl1271_if_operations sdio_ops = {
.read = wl1271_sdio_raw_read,
.write = wl1271_sdio_raw_write,
.reset = wl1271_sdio_reset,
.init = wl1271_sdio_init,
+ .power = wl1271_sdio_set_power,
.dev = wl1271_sdio_wl_to_dev,
.enable_irq = wl1271_sdio_enable_interrupts,
.disable_irq = wl1271_sdio_disable_interrupts
};
-static void wl1271_sdio_set_power(bool enable)
-{
-}
-
static int __devinit wl1271_probe(struct sdio_func *func,
const struct sdio_device_id *id)
{
@@ -190,8 +191,6 @@ static int __devinit wl1271_probe(struct sdio_func *func,
wl->if_priv = func;
wl->if_ops = &sdio_ops;
- wl->set_power = wl1271_sdio_set_power;
-
/* Grab access to FN0 for ELP reg. */
func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_spi.c b/drivers/net/wireless/wl12xx/wl1271_spi.c
index ed285fe..0eea733 100644
--- a/drivers/net/wireless/wl12xx/wl1271_spi.c
+++ b/drivers/net/wireless/wl12xx/wl1271_spi.c
@@ -347,11 +347,18 @@ static struct platform_device wl1271_device = {
},
};
+static void wl1271_spi_set_power(struct wl1271 *wl, bool enable)
+{
+ if (wl->set_power)
+ wl->set_power(enable);
+}
+
static struct wl1271_if_operations spi_ops = {
.read = wl1271_spi_raw_read,
.write = wl1271_spi_raw_write,
.reset = wl1271_spi_reset,
.init = wl1271_spi_init,
+ .power = wl1271_spi_set_power,
.dev = wl1271_spi_wl_to_dev,
.enable_irq = wl1271_spi_enable_interrupts,
.disable_irq = wl1271_spi_disable_interrupts
--
1.6.3.3
From: Kalle Valo <[email protected]>
Everything is ready now and we can enable WMM in wl1271.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_main.c | 2 ++
drivers/net/wireless/wl12xx/wl1271_tx.h | 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 abf9f22..d21bfe2 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -2091,6 +2091,8 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
if (wl1271_11a_enabled())
wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
+ wl->hw->queues = 4;
+
SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
return 0;
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.h b/drivers/net/wireless/wl12xx/wl1271_tx.h
index 8b9f6b4..5e6c27a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.h
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.h
@@ -125,9 +125,6 @@ struct wl1271_tx_hw_res_if {
static inline int wl1271_tx_get_queue(int queue)
{
- /* FIXME: use best effort until WMM is enabled */
- return CONF_TX_AC_BE;
-
switch (queue) {
case 0:
return CONF_TX_AC_VO;
--
1.6.3.3
From: Kalle Valo <[email protected]>
Needed for U-APSD.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 22 ++++++++++++++++++++++
drivers/net/wireless/wl12xx/wl1271_cmd.h | 1 +
2 files changed, 23 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 8364270..0cbb0e1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -26,6 +26,7 @@
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/etherdevice.h>
+#include <linux/ieee80211.h>
#include "wl1271.h"
#include "wl1271_reg.h"
@@ -778,6 +779,27 @@ out:
return ret;
}
+int wl1271_build_qos_null_data(struct wl1271 *wl)
+{
+ struct ieee80211_qos_hdr template;
+
+ memset(&template, 0, sizeof(template));
+
+ memcpy(template.addr1, wl->bssid, ETH_ALEN);
+ memcpy(template.addr2, wl->mac_addr, ETH_ALEN);
+ memcpy(template.addr3, wl->bssid, ETH_ALEN);
+
+ template.frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+ IEEE80211_STYPE_QOS_NULLFUNC |
+ IEEE80211_FCTL_TODS);
+
+ /* FIXME: not sure what priority to use here */
+ template.qos_ctrl = cpu_to_le16(0);
+
+ return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
+ sizeof(template));
+}
+
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
{
struct wl1271_cmd_set_keys *cmd;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index e936d3a..6324bbf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -51,6 +51,7 @@ int wl1271_cmd_build_ps_poll(struct wl1271 *wl, u16 aid);
int wl1271_cmd_build_probe_req(struct wl1271 *wl,
const u8 *ssid, size_t ssid_len,
const u8 *ie, size_t ie_len, u8 band);
+int wl1271_build_qos_null_data(struct wl1271 *wl);
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
--
1.6.3.3
From: Teemu Paasikivi <[email protected]>
Changed driver to keep MMC host claimed while wlan interface is up.
This keeps MMC stack from powering the SDIO device down.
Signed-off-by: Teemu Paasikivi <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_sdio.c | 27 +++++++++------------------
1 files changed, 9 insertions(+), 18 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_sdio.c b/drivers/net/wireless/wl12xx/wl1271_sdio.c
index d43e0d4..d9183b6 100644
--- a/drivers/net/wireless/wl12xx/wl1271_sdio.c
+++ b/drivers/net/wireless/wl12xx/wl1271_sdio.c
@@ -107,7 +107,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
int ret;
struct sdio_func *func = wl_to_func(wl);
- sdio_claim_host(func);
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
wl1271_debug(DEBUG_SPI, "sdio read 52 addr 0x%x, byte 0x%02x",
@@ -126,7 +125,6 @@ static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
if (ret)
wl1271_error("sdio read failed (%d)", ret);
- sdio_release_host(func);
}
static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
@@ -135,7 +133,6 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
int ret;
struct sdio_func *func = wl_to_func(wl);
- sdio_claim_host(func);
if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
wl1271_debug(DEBUG_SPI, "sdio write 52 addr 0x%x, byte 0x%02x",
@@ -153,11 +150,19 @@ static void wl1271_sdio_raw_write(struct wl1271 *wl, int addr, void *buf,
if (ret)
wl1271_error("sdio write failed (%d)", ret);
- sdio_release_host(func);
}
static void wl1271_sdio_set_power(struct wl1271 *wl, bool enable)
{
+ struct sdio_func *func = wl_to_func(wl);
+
+ if (enable) {
+ sdio_claim_host(func);
+ sdio_enable_func(func);
+ } else {
+ sdio_disable_func(func);
+ sdio_release_host(func);
+ }
}
static struct wl1271_if_operations sdio_ops = {
@@ -219,22 +224,12 @@ static int __devinit wl1271_probe(struct sdio_func *func,
if (ret)
goto out_irq;
- sdio_claim_host(func);
sdio_set_drvdata(func, wl);
- ret = sdio_enable_func(func);
- if (ret)
- goto out_release;
-
- sdio_release_host(func);
-
wl1271_notice("initialized");
return 0;
- out_release:
- sdio_release_host(func);
-
out_irq:
free_irq(wl->irq, wl);
@@ -251,10 +246,6 @@ static void __devexit wl1271_remove(struct sdio_func *func)
ieee80211_unregister_hw(wl->hw);
- sdio_claim_host(func);
- sdio_disable_func(func);
- sdio_release_host(func);
-
free_irq(wl->irq, wl);
kfree(wl->target_mem_map);
--
1.6.3.3
From: Kalle Valo <[email protected]>
If we get probe request from mac80211, we can remove two functions.
Signed-off-by: Kalle Valo <[email protected]>
Reviewed-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Juuso Oikarinen <[email protected]>
Signed-off-by: Luciano Coelho <[email protected]>
---
drivers/net/wireless/wl12xx/wl1271_cmd.c | 137 ++++++----------------------
drivers/net/wireless/wl12xx/wl1271_cmd.h | 11 +-
drivers/net/wireless/wl12xx/wl1271_event.c | 2 +
drivers/net/wireless/wl12xx/wl1271_main.c | 6 +-
4 files changed, 40 insertions(+), 116 deletions(-)
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 3a615fa..8364270 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -546,9 +546,9 @@ out:
return ret;
}
-int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
- u8 active_scan, u8 high_prio, u8 band,
- u8 probe_requests)
+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)
{
struct wl1271_cmd_trigger_scan_to *trigger = NULL;
@@ -619,12 +619,13 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
params->params.num_channels = j;
- if (len && ssid) {
- params->params.ssid_len = len;
- memcpy(params->params.ssid, ssid, len);
+ if (ssid_len && ssid) {
+ params->params.ssid_len = ssid_len;
+ memcpy(params->params.ssid, ssid, ssid_len);
}
- ret = wl1271_cmd_build_probe_req(wl, ssid, len, ieee_band);
+ ret = wl1271_cmd_build_probe_req(wl, ssid, ssid_len,
+ ie, ie_len, ieee_band);
if (ret < 0) {
wl1271_error("PROBE request template failed");
goto out;
@@ -655,9 +656,9 @@ int wl1271_cmd_scan(struct wl1271 *wl, u8 *ssid, size_t len,
wl->scan.active = active_scan;
wl->scan.high_prio = high_prio;
wl->scan.probe_requests = probe_requests;
- if (len && ssid) {
- wl->scan.ssid_len = len;
- memcpy(wl->scan.ssid, ssid, len);
+ if (ssid_len && ssid) {
+ wl->scan.ssid_len = ssid_len;
+ memcpy(wl->scan.ssid, ssid, ssid_len);
} else
wl->scan.ssid_len = 0;
}
@@ -714,66 +715,6 @@ out:
return ret;
}
-static int wl1271_build_basic_rates(u8 *rates, u8 band)
-{
- u8 index = 0;
-
- if (band == IEEE80211_BAND_2GHZ) {
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_1MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_2MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_5MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_CCK_RATE_11MB;
- } else if (band == IEEE80211_BAND_5GHZ) {
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_6MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_12MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
- } else {
- wl1271_error("build_basic_rates invalid band: %d", band);
- }
-
- return index;
-}
-
-static int wl1271_build_extended_rates(u8 *rates, u8 band)
-{
- u8 index = 0;
-
- if (band == IEEE80211_BAND_2GHZ) {
- rates[index++] = IEEE80211_OFDM_RATE_6MB;
- rates[index++] = IEEE80211_OFDM_RATE_9MB;
- rates[index++] = IEEE80211_OFDM_RATE_12MB;
- rates[index++] = IEEE80211_OFDM_RATE_18MB;
- rates[index++] = IEEE80211_OFDM_RATE_24MB;
- rates[index++] = IEEE80211_OFDM_RATE_36MB;
- rates[index++] = IEEE80211_OFDM_RATE_48MB;
- rates[index++] = IEEE80211_OFDM_RATE_54MB;
- } else if (band == IEEE80211_BAND_5GHZ) {
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_9MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_18MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_24MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_36MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_48MB;
- rates[index++] =
- IEEE80211_BASIC_RATE_MASK | IEEE80211_OFDM_RATE_54MB;
- } else {
- wl1271_error("build_basic_rates invalid band: %d", band);
- }
-
- return index;
-}
-
int wl1271_cmd_build_null_data(struct wl1271 *wl)
{
struct sk_buff *skb;
@@ -809,53 +750,31 @@ out:
return ret;
}
-int wl1271_cmd_build_probe_req(struct wl1271 *wl, u8 *ssid, size_t ssid_len,
- u8 band)
+int wl1271_cmd_build_probe_req(struct wl1271 *wl,
+ const u8 *ssid, size_t ssid_len,
+ const u8 *ie, size_t ie_len, u8 band)
{
- struct wl12xx_probe_req_template template;
- struct wl12xx_ie_rates *rates;
- char *ptr;
- u16 size;
+ struct sk_buff *skb;
int ret;
- ptr = (char *)&template;
- size = sizeof(struct ieee80211_header);
-
- memset(template.header.da, 0xff, ETH_ALEN);
- memset(template.header.bssid, 0xff, ETH_ALEN);
- memcpy(template.header.sa, wl->mac_addr, ETH_ALEN);
- template.header.frame_ctl = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
-
- /* IEs */
- /* SSID */
- template.ssid.header.id = WLAN_EID_SSID;
- template.ssid.header.len = ssid_len;
- if (ssid_len && ssid)
- memcpy(template.ssid.ssid, ssid, ssid_len);
- size += sizeof(struct wl12xx_ie_header) + ssid_len;
- ptr += size;
-
- /* Basic Rates */
- rates = (struct wl12xx_ie_rates *)ptr;
- rates->header.id = WLAN_EID_SUPP_RATES;
- rates->header.len = wl1271_build_basic_rates(rates->rates, band);
- size += sizeof(struct wl12xx_ie_header) + rates->header.len;
- ptr += sizeof(struct wl12xx_ie_header) + rates->header.len;
-
- /* Extended rates */
- rates = (struct wl12xx_ie_rates *)ptr;
- rates->header.id = WLAN_EID_EXT_SUPP_RATES;
- rates->header.len = wl1271_build_extended_rates(rates->rates, band);
- size += sizeof(struct wl12xx_ie_header) + rates->header.len;
-
- wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", &template, size);
+ skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len,
+ ie, ie_len);
+ if (!skb) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ wl1271_dump(DEBUG_SCAN, "PROBE REQ: ", skb->data, skb->len);
if (band == IEEE80211_BAND_2GHZ)
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4,
- &template, size);
+ skb->data, skb->len);
else
ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
- &template, size);
+ skb->data, skb->len);
+
+out:
+ dev_kfree_skb(skb);
return ret;
}
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 4297205..e936d3a 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -41,15 +41,16 @@ 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_scan(struct wl1271 *wl, u8 *ssid, size_t len,
- u8 active_scan, u8 high_prio, u8 band,
- u8 probe_requests);
+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 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, u8 *ssid, size_t ssid_len,
- u8 band);
+int wl1271_cmd_build_probe_req(struct wl1271 *wl,
+ const u8 *ssid, size_t ssid_len,
+ const u8 *ie, size_t ie_len, u8 band);
int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
u8 key_size, const u8 *key, const u8 *addr,
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index 5533519..4d35af9 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -44,7 +44,9 @@ static int wl1271_event_scan_complete(struct wl1271 *wl,
* scanning as it checks that.
*/
clear_bit(WL1271_FLAG_SCANNING, &wl->flags);
+ /* FIXME: ie missing! */
wl1271_cmd_scan(wl, wl->scan.ssid, wl->scan.ssid_len,
+ NULL, 0,
wl->scan.active,
wl->scan.high_prio,
WL1271_SCAN_BAND_5_GHZ,
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index d21bfe2..fbc42ce 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -1566,10 +1566,12 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
goto out;
if (wl1271_11a_enabled())
- ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
+ ret = wl1271_cmd_scan(hw->priv, ssid, len,
+ req->ie, req->ie_len, 1, 0,
WL1271_SCAN_BAND_DUAL, 3);
else
- ret = wl1271_cmd_scan(hw->priv, ssid, len, 1, 0,
+ ret = wl1271_cmd_scan(hw->priv, ssid, len,
+ req->ie, req->ie_len, 1, 0,
WL1271_SCAN_BAND_2_4_GHZ, 3);
wl1271_ps_elp_sleep(wl);
--
1.6.3.3