From 77e7b30b23d3360f627e991aea8255fa9914dd55 Mon Sep 17 00:00:00 2001 From: Devendra Naga Date: Wed, 29 Aug 2012 23:03:01 +0530 Subject: [PATCH 01/73] wl18xx: use module_platform_driver the driver's init and exit routines can be implemented with the module_platform_driver, as the init and exit code is same as that of the module_platform_driver Signed-off-by: Devendra Naga Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 31cf6eba3a9e..99364d4feac4 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1538,18 +1538,7 @@ static struct platform_driver wl18xx_driver = { } }; -static int __init wl18xx_init(void) -{ - return platform_driver_register(&wl18xx_driver); -} -module_init(wl18xx_init); - -static void __exit wl18xx_exit(void) -{ - platform_driver_unregister(&wl18xx_driver); -} -module_exit(wl18xx_exit); - +module_platform_driver(wl18xx_driver); module_param_named(ht_mode, ht_mode_param, charp, S_IRUSR); MODULE_PARM_DESC(ht_mode, "Force HT mode: wide or siso20"); From ae35c30c144b90266c75c5a1838753ff0c9130d0 Mon Sep 17 00:00:00 2001 From: Luciano Coelho Date: Thu, 27 Sep 2012 12:02:38 +0300 Subject: [PATCH 02/73] wl12xx: use module_platform_driver Use a module_platform_driver declaration instead of replicating the init and exit functions in the driver. Based on the patch for wl18xx by Devendra Naga. Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index f429fc110cb0..30ca727bc4c1 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1714,17 +1714,7 @@ static struct platform_driver wl12xx_driver = { } }; -static int __init wl12xx_init(void) -{ - return platform_driver_register(&wl12xx_driver); -} -module_init(wl12xx_init); - -static void __exit wl12xx_exit(void) -{ - platform_driver_unregister(&wl12xx_driver); -} -module_exit(wl12xx_exit); +module_platform_driver(wl12xx_driver); module_param_named(fref, fref_param, charp, 0); MODULE_PARM_DESC(fref, "FREF clock: 19.2, 26, 26x, 38.4, 38.4x, 52"); From 0635ad4550d1f30f265c7022a6988e49bf7a6fa3 Mon Sep 17 00:00:00 2001 From: Tim Gardner Date: Wed, 29 Aug 2012 13:09:33 -0600 Subject: [PATCH 03/73] wlcore: Declare MODULE_FIRMWARE usage Declare any firmware that might be used by this driver. If all drivers declare their firmware usage, then a sufficiently complete list of firmware files can then be used to pare down the external linux-firmware package to just the files in actual use. Cc: Luciano Coelho Cc: linux-wireless@vger.kernel.org Cc: netdev@vger.kernel.org Signed-off-by: Tim Gardner Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index ff830cf50c70..600af8e81904 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5665,3 +5665,4 @@ MODULE_PARM_DESC(no_recovery, "Prevent HW recovery. FW will remain stuck."); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Luciano Coelho "); MODULE_AUTHOR("Juuso Oikarinen "); +MODULE_FIRMWARE(WL12XX_NVS_NAME); From 27b7ce7c7f364b7b075c8a6a07260c5cdd41b3bf Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Sun, 26 Aug 2012 09:47:06 +0800 Subject: [PATCH 04/73] wl12xx: remove duplicated include from main.c Remove duplicated include. Signed-off-by: Wei Yongjun Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 30ca727bc4c1..9ab85c0a3fb8 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -32,7 +32,6 @@ #include "../wlcore/acx.h" #include "../wlcore/tx.h" #include "../wlcore/rx.h" -#include "../wlcore/io.h" #include "../wlcore/boot.h" #include "wl12xx.h" From e1c497c3e4b79feea3d587c8ca76fb437c1b2495 Mon Sep 17 00:00:00 2001 From: Ido Reis Date: Fri, 13 Jul 2012 00:12:08 +0300 Subject: [PATCH 05/73] wl18xx: update default phy configuration for pg2 default switch configuration set to pg2 chips (rdl 1/2/3/4). removed hacks for specific board types. pg1.x boards are now supported only using module params or specific conf files. Signed-off-by: Ido Reis Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 99364d4feac4..3c274ebd1b49 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -505,8 +505,8 @@ static struct wl18xx_priv_conf wl18xx_default_priv_conf = { .rdl = 0x01, .auto_detect = 0x00, .dedicated_fem = FEM_NONE, - .low_band_component = COMPONENT_2_WAY_SWITCH, - .low_band_component_type = 0x06, + .low_band_component = COMPONENT_3_WAY_SWITCH, + .low_band_component_type = 0x04, .high_band_component = COMPONENT_2_WAY_SWITCH, .high_band_component_type = 0x09, .tcxo_ldo_voltage = 0x00, @@ -1428,18 +1428,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) } } - /* HACK! Just for now we hardcode COM8 and HDK to 0x06 */ - switch (priv->conf.phy.board_type) { - case BOARD_TYPE_HDK_18XX: - case BOARD_TYPE_COM8_18XX: - priv->conf.phy.low_band_component_type = 0x06; - break; - case BOARD_TYPE_FPGA_18XX: - case BOARD_TYPE_DVP_18XX: - case BOARD_TYPE_EVB_18XX: - priv->conf.phy.low_band_component_type = 0x05; - break; - default: + if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) { wl1271_error("invalid board type '%d'", priv->conf.phy.board_type); ret = -EINVAL; From 9b1a0a7771a62c3af4dce83e7cfd199367bd84ff Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 25 Jul 2012 14:22:21 +0300 Subject: [PATCH 06/73] wlcore: consider single fw case When a single fw is being used for both single-role and multi-role cases (e.g. 18xx), wl->mr_fw_name is NULL, which results in NULL dereference while trying to load the multi-role fw. In this case, always use the single-role fw, and avoid redundant fw switch by checking for this case in wl12xx_need_fw_change() as well. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 600af8e81904..f421c42b32ea 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -696,7 +696,7 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) * we can't call wl12xx_get_vif_count() here because * wl->mutex is taken, so use the cached last_vif_count value */ - if (wl->last_vif_count > 1) { + if (wl->last_vif_count > 1 && wl->mr_fw_name) { fw_type = WL12XX_FW_TYPE_MULTI; fw_name = wl->mr_fw_name; } else { @@ -2170,6 +2170,10 @@ static bool wl12xx_need_fw_change(struct wl1271 *wl, if (wl->state == WL1271_STATE_OFF) return false; + /* no need for fw change if a single fw is used */ + if (!wl->mr_fw_name) + return false; + if (vif_count > 1 && current_fw == WL12XX_FW_TYPE_NORMAL) return true; if (vif_count <= 1 && current_fw == WL12XX_FW_TYPE_MULTI) From 4cc533830b7e6b309e8b73196c410951fc2bed91 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Tue, 24 Jul 2012 19:18:49 +0300 Subject: [PATCH 07/73] wlcore: Prevent interaction with HW after recovery is queued When a function requests to recover, it would normally abort and will not send any additional commands to the HW. However, other threads may not be aware of the failure and could try to communicate with the HW after a recovery was queued, but before the recovery work began. Fix this by introducing an intermediate state which is set when recovery is queued, and modify all state checks accordingly. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/debugfs.c | 2 +- drivers/net/wireless/ti/wlcore/cmd.c | 3 + drivers/net/wireless/ti/wlcore/debugfs.c | 15 +++-- drivers/net/wireless/ti/wlcore/io.h | 4 +- drivers/net/wireless/ti/wlcore/main.c | 73 +++++++++++------------ drivers/net/wireless/ti/wlcore/ps.c | 2 +- drivers/net/wireless/ti/wlcore/scan.c | 2 +- drivers/net/wireless/ti/wlcore/testmode.c | 4 +- drivers/net/wireless/ti/wlcore/tx.c | 2 +- drivers/net/wireless/ti/wlcore/wlcore.h | 2 +- drivers/net/wireless/ti/wlcore/wlcore_i.h | 7 ++- 11 files changed, 61 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/debugfs.c b/drivers/net/wireless/ti/wl18xx/debugfs.c index 3ce6f1039af3..7f1669cdea09 100644 --- a/drivers/net/wireless/ti/wl18xx/debugfs.c +++ b/drivers/net/wireless/ti/wl18xx/debugfs.c @@ -220,7 +220,7 @@ static ssize_t clear_fw_stats_write(struct file *file, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl18xx_acx_clear_statistics(wl); diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 20e1bd923832..b63995da7e45 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -59,6 +59,9 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, u16 status; u16 poll_count = 0; + if (WARN_ON(unlikely(wl->state == WLCORE_STATE_RESTARTING))) + return -EIO; + cmd = buf; cmd->id = cpu_to_le16(id); cmd->status = 0; diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 80dbc5304fac..3b7e0e817984 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -62,11 +62,14 @@ void wl1271_debugfs_update_stats(struct wl1271 *wl) mutex_lock(&wl->mutex); + if (unlikely(wl->state != WLCORE_STATE_ON)) + goto out; + ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; - if (wl->state == WL1271_STATE_ON && !wl->plt && + if (!wl->plt && time_after(jiffies, wl->stats.fw_stats_update + msecs_to_jiffies(WL1271_DEBUGFS_STATS_LIFETIME))) { wl1271_acx_statistics(wl, wl->stats.fw_stats); @@ -286,7 +289,7 @@ static ssize_t dynamic_ps_timeout_write(struct file *file, wl->conf.conn.dynamic_ps_timeout = value; - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -353,7 +356,7 @@ static ssize_t forced_ps_write(struct file *file, wl->conf.conn.forced_ps = value; - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -999,7 +1002,7 @@ static ssize_t sleep_auth_write(struct file *file, wl->conf.conn.sta_sleep_auth = value; - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { /* this will show up on "read" in case we are off */ wl->sleep_auth = value; goto out; @@ -1060,7 +1063,7 @@ static ssize_t dev_mem_read(struct file *file, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EFAULT; goto skip_read; } @@ -1145,7 +1148,7 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EFAULT; goto skip_write; } diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h index 259149f36fae..f48530fec14f 100644 --- a/drivers/net/wireless/ti/wlcore/io.h +++ b/drivers/net/wireless/ti/wlcore/io.h @@ -64,7 +64,7 @@ static inline int __must_check wlcore_raw_write(struct wl1271 *wl, int addr, return -EIO; ret = wl->if_ops->write(wl->dev, addr, buf, len, fixed); - if (ret && wl->state != WL1271_STATE_OFF) + if (ret && wl->state != WLCORE_STATE_OFF) set_bit(WL1271_FLAG_IO_FAILED, &wl->flags); return ret; @@ -80,7 +80,7 @@ static inline int __must_check wlcore_raw_read(struct wl1271 *wl, int addr, return -EIO; ret = wl->if_ops->read(wl->dev, addr, buf, len, fixed); - if (ret && wl->state != WL1271_STATE_OFF) + if (ret && wl->state != WLCORE_STATE_OFF) set_bit(WL1271_FLAG_IO_FAILED, &wl->flags); return ret; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index f421c42b32ea..21267c5b9705 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -248,7 +248,7 @@ static void wl12xx_tx_watchdog_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; /* Tx went out in the meantime - everything is ok */ @@ -512,7 +512,7 @@ static int wlcore_irq_locked(struct wl1271 *wl) wl1271_debug(DEBUG_IRQ, "IRQ work"); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -776,6 +776,7 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) /* Avoid a recursive recovery */ if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { + wl->state = WLCORE_STATE_RESTARTING; wlcore_disable_interrupts_nosync(wl); ieee80211_queue_work(wl->hw, &wl->recovery_work); } @@ -913,7 +914,7 @@ static void wl1271_recovery_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->state != WL1271_STATE_ON || wl->plt) + if (wl->state == WLCORE_STATE_OFF || wl->plt) goto out_unlock; if (!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)) { @@ -1081,7 +1082,7 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode) wl1271_notice("power up"); - if (wl->state != WL1271_STATE_OFF) { + if (wl->state != WLCORE_STATE_OFF) { wl1271_error("cannot go into PLT state because not " "in off state: %d", wl->state); ret = -EBUSY; @@ -1102,7 +1103,7 @@ int wl1271_plt_start(struct wl1271 *wl, const enum plt_mode plt_mode) if (ret < 0) goto power_off; - wl->state = WL1271_STATE_ON; + wl->state = WLCORE_STATE_ON; wl1271_notice("firmware booted in PLT mode %s (%s)", PLT_MODE[plt_mode], wl->chip.fw_ver_str); @@ -1171,7 +1172,7 @@ int wl1271_plt_stop(struct wl1271 *wl) wl1271_power_off(wl); wl->flags = 0; wl->sleep_auth = WL1271_PSM_ILLEGAL; - wl->state = WL1271_STATE_OFF; + wl->state = WLCORE_STATE_OFF; wl->plt = false; wl->plt_mode = PLT_OFF; wl->rx_counter = 0; @@ -1833,7 +1834,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) { int i; - if (wl->state == WL1271_STATE_OFF) { + if (wl->state == WLCORE_STATE_OFF) { if (test_and_clear_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) wlcore_enable_interrupts(wl); @@ -1845,7 +1846,7 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) * this must be before the cancel_work calls below, so that the work * functions don't perform further work. */ - wl->state = WL1271_STATE_OFF; + wl->state = WLCORE_STATE_OFF; /* * Use the nosync variant to disable interrupts, so the mutex could be @@ -2098,7 +2099,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) /* Unlocking the mutex in the middle of handling is inherently unsafe. In this case we deem it safe to do, because we need to let any possibly pending IRQ out of - the system (and while we are WL1271_STATE_OFF the IRQ + the system (and while we are WLCORE_STATE_OFF the IRQ work function will not do anything.) Also, any other possible concurrent operations will fail due to the current state, hence the wl1271 struct should be safe. */ @@ -2133,7 +2134,7 @@ static bool wl12xx_init_fw(struct wl1271 *wl) wl1271_debug(DEBUG_MAC80211, "11a is %ssupported", wl->enable_11a ? "" : "not "); - wl->state = WL1271_STATE_ON; + wl->state = WLCORE_STATE_ON; out: return booted; } @@ -2167,7 +2168,7 @@ static bool wl12xx_need_fw_change(struct wl1271 *wl, wl->last_vif_count = vif_count; /* no need for fw change if the device is OFF */ - if (wl->state == WL1271_STATE_OFF) + if (wl->state == WLCORE_STATE_OFF) return false; /* no need for fw change if a single fw is used */ @@ -2253,7 +2254,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, * TODO: after the nvs issue will be solved, move this block * to start(), and make sure here the driver is ON. */ - if (wl->state == WL1271_STATE_OFF) { + if (wl->state == WLCORE_STATE_OFF) { /* * we still need this in order to configure the fw * while uploading the nvs @@ -2320,7 +2321,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, return; /* because of hardware recovery, we may get here twice */ - if (wl->state != WL1271_STATE_ON) + if (wl->state == WLCORE_STATE_OFF) return; wl1271_info("down"); @@ -2441,7 +2442,7 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, wl12xx_get_vif_count(hw, vif, &vif_count); mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF || + if (wl->state == WLCORE_STATE_OFF || !test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags)) goto out; @@ -2776,7 +2777,7 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed) if (changed & IEEE80211_CONF_CHANGE_POWER) wl->power_level = conf->power_level; - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -2810,10 +2811,6 @@ static u64 wl1271_op_prepare_multicast(struct ieee80211_hw *hw, { struct wl1271_filter_params *fp; struct netdev_hw_addr *ha; - struct wl1271 *wl = hw->priv; - - if (unlikely(wl->state == WL1271_STATE_OFF)) - return 0; fp = kzalloc(sizeof(*fp), GFP_ATOMIC); if (!fp) { @@ -2862,7 +2859,7 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw, *total &= WL1271_SUPPORTED_FILTERS; changed &= WL1271_SUPPORTED_FILTERS; - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -3111,7 +3108,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EAGAIN; goto out_unlock; } @@ -3225,7 +3222,7 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { /* * We cannot return -EBUSY here because cfg80211 will expect * a call to ieee80211_scan_completed if we do - in this case @@ -3265,7 +3262,7 @@ static void wl1271_op_cancel_hw_scan(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; if (wl->scan.state == WL1271_SCAN_STATE_IDLE) @@ -3314,7 +3311,7 @@ static int wl1271_op_sched_scan_start(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EAGAIN; goto out; } @@ -3351,7 +3348,7 @@ static void wl1271_op_sched_scan_stop(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -3372,7 +3369,7 @@ static int wl1271_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EAGAIN; goto out; } @@ -3401,7 +3398,7 @@ static int wl1271_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EAGAIN; goto out; } @@ -4177,7 +4174,7 @@ static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; if (unlikely(!test_bit(WLVIF_FLAG_INITIALIZED, &wlvif->flags))) @@ -4261,7 +4258,7 @@ static u64 wl1271_op_get_tsf(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -4460,7 +4457,7 @@ static int wl12xx_op_sta_state(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EBUSY; goto out; } @@ -4499,7 +4496,7 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EAGAIN; goto out; } @@ -4617,7 +4614,7 @@ static int wl12xx_set_bitrate_mask(struct ieee80211_hw *hw, mask->control[i].legacy, i); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; if (wlvif->bss_type == BSS_TYPE_STA_BSS && @@ -4653,12 +4650,14 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) { + if (unlikely(wl->state == WLCORE_STATE_OFF)) { wl12xx_for_each_wlvif_sta(wl, wlvif) { struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); ieee80211_chswitch_done(vif, false); } goto out; + } else if (unlikely(wl->state != WLCORE_STATE_ON)) { + goto out; } ret = wl1271_ps_elp_wakeup(wl); @@ -4693,7 +4692,7 @@ static bool wl1271_tx_frames_pending(struct ieee80211_hw *hw) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; /* packets are considered pending if in the TX queue or the FW */ @@ -4942,7 +4941,7 @@ static ssize_t wl1271_sysfs_store_bt_coex_state(struct device *dev, wl->sg_enabled = res; - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; ret = wl1271_ps_elp_wakeup(wl); @@ -5060,7 +5059,7 @@ static void wl1271_connection_loss_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; /* Call mac80211 connection loss */ @@ -5396,7 +5395,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) spin_lock_init(&wl->wl_lock); - wl->state = WL1271_STATE_OFF; + wl->state = WLCORE_STATE_OFF; wl->fw_type = WL12XX_FW_TYPE_NONE; mutex_init(&wl->mutex); mutex_init(&wl->flush_mutex); diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index 46d36fd30eba..e904d68767e2 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c @@ -44,7 +44,7 @@ void wl1271_elp_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; /* our work might have been already cancelled */ diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index dbeca1bfbb2c..bc924877ca4d 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -46,7 +46,7 @@ void wl1271_scan_complete_work(struct work_struct *work) mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) + if (unlikely(wl->state != WLCORE_STATE_ON)) goto out; if (wl->scan.state == WL1271_SCAN_STATE_IDLE) diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c index 49e5ee1525c9..f3442762d884 100644 --- a/drivers/net/wireless/ti/wlcore/testmode.c +++ b/drivers/net/wireless/ti/wlcore/testmode.c @@ -92,7 +92,7 @@ static int wl1271_tm_cmd_test(struct wl1271 *wl, struct nlattr *tb[]) mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EINVAL; goto out; } @@ -164,7 +164,7 @@ static int wl1271_tm_cmd_interrogate(struct wl1271 *wl, struct nlattr *tb[]) mutex_lock(&wl->mutex); - if (wl->state == WL1271_STATE_OFF) { + if (unlikely(wl->state != WLCORE_STATE_ON)) { ret = -EINVAL; goto out; } diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 1a2f31c289c5..4f66e759de37 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -687,7 +687,7 @@ int wlcore_tx_work_locked(struct wl1271 *wl) int bus_ret = 0; u8 hlid; - if (unlikely(wl->state == WL1271_STATE_OFF)) + if (unlikely(wl->state != WLCORE_STATE_ON)) return 0; while ((skb = wl1271_skb_dequeue(wl, &hlid))) { diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 0ce7a8ebbd46..81790a0aea08 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -153,7 +153,7 @@ struct wl1271 { spinlock_t wl_lock; - enum wl1271_state state; + enum wlcore_state state; enum wl12xx_fw_type fw_type; bool plt; enum plt_mode plt_mode; diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index c0505635bb00..58fbdcac6452 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -85,9 +85,10 @@ #define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE) -enum wl1271_state { - WL1271_STATE_OFF, - WL1271_STATE_ON, +enum wlcore_state { + WLCORE_STATE_OFF, + WLCORE_STATE_RESTARTING, + WLCORE_STATE_ON, }; enum wl12xx_fw_type { From 9ae48aeaa3618258f723d184871cc49ff4e50996 Mon Sep 17 00:00:00 2001 From: Ido Reis Date: Mon, 25 Jun 2012 18:51:54 +0300 Subject: [PATCH 08/73] wl18xx: increase rx_ba_win_size to 32 The new FWs support a bigger BA window. Signed-off-by: Ido Reis Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 3c274ebd1b49..181cd94ee146 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -415,7 +415,7 @@ static struct wlcore_conf wl18xx_conf = { .snr_threshold = 0, }, .ht = { - .rx_ba_win_size = 10, + .rx_ba_win_size = 32, .tx_ba_win_size = 64, .inactivity_timeout = 10000, .tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP, From 6dbc5fc2596059afca1db47eb1ac78f7095d27a1 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 29 Jul 2012 14:37:29 +0300 Subject: [PATCH 09/73] wlcore: cancel recovery_work on stop() instead of remove_interface() recovery_work should be cancelled when stopping the device, not when removing an interface (this is probably a leftover from the single-role days) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 21267c5b9705..612008f32992 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1857,6 +1857,8 @@ static void wlcore_op_stop_locked(struct wl1271 *wl) mutex_unlock(&wl->mutex); wlcore_synchronize_interrupts(wl); + if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) + cancel_work_sync(&wl->recovery_work); wl1271_flush_deferred_work(wl); cancel_delayed_work_sync(&wl->scan_complete_work); cancel_work_sync(&wl->netstack_work); @@ -2437,7 +2439,6 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); struct wl12xx_vif *iter; struct vif_counter_data vif_count; - bool cancel_recovery = true; wl12xx_get_vif_count(hw, vif, &vif_count); mutex_lock(&wl->mutex); @@ -2462,12 +2463,9 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw, wl12xx_force_active_psm(wl); set_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags); wl12xx_queue_recovery_work(wl); - cancel_recovery = false; } out: mutex_unlock(&wl->mutex); - if (cancel_recovery) - cancel_work_sync(&wl->recovery_work); } static int wl12xx_op_change_interface(struct ieee80211_hw *hw, From c3e06fc03b64c626e150c33b897ddd728c30a316 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 23 Jul 2012 10:38:18 +0300 Subject: [PATCH 10/73] wlcore: AP mode - send non-data packets with basic rates This solves interoperability issues with peer that don't seem to "hear" management packets transmitted in higher rates. Based on a previous patch by Igal Chernobelsky. Cc: Igal Chernobelsky Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/tx.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 4f66e759de37..24ac8ecde867 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -319,8 +319,12 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct wl12xx_vif *wlvif, if (hlid == wlvif->ap.global_hlid) rate_idx = wlvif->ap.mgmt_rate_idx; else if (hlid == wlvif->ap.bcast_hlid || - skb->protocol == cpu_to_be16(ETH_P_PAE)) - /* send AP bcast and EAPOLs using the min basic rate */ + skb->protocol == cpu_to_be16(ETH_P_PAE) || + !ieee80211_is_data(frame_control)) + /* + * send non-data, bcast and EAPOLs using the + * min basic rate + */ rate_idx = wlvif->ap.bcast_rate_idx; else rate_idx = wlvif->ap.ucast_rate_idx[ac]; From 714947600eca45e053af7d77d99d1b8fb227dc83 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 23 Jul 2012 15:18:29 +0300 Subject: [PATCH 11/73] wlcore: allow only the lowest OFDM rate for p2p setup frames The IEEE80211_TX_CTL_NO_CCK_RATE flag is only set for mgmt packets transmitted during p2p connection setup. Make sure to use the lowest OFDM rate guarantee the peer always hears us. Change the p2p rate policy to contain only the 6mpbs rate to acheive this effect. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/conf.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/conf.h b/drivers/net/wireless/ti/wlcore/conf.h index d77224f2ac6b..9e40760bafe1 100644 --- a/drivers/net/wireless/ti/wlcore/conf.h +++ b/drivers/net/wireless/ti/wlcore/conf.h @@ -412,8 +412,7 @@ struct conf_rx_settings { #define CONF_TX_RATE_RETRY_LIMIT 10 /* basic rates for p2p operations (probe req/resp, etc.) */ -#define CONF_TX_RATE_MASK_BASIC_P2P (CONF_HW_BIT_RATE_6MBPS | \ - CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS) +#define CONF_TX_RATE_MASK_BASIC_P2P CONF_HW_BIT_RATE_6MBPS /* * Rates supported for data packets when operating as AP. Note the absence From 958e303abba61bad165a96e22e138c4763047df2 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 23 Jul 2012 23:50:45 +0300 Subject: [PATCH 12/73] wlcore: make Tx flush timings more verbose Print how much time a flush took. This will help debug the time it takes to switch between channels. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/tx.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index 24ac8ecde867..d89e0db8a6f9 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -1076,9 +1076,10 @@ void wl12xx_tx_reset(struct wl1271 *wl) /* caller must *NOT* hold wl->mutex */ void wl1271_tx_flush(struct wl1271 *wl) { - unsigned long timeout; + unsigned long timeout, start_time; int i; - timeout = jiffies + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); + start_time = jiffies; + timeout = start_time + usecs_to_jiffies(WL1271_TX_FLUSH_TIMEOUT); /* only one flush should be in progress, for consistent queue state */ mutex_lock(&wl->flush_mutex); @@ -1087,19 +1088,23 @@ void wl1271_tx_flush(struct wl1271 *wl) while (!time_after(jiffies, timeout)) { mutex_lock(&wl->mutex); - wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d", + wl1271_debug(DEBUG_MAC80211, "flushing tx buffer: %d %d", wl->tx_frames_cnt, wl1271_tx_total_queue_count(wl)); if ((wl->tx_frames_cnt == 0) && (wl1271_tx_total_queue_count(wl) == 0)) { mutex_unlock(&wl->mutex); + wl1271_debug(DEBUG_MAC80211, "tx flush took %d ms", + jiffies_to_msecs(jiffies - start_time)); goto out; } mutex_unlock(&wl->mutex); msleep(1); } - wl1271_warning("Unable to flush all TX buffers, timed out."); + wl1271_warning("Unable to flush all TX buffers, " + "timed out (timeout %d ms", + WL1271_TX_FLUSH_TIMEOUT / 1000); /* forcibly flush all Tx buffers on our queues */ mutex_lock(&wl->mutex); From f83e54134a6d38437ddee0fda96692a6b0c33b0e Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Sun, 29 Jul 2012 12:18:32 +0300 Subject: [PATCH 13/73] wlcore: tx_flush - optimize flow and force Tx during the flush Force Tx during the flush if there are packets pending in the driver. This actually solves a bug where we would get called from the mac80211 wq context, which would prevent tx_work from getting queued, even when the mutex is unlocked. Don't stop the queues needlessly if there's nothing to flush. Use a larger delay when sleeping to give the driver a chance to flush and avoid cpu busy looping. Re-arrange the loop so the last iteration is not wasted. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/tx.c | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index d89e0db8a6f9..f9c26b19bff0 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -1084,22 +1084,32 @@ void wl1271_tx_flush(struct wl1271 *wl) /* only one flush should be in progress, for consistent queue state */ mutex_lock(&wl->flush_mutex); + mutex_lock(&wl->mutex); + if (wl->tx_frames_cnt == 0 && wl1271_tx_total_queue_count(wl) == 0) { + mutex_unlock(&wl->mutex); + goto out; + } + wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); while (!time_after(jiffies, timeout)) { - mutex_lock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "flushing tx buffer: %d %d", wl->tx_frames_cnt, wl1271_tx_total_queue_count(wl)); + + /* force Tx and give the driver some time to flush data */ + mutex_unlock(&wl->mutex); + if (wl1271_tx_total_queue_count(wl)) + wl1271_tx_work(&wl->tx_work); + msleep(20); + mutex_lock(&wl->mutex); + if ((wl->tx_frames_cnt == 0) && (wl1271_tx_total_queue_count(wl) == 0)) { - mutex_unlock(&wl->mutex); wl1271_debug(DEBUG_MAC80211, "tx flush took %d ms", jiffies_to_msecs(jiffies - start_time)); - goto out; + goto out_wake; } - mutex_unlock(&wl->mutex); - msleep(1); } wl1271_warning("Unable to flush all TX buffers, " @@ -1107,13 +1117,13 @@ void wl1271_tx_flush(struct wl1271 *wl) WL1271_TX_FLUSH_TIMEOUT / 1000); /* forcibly flush all Tx buffers on our queues */ - mutex_lock(&wl->mutex); for (i = 0; i < WL12XX_MAX_LINKS; i++) wl1271_tx_reset_link_queues(wl, i); - mutex_unlock(&wl->mutex); -out: +out_wake: wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_FLUSH); + mutex_unlock(&wl->mutex); +out: mutex_unlock(&wl->flush_mutex); } EXPORT_SYMBOL_GPL(wl1271_tx_flush); From f1c434df6727ebb3068b67b06eae945a80f07ad3 Mon Sep 17 00:00:00 2001 From: Igal Chernobelsky Date: Tue, 31 Jul 2012 14:48:46 +0300 Subject: [PATCH 14/73] wl18xx/wl12xx: defines for Tx/Rx descriptors num Use defines for number of Tx/Rx descriptors. Signed-off-by: Igal Chernobelsky Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 4 ++-- drivers/net/wireless/ti/wl12xx/wl12xx.h | 3 +++ drivers/net/wireless/ti/wl18xx/main.c | 4 ++-- drivers/net/wireless/ti/wl18xx/wl18xx.h | 3 +++ 4 files changed, 10 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 9ab85c0a3fb8..f38e76942ccc 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1641,8 +1641,8 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) wl->ops = &wl12xx_ops; wl->ptable = wl12xx_ptable; wl->rtable = wl12xx_rtable; - wl->num_tx_desc = 16; - wl->num_rx_desc = 8; + wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; + wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; wl->band_rate_to_idx = wl12xx_band_rate_to_idx; wl->hw_tx_rate_tbl_size = WL12XX_CONF_HW_RXTX_RATE_MAX; wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index 26990fb4edea..c8ff7ec9fd41 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h @@ -38,6 +38,9 @@ #define WL128X_SUBTYPE_VER 2 #define WL128X_MINOR_VER 115 +#define WL12XX_NUM_TX_DESCRIPTORS 16 +#define WL12XX_NUM_RX_DESCRIPTORS 8 + struct wl127x_rx_mem_pool_addr { u32 addr; u32 addr_extra; diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 181cd94ee146..934708b6db8d 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1392,8 +1392,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) wl->ops = &wl18xx_ops; wl->ptable = wl18xx_ptable; wl->rtable = wl18xx_rtable; - wl->num_tx_desc = 32; - wl->num_rx_desc = 32; + wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; + wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS; wl->band_rate_to_idx = wl18xx_band_rate_to_idx; wl->hw_tx_rate_tbl_size = WL18XX_CONF_HW_RXTX_RATE_MAX; wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index 6452396fa1d4..9882e29db4a8 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -33,6 +33,9 @@ #define WL18XX_CMD_MAX_SIZE 740 +#define WL18XX_NUM_TX_DESCRIPTORS 32 +#define WL18XX_NUM_RX_DESCRIPTORS 32 + struct wl18xx_priv { /* buffer for sending commands to FW */ u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; From 26a309c7586140afd40628a7031993afbaae0f07 Mon Sep 17 00:00:00 2001 From: Igal Chernobelsky Date: Sun, 29 Jul 2012 18:21:12 +0300 Subject: [PATCH 15/73] wlcore/wl18xx/wl12xx: aggregation buffer size set Aggregation buffer size is set separately per 18xx/12xx chip family. For 18xx aggragation buffer is set to 13 pages to utilize all the available tx/rx descriptors for aggregation. [Arik - remove redundant parts from the patch] Signed-off-by: Igal Chernobelsky Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 2 +- drivers/net/wireless/ti/wl12xx/wl12xx.h | 2 ++ drivers/net/wireless/ti/wl18xx/main.c | 2 +- drivers/net/wireless/ti/wl18xx/wl18xx.h | 2 ++ drivers/net/wireless/ti/wlcore/main.c | 8 ++++---- drivers/net/wireless/ti/wlcore/rx.c | 2 +- drivers/net/wireless/ti/wlcore/tx.c | 2 +- drivers/net/wireless/ti/wlcore/wlcore.h | 3 ++- 8 files changed, 14 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index f38e76942ccc..0a8bc0c7b6cc 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1630,7 +1630,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) struct ieee80211_hw *hw; struct wl12xx_priv *priv; - hw = wlcore_alloc_hw(sizeof(*priv)); + hw = wlcore_alloc_hw(sizeof(*priv), WL12XX_AGGR_BUFFER_SIZE); if (IS_ERR(hw)) { wl1271_error("can't allocate hw"); return PTR_ERR(hw); diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index c8ff7ec9fd41..9953374a307d 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h @@ -38,6 +38,8 @@ #define WL128X_SUBTYPE_VER 2 #define WL128X_MINOR_VER 115 +#define WL12XX_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) + #define WL12XX_NUM_TX_DESCRIPTORS 16 #define WL12XX_NUM_RX_DESCRIPTORS 8 diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 934708b6db8d..3f4fbd80d4ae 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1380,7 +1380,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) struct wl18xx_priv *priv; int ret; - hw = wlcore_alloc_hw(sizeof(*priv)); + hw = wlcore_alloc_hw(sizeof(*priv), WL18XX_AGGR_BUFFER_SIZE); if (IS_ERR(hw)) { wl1271_error("can't allocate hw"); ret = PTR_ERR(hw); diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index 9882e29db4a8..a6e61a25124d 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -33,6 +33,8 @@ #define WL18XX_CMD_MAX_SIZE 740 +#define WL18XX_AGGR_BUFFER_SIZE (13 * PAGE_SIZE) + #define WL18XX_NUM_TX_DESCRIPTORS 32 #define WL18XX_NUM_RX_DESCRIPTORS 32 diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 612008f32992..7fe19defa97f 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5313,7 +5313,7 @@ static int wl1271_init_ieee80211(struct wl1271 *wl) #define WL1271_DEFAULT_CHANNEL 0 -struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) +struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) { struct ieee80211_hw *hw; struct wl1271 *wl; @@ -5398,12 +5398,13 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size) mutex_init(&wl->mutex); mutex_init(&wl->flush_mutex); - order = get_order(WL1271_AGGR_BUFFER_SIZE); + order = get_order(aggr_buf_size); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); if (!wl->aggr_buf) { ret = -ENOMEM; goto err_wq; } + wl->aggr_buf_size = aggr_buf_size; wl->dummy_packet = wl12xx_alloc_dummy_packet(wl); if (!wl->dummy_packet) { @@ -5466,8 +5467,7 @@ int wlcore_free_hw(struct wl1271 *wl) device_remove_file(wl->dev, &dev_attr_bt_coex_state); free_page((unsigned long)wl->fwlog); dev_kfree_skb(wl->dummy_packet); - free_pages((unsigned long)wl->aggr_buf, - get_order(WL1271_AGGR_BUFFER_SIZE)); + free_pages((unsigned long)wl->aggr_buf, get_order(wl->aggr_buf_size)); wl1271_debugfs_exit(wl); diff --git a/drivers/net/wireless/ti/wlcore/rx.c b/drivers/net/wireless/ti/wlcore/rx.c index f55e2f9e7ac5..9ee0ec6fd1db 100644 --- a/drivers/net/wireless/ti/wlcore/rx.c +++ b/drivers/net/wireless/ti/wlcore/rx.c @@ -221,7 +221,7 @@ int wlcore_rx(struct wl1271 *wl, struct wl_fw_status_1 *status) pkt_len = wlcore_rx_get_buf_size(wl, des); align_pkt_len = wlcore_rx_get_align_buf_size(wl, pkt_len); - if (buf_size + align_pkt_len > WL1271_AGGR_BUFFER_SIZE) + if (buf_size + align_pkt_len > wl->aggr_buf_size) break; buf_size += align_pkt_len; rx_counter++; diff --git a/drivers/net/wireless/ti/wlcore/tx.c b/drivers/net/wireless/ti/wlcore/tx.c index f9c26b19bff0..a90d3cd09408 100644 --- a/drivers/net/wireless/ti/wlcore/tx.c +++ b/drivers/net/wireless/ti/wlcore/tx.c @@ -193,7 +193,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct wl12xx_vif *wlvif, int id, ret = -EBUSY, ac; u32 spare_blocks; - if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) + if (buf_offset + total_len > wl->aggr_buf_size) return -EAGAIN; spare_blocks = wlcore_hw_get_spare_blocks(wl, is_gem); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 81790a0aea08..a7e9d5869db4 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -237,6 +237,7 @@ struct wl1271 { /* Intermediate buffer, used for packet aggregation */ u8 *aggr_buf; + u32 aggr_buf_size; /* Reusable dummy packet template */ struct sk_buff *dummy_packet; @@ -399,7 +400,7 @@ struct wl1271 { int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); int __devexit wlcore_remove(struct platform_device *pdev); -struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size); +struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size); int wlcore_free_hw(struct wl1271 *wl); int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, struct ieee80211_vif *vif, From 11bc97eb902ddac822f32dc5a890d7b6274b754d Mon Sep 17 00:00:00 2001 From: Eyal Shapira Date: Thu, 2 Aug 2012 07:15:19 +0300 Subject: [PATCH 16/73] wlcore: configure wowlan regardless of wakeup conditions wowlan filters should be configured in any case in suspend/resume. This shouldn't be dependent on whether wakeup conditions are the same for suspend and resume states. Only the FW command to reconfigure wakeup conditions should be avoided in such a case. Reported-by: Arik Nemtsov Signed-off-by: Eyal Shapira Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 7fe19defa97f..a797ce7201b2 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1603,12 +1603,6 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) goto out; - if ((wl->conf.conn.suspend_wake_up_event == - wl->conf.conn.wake_up_event) && - (wl->conf.conn.suspend_listen_interval == - wl->conf.conn.listen_interval)) - goto out; - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) goto out; @@ -1617,6 +1611,12 @@ static int wl1271_configure_suspend_sta(struct wl1271 *wl, if (ret < 0) goto out_sleep; + if ((wl->conf.conn.suspend_wake_up_event == + wl->conf.conn.wake_up_event) && + (wl->conf.conn.suspend_listen_interval == + wl->conf.conn.listen_interval)) + goto out_sleep; + ret = wl1271_acx_wake_up_conditions(wl, wlvif, wl->conf.conn.suspend_wake_up_event, wl->conf.conn.suspend_listen_interval); @@ -1672,13 +1672,6 @@ static void wl1271_configure_resume(struct wl1271 *wl, if ((!is_ap) && (!is_sta)) return; - if (is_sta && - ((wl->conf.conn.suspend_wake_up_event == - wl->conf.conn.wake_up_event) && - (wl->conf.conn.suspend_listen_interval == - wl->conf.conn.listen_interval))) - return; - ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) return; @@ -1686,6 +1679,12 @@ static void wl1271_configure_resume(struct wl1271 *wl, if (is_sta) { wl1271_configure_wowlan(wl, NULL); + if ((wl->conf.conn.suspend_wake_up_event == + wl->conf.conn.wake_up_event) && + (wl->conf.conn.suspend_listen_interval == + wl->conf.conn.listen_interval)) + goto out_sleep; + ret = wl1271_acx_wake_up_conditions(wl, wlvif, wl->conf.conn.wake_up_event, wl->conf.conn.listen_interval); @@ -1698,6 +1697,7 @@ static void wl1271_configure_resume(struct wl1271 *wl, ret = wl1271_acx_beacon_filter_opt(wl, wlvif, false); } +out_sleep: wl1271_ps_elp_sleep(wl); } From d49524d3e8406e3b858650abcf846531a2104120 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Wed, 1 Aug 2012 18:44:22 +0300 Subject: [PATCH 17/73] wlcore: resume() only if sta is associated mac80211's resume() callback might get called even if the sta is not associated (but only up). The resume sequence in this case results in configuring the wake-up conditions of a non-started role, which causes fw assertion. Fix it by bailing out if the STA is not connected (like we do on suspend()). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index a797ce7201b2..ae2b0fd7e558 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1672,6 +1672,9 @@ static void wl1271_configure_resume(struct wl1271 *wl, if ((!is_ap) && (!is_sta)) return; + if (is_sta && !test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) + return; + ret = wl1271_ps_elp_wakeup(wl); if (ret < 0) return; From f4afbed9447c86e5d3cec5933ae74b902617987c Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Thu, 2 Aug 2012 20:37:21 +0300 Subject: [PATCH 18/73] wlcore/wl18xx/wl12xx: allow up to 3 mac addresses Allow 3 native mac addresses on 18xx. On 12xx allow 2 native mac addresses and set the LAA bit to create a third mac address. This enabled operation with a separate group interface. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 1 + drivers/net/wireless/ti/wl12xx/wl12xx.h | 2 ++ drivers/net/wireless/ti/wl18xx/main.c | 1 + drivers/net/wireless/ti/wl18xx/wl18xx.h | 2 ++ drivers/net/wireless/ti/wlcore/main.c | 30 ++++++++++++++++++------- drivers/net/wireless/ti/wlcore/wlcore.h | 11 ++++++++- 6 files changed, 38 insertions(+), 9 deletions(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 0a8bc0c7b6cc..f49ce7c633b6 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1643,6 +1643,7 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) wl->rtable = wl12xx_rtable; wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; + 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; wl->hw_min_ht_rate = WL12XX_CONF_HW_RXTX_RATE_MCS0; diff --git a/drivers/net/wireless/ti/wl12xx/wl12xx.h b/drivers/net/wireless/ti/wl12xx/wl12xx.h index 9953374a307d..7182bbf6625d 100644 --- a/drivers/net/wireless/ti/wl12xx/wl12xx.h +++ b/drivers/net/wireless/ti/wl12xx/wl12xx.h @@ -43,6 +43,8 @@ #define WL12XX_NUM_TX_DESCRIPTORS 16 #define WL12XX_NUM_RX_DESCRIPTORS 8 +#define WL12XX_NUM_MAC_ADDRESSES 2 + struct wl127x_rx_mem_pool_addr { u32 addr; u32 addr_extra; diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 3f4fbd80d4ae..93b148fe17a3 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1394,6 +1394,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) wl->rtable = wl18xx_rtable; wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS; + 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; wl->hw_min_ht_rate = WL18XX_CONF_HW_RXTX_RATE_MCS0; diff --git a/drivers/net/wireless/ti/wl18xx/wl18xx.h b/drivers/net/wireless/ti/wl18xx/wl18xx.h index a6e61a25124d..96a1e438d677 100644 --- a/drivers/net/wireless/ti/wl18xx/wl18xx.h +++ b/drivers/net/wireless/ti/wl18xx/wl18xx.h @@ -38,6 +38,8 @@ #define WL18XX_NUM_TX_DESCRIPTORS 32 #define WL18XX_NUM_RX_DESCRIPTORS 32 +#define WL18XX_NUM_MAC_ADDRESSES 3 + struct wl18xx_priv { /* buffer for sending commands to FW */ u8 cmd_buf[WL18XX_CMD_MAX_SIZE]; diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index ae2b0fd7e558..dd0cbd9f6ce1 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5074,18 +5074,17 @@ static void wl1271_connection_loss_work(struct work_struct *work) mutex_unlock(&wl->mutex); } -static void wl12xx_derive_mac_addresses(struct wl1271 *wl, - u32 oui, u32 nic, int n) +static void wl12xx_derive_mac_addresses(struct wl1271 *wl, u32 oui, u32 nic) { int i; - wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x, n %d", - oui, nic, n); + wl1271_debug(DEBUG_PROBE, "base address: oui %06x nic %06x", + oui, nic); - if (nic + n - 1 > 0xffffff) + if (nic + WLCORE_NUM_MAC_ADDRESSES - wl->num_mac_addr > 0xffffff) wl1271_warning("NIC part of the MAC address wraps around!"); - for (i = 0; i < n; i++) { + for (i = 0; i < wl->num_mac_addr; i++) { wl->addresses[i].addr[0] = (u8)(oui >> 16); wl->addresses[i].addr[1] = (u8)(oui >> 8); wl->addresses[i].addr[2] = (u8) oui; @@ -5095,7 +5094,22 @@ static void wl12xx_derive_mac_addresses(struct wl1271 *wl, nic++; } - wl->hw->wiphy->n_addresses = n; + /* we may be one address short at the most */ + WARN_ON(wl->num_mac_addr + 1 < WLCORE_NUM_MAC_ADDRESSES); + + /* + * turn on the LAA bit in the first address and use it as + * the last address. + */ + if (wl->num_mac_addr < WLCORE_NUM_MAC_ADDRESSES) { + int idx = WLCORE_NUM_MAC_ADDRESSES - 1; + memcpy(&wl->addresses[idx], &wl->addresses[0], + sizeof(wl->addresses[0])); + /* LAA bit */ + wl->addresses[idx].addr[2] |= BIT(1); + } + + wl->hw->wiphy->n_addresses = WLCORE_NUM_MAC_ADDRESSES; wl->hw->wiphy->addresses = wl->addresses; } @@ -5155,7 +5169,7 @@ static int wl1271_register_hw(struct wl1271 *wl) nic_addr = wl->fuse_nic_addr + 1; } - wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr, 2); + wl12xx_derive_mac_addresses(wl, oui_addr, nic_addr); ret = ieee80211_register_hw(wl->hw); if (ret < 0) { diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index a7e9d5869db4..165afae2d9ad 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -31,6 +31,12 @@ /* The maximum number of Tx descriptors in all chip families */ #define WLCORE_MAX_TX_DESCRIPTORS 32 +/* + * We always allocate this number of mac addresses. If we don't + * have enough allocated addresses, the LAA bit is used + */ +#define WLCORE_NUM_MAC_ADDRESSES 3 + /* forward declaration */ struct wl1271_tx_hw_descr; enum wl_rx_buf_align; @@ -181,7 +187,7 @@ struct wl1271 { u32 fuse_nic_addr; /* we have up to 2 MAC addresses */ - struct mac_address addresses[2]; + struct mac_address addresses[WLCORE_NUM_MAC_ADDRESSES]; int channel; u8 system_hlid; @@ -394,6 +400,9 @@ struct wl1271 { /* sleep auth value currently configured to FW */ int sleep_auth; + /* the number of allocated MAC addresses in this chip */ + int num_mac_addr; + /* the minimum FW version required for the driver to work */ unsigned int min_fw_ver[NUM_FW_VER]; }; From fc3d1db5b60ebb81f9ce2ac3a1192f2c763ab504 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Thu, 2 Aug 2012 15:27:51 +0300 Subject: [PATCH 19/73] wlcore: make debug prints work without dynamic debug Make debug prints operational when dynamic debug is not defined. This allows better debugging in production environments. Change the driver prefix to "wlcore" while were at it. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/debug.h | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/debug.h b/drivers/net/wireless/ti/wlcore/debug.h index 6b800b3cbea5..db4bf5a68ce2 100644 --- a/drivers/net/wireless/ti/wlcore/debug.h +++ b/drivers/net/wireless/ti/wlcore/debug.h @@ -28,7 +28,7 @@ #include #include -#define DRIVER_NAME "wl12xx" +#define DRIVER_NAME "wlcore" #define DRIVER_PREFIX DRIVER_NAME ": " enum { @@ -73,11 +73,21 @@ extern u32 wl12xx_debug_level; #define wl1271_info(fmt, arg...) \ pr_info(DRIVER_PREFIX fmt "\n", ##arg) +/* define the debug macro differently if dynamic debug is supported */ +#if defined(CONFIG_DYNAMIC_DEBUG) #define wl1271_debug(level, fmt, arg...) \ do { \ - if (level & wl12xx_debug_level) \ - pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ + if (unlikely(level & wl12xx_debug_level)) \ + dynamic_pr_debug(DRIVER_PREFIX fmt "\n", ##arg); \ } while (0) +#else +#define wl1271_debug(level, fmt, arg...) \ + do { \ + if (unlikely(level & wl12xx_debug_level)) \ + printk(KERN_DEBUG pr_fmt(DRIVER_PREFIX fmt "\n"), \ + ##arg); \ + } while (0) +#endif /* TODO: use pr_debug_hex_dump when it becomes available */ #define wl1271_dump(level, prefix, buf, len) \ From 8dc574308b9172e2a38ac20319b7dd696b6d4741 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 26 Jul 2012 17:17:05 +0300 Subject: [PATCH 20/73] wlcore: always use wlvif->role_id for scans enabled (but not-started) sta role should be good enough for scanning (both normal and scheduled), so use it instead of the device_role. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/scan.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/scan.c b/drivers/net/wireless/ti/wlcore/scan.c index bc924877ca4d..d00501493dfe 100644 --- a/drivers/net/wireless/ti/wlcore/scan.c +++ b/drivers/net/wireless/ti/wlcore/scan.c @@ -184,11 +184,7 @@ static int wl1271_scan_send(struct wl1271 *wl, struct ieee80211_vif *vif, if (passive) scan_options |= WL1271_SCAN_OPT_PASSIVE; - if (wlvif->bss_type == BSS_TYPE_AP_BSS || - test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) - cmd->params.role_id = wlvif->role_id; - else - cmd->params.role_id = wlvif->dev_role_id; + cmd->params.role_id = wlvif->role_id; if (WARN_ON(cmd->params.role_id == WL12XX_INVALID_ROLE_ID)) { ret = -EINVAL; @@ -593,7 +589,7 @@ wl12xx_scan_sched_scan_ssid_list(struct wl1271 *wl, goto out; } - cmd->role_id = wlvif->dev_role_id; + cmd->role_id = wlvif->role_id; if (!n_match_ssids) { /* No filter, with ssids */ type = SCAN_SSID_FILTER_DISABLED; @@ -683,7 +679,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!cfg) return -ENOMEM; - cfg->role_id = wlvif->dev_role_id; + cfg->role_id = wlvif->role_id; cfg->rssi_threshold = c->rssi_threshold; cfg->snr_threshold = c->snr_threshold; cfg->n_probe_reqs = c->num_probe_reqs; @@ -718,7 +714,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!force_passive && cfg->active[0]) { u8 band = IEEE80211_BAND_2GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, - wlvif->dev_role_id, band, + wlvif->role_id, band, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[band], @@ -732,7 +728,7 @@ int wl1271_scan_sched_scan_config(struct wl1271 *wl, if (!force_passive && cfg->active[1]) { u8 band = IEEE80211_BAND_5GHZ; ret = wl12xx_cmd_build_probe_req(wl, wlvif, - wlvif->dev_role_id, band, + wlvif->role_id, band, req->ssids[0].ssid, req->ssids[0].ssid_len, ies->ie[band], @@ -774,7 +770,7 @@ int wl1271_scan_sched_scan_start(struct wl1271 *wl, struct wl12xx_vif *wlvif) if (!start) return -ENOMEM; - start->role_id = wlvif->dev_role_id; + start->role_id = wlvif->role_id; start->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_START_PERIODIC_SCAN, start, @@ -810,7 +806,7 @@ void wl1271_scan_sched_scan_stop(struct wl1271 *wl, struct wl12xx_vif *wlvif) return; } - stop->role_id = wlvif->dev_role_id; + stop->role_id = wlvif->role_id; stop->tag = WL1271_SCAN_DEFAULT_TAG; ret = wl1271_cmd_send(wl, CMD_STOP_PERIODIC_SCAN, stop, From 889300fa53702ce3ed063eeadddfa7775afc8cde Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 26 Jul 2012 17:17:06 +0300 Subject: [PATCH 21/73] wlcore: lazy-enable device roles Enable device roles just before starting it. This way, a single device role should be enough for all vifs, as we can't use concurrent device roles (which require ROC) anyway. Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/cmd.c | 16 +++++++++++++++- drivers/net/wireless/ti/wlcore/main.c | 19 ------------------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index b63995da7e45..4c07a5bced9c 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -1788,10 +1788,17 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) wlvif->bss_type == BSS_TYPE_IBSS))) return -EINVAL; - ret = wl12xx_cmd_role_start_dev(wl, wlvif); + ret = wl12xx_cmd_role_enable(wl, + wl12xx_wlvif_to_vif(wlvif)->addr, + WL1271_ROLE_DEVICE, + &wlvif->dev_role_id); if (ret < 0) goto out; + ret = wl12xx_cmd_role_start_dev(wl, wlvif); + if (ret < 0) + goto out_disable; + ret = wl12xx_roc(wl, wlvif, wlvif->dev_role_id); if (ret < 0) goto out_stop; @@ -1800,6 +1807,8 @@ int wl12xx_start_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) out_stop: wl12xx_cmd_role_stop_dev(wl, wlvif); +out_disable: + wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); out: return ret; } @@ -1827,6 +1836,11 @@ int wl12xx_stop_dev(struct wl1271 *wl, struct wl12xx_vif *wlvif) ret = wl12xx_cmd_role_stop_dev(wl, wlvif); if (ret < 0) goto out; + + ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); + if (ret < 0) + goto out; + out: return ret; } diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index dd0cbd9f6ce1..09f0e44f21b3 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -2273,21 +2273,6 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw, } } - if (wlvif->bss_type == BSS_TYPE_STA_BSS || - wlvif->bss_type == BSS_TYPE_IBSS) { - /* - * The device role is a special role used for - * rx and tx frames prior to association (as - * the STA role can get packets only from - * its associated bssid) - */ - ret = wl12xx_cmd_role_enable(wl, vif->addr, - WL1271_ROLE_DEVICE, - &wlvif->dev_role_id); - if (ret < 0) - goto out; - } - ret = wl12xx_cmd_role_enable(wl, vif->addr, role_type, &wlvif->role_id); if (ret < 0) @@ -2356,10 +2341,6 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wlvif->bss_type == BSS_TYPE_IBSS) { if (wl12xx_dev_role_started(wlvif)) wl12xx_stop_dev(wl, wlvif); - - ret = wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id); - if (ret < 0) - goto deinit; } ret = wl12xx_cmd_role_disable(wl, &wlvif->role_id); From e7a6ba29d3a1610a5e9706e1892a07ad74b34c9a Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Thu, 2 Aug 2012 22:00:34 +0300 Subject: [PATCH 22/73] wlcore: allow up to 3 running STA interfaces in combinations This allows us to have a p2p-management interface (in STA mode), as we as a group dedicated interface. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 09f0e44f21b3..7b825e8c1a9b 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5180,7 +5180,7 @@ static void wl1271_unregister_hw(struct wl1271 *wl) static const struct ieee80211_iface_limit wlcore_iface_limits[] = { { - .max = 2, + .max = 3, .types = BIT(NL80211_IFTYPE_STATION), }, { @@ -5195,7 +5195,7 @@ static const struct ieee80211_iface_combination wlcore_iface_combinations[] = { { .num_different_channels = 1, - .max_interfaces = 2, + .max_interfaces = 3, .limits = wlcore_iface_limits, .n_limits = ARRAY_SIZE(wlcore_iface_limits), }, From e166de556f7795a3061e49deca28d61b3764d512 Mon Sep 17 00:00:00 2001 From: Yair Shapira Date: Sun, 5 Aug 2012 16:51:16 +0300 Subject: [PATCH 23/73] wl18xx: number_of_assembled_ant5 indicates if A band is enabled Use number_of_assembled_ant5 phy param to indicate if A band is enabled: if number_of_assembled_ant5 != 0 then it is enabled otherwise it is disabled. This aligns with phy implementation that uses this param both to indicate if band is active and the number of antennas. This parameter replaces enable_11a module param that was removed. User-Space applications can use wlconf and/or INI files to disable A band using this parameter. Signed-off-by: Yair Shapira Signed-off-by: Igal Chernobelsky Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 93b148fe17a3..ae6920bc6a40 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -45,7 +45,6 @@ static char *ht_mode_param = NULL; static char *board_type_param = NULL; static bool checksum_param = false; -static bool enable_11a_param = true; static int num_rx_desc_param = -1; /* phy paramters */ @@ -1502,7 +1501,8 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) wl18xx_ops.init_vif = NULL; } - wl->enable_11a = enable_11a_param; + /* Enable 11a Band only if we have 5G antennas */ + wl->enable_11a = (priv->conf.phy.number_of_assembled_ant5 != 0); return wlcore_probe(wl, pdev); @@ -1539,9 +1539,6 @@ MODULE_PARM_DESC(board_type, "Board type: fpga, hdk (default), evb, com8 or " module_param_named(checksum, checksum_param, bool, S_IRUSR); MODULE_PARM_DESC(checksum, "Enable TCP checksum: boolean (defaults to false)"); -module_param_named(enable_11a, enable_11a_param, bool, S_IRUSR); -MODULE_PARM_DESC(enable_11a, "Enable 11a (5GHz): boolean (defaults to true)"); - module_param_named(dc2dc, dc2dc_param, int, S_IRUSR); MODULE_PARM_DESC(dc2dc, "External DC2DC: u8 (defaults to 0)"); From 61932ba59f5278e3f0c9fbded1a1af39ef89333f Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Mon, 6 Aug 2012 11:21:39 +0300 Subject: [PATCH 24/73] wlcore: spi: use private max-buf-size limit Limit SPI transmissions to the wl12xx max buffer size, as only 12xx was tested with SPI. This allows us to remove the global aggregation buffer constant. Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/spi.c | 10 ++++++++-- drivers/net/wireless/ti/wlcore/wlcore_i.h | 2 -- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c index 8da4ed243ebc..a519bc3adec1 100644 --- a/drivers/net/wireless/ti/wlcore/spi.c +++ b/drivers/net/wireless/ti/wlcore/spi.c @@ -66,7 +66,13 @@ /* HW limitation: maximum possible chunk size is 4095 bytes */ #define WSPI_MAX_CHUNK_SIZE 4092 -#define WSPI_MAX_NUM_OF_CHUNKS (WL1271_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) +/* + * only support SPI for 12xx - this code should be reworked when 18xx + * support is introduced + */ +#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE) + +#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) struct wl12xx_spi_glue { struct device *dev; @@ -271,7 +277,7 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr, u32 chunk_len; int i; - WARN_ON(len > WL1271_AGGR_BUFFER_SIZE); + WARN_ON(len > SPI_AGGR_BUFFER_SIZE); spi_message_init(&m); memset(t, 0, sizeof(t)); diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 58fbdcac6452..a7472bf8e8ba 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -83,8 +83,6 @@ #define WL1271_AP_BSS_INDEX 0 #define WL1271_AP_DEF_BEACON_EXP 20 -#define WL1271_AGGR_BUFFER_SIZE (5 * PAGE_SIZE) - enum wlcore_state { WLCORE_STATE_OFF, WLCORE_STATE_RESTARTING, From 1defbeb0426b5ca6280369b8fa89f0170420ff40 Mon Sep 17 00:00:00 2001 From: Yair Shapira Date: Tue, 7 Aug 2012 17:38:21 +0300 Subject: [PATCH 25/73] wlcore/wl18xx: add phy_fw_version_str to debugfs driver_state add phy_fw_version_str to debugfs driver_state file. information is taken during boot and stored in wl->chip.phy_fw_ver_str. Signed-off-by: Yair Shapira Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 6 ++++++ drivers/net/wireless/ti/wlcore/debugfs.c | 1 + drivers/net/wireless/ti/wlcore/wlcore_i.h | 1 + 3 files changed, 8 insertions(+) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index ae6920bc6a40..fa7e6ef3f6a2 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1201,6 +1201,12 @@ static int wl18xx_handle_static_data(struct wl1271 *wl, struct wl18xx_static_data_priv *static_data_priv = (struct wl18xx_static_data_priv *) static_data->priv; + strncpy(wl->chip.phy_fw_ver_str, static_data_priv->phy_version, + sizeof(wl->chip.phy_fw_ver_str)); + + /* make sure the string is NULL-terminated */ + wl->chip.phy_fw_ver_str[sizeof(wl->chip.phy_fw_ver_str) - 1] = '\0'; + wl1271_info("PHY firmware version: %s", static_data_priv->phy_version); return 0; diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 3b7e0e817984..3d39784d639b 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -489,6 +489,7 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf, DRIVER_STATE_PRINT_HEX(platform_quirks); 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(sched_scanning); #undef DRIVER_STATE_PRINT_INT diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index a7472bf8e8ba..496e7c666332 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -123,6 +123,7 @@ struct wl1271_chip { u32 id; char fw_ver_str[ETHTOOL_BUSINFO_LEN]; unsigned int fw_ver[NUM_FW_VER]; + char phy_fw_ver_str[ETHTOOL_BUSINFO_LEN]; }; #define NUM_TX_QUEUES 4 From 792a58a8720f02c8f340583f6ee54c9eb46adf0b Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Wed, 15 Aug 2012 15:09:30 +0300 Subject: [PATCH 26/73] wlcore: Don't recover during boot While recursive recovery is avoided during shutdown, a new recovery may be queued when the FW boots. The recovery work will then try to stop an already stopped hardware, which will most likely result in a kernel panic. Fix this by verifying that wl->state is on before queueing a new recovery. Signed-off-by: Ido Yariv Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 7b825e8c1a9b..3f5d87e95d92 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -775,8 +775,9 @@ void wl12xx_queue_recovery_work(struct wl1271 *wl) WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); /* Avoid a recursive recovery */ - if (!test_and_set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) { + if (wl->state == WLCORE_STATE_ON) { wl->state = WLCORE_STATE_RESTARTING; + set_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags); wlcore_disable_interrupts_nosync(wl); ieee80211_queue_work(wl->hw, &wl->recovery_work); } From a8311c8a9a7c41de9cc2d5e1573ff7005b4959ab Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Wed, 15 Aug 2012 18:29:04 +0300 Subject: [PATCH 27/73] wlcore: Fix unbalanced interrupts enablement The interrupt line is enabled by wl12xx_enable_interrupts and wl18xx_enable_interrupts, but it will not be disabled in all failure paths. Fix this. Signed-off-by: Ido Yariv Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 9 ++++++++- drivers/net/wireless/ti/wl18xx/main.c | 7 +++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index f49ce7c633b6..630b4d4cea04 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1184,9 +1184,16 @@ static int wl12xx_enable_interrupts(struct wl1271 *wl) ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL & ~(WL12XX_INTR_MASK)); if (ret < 0) - goto out; + goto disable_interrupts; ret = wlcore_write32(wl, WL12XX_HI_CFG, HI_CFG_DEF_VAL); + if (ret < 0) + goto disable_interrupts; + + return ret; + +disable_interrupts: + wlcore_disable_interrupts(wl); out: return ret; diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index fa7e6ef3f6a2..9bf2d8755c5b 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -811,6 +811,13 @@ static int wl18xx_enable_interrupts(struct wl1271 *wl) ret = wlcore_write_reg(wl, REG_INTERRUPT_MASK, WL1271_ACX_INTR_ALL & ~intr_mask); + if (ret < 0) + goto disable_interrupts; + + return ret; + +disable_interrupts: + wlcore_disable_interrupts(wl); out: return ret; From 8c5dab1a8449428685414c0de494b77841571fd3 Mon Sep 17 00:00:00 2001 From: Arik Nemtsov Date: Wed, 15 Aug 2012 19:11:43 +0300 Subject: [PATCH 28/73] wl18xx: default to siso40 in 2.4ghz with a single antenna The driver used siso20 in this case for legacy reasons. Reported-by: Ido Reis Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 9bf2d8755c5b..44e5cadc8f32 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1485,14 +1485,14 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) if (priv->conf.ht.mode == HT_MODE_DEFAULT) { /* * Only support mimo with multiple antennas. Fall back to - * siso20. + * siso40. */ if (wl18xx_is_mimo_supported(wl)) wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, &wl18xx_mimo_ht_cap_2ghz); else wlcore_set_ht_cap(wl, IEEE80211_BAND_2GHZ, - &wl18xx_siso20_ht_cap); + &wl18xx_siso40_ht_cap_2ghz); /* 5Ghz is always wide */ wlcore_set_ht_cap(wl, IEEE80211_BAND_5GHZ, From 4137c17c8c88eca51a9e9d53c5eea0ea3d49940e Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 16 Aug 2012 13:32:32 +0300 Subject: [PATCH 29/73] wlcore: invalidate keep-alive template on disconnection Previously, invalidation of the keep-alive template was done when going idle. However, while removing the idle-handling we didn't move the keep-alive template invalidation to another place. This finally resulted in fw error when trying to use the keep-alive template by another role. (Note that we still have an error here - each role should have its unique keep-alive template id, while currently they all use CMD_TEMPL_KLV_IDX_NULL_DATA (0). This only works now because we don't support concurrent connected stations yet) Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 3f5d87e95d92..7c04b0b15b60 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -2544,6 +2544,11 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) ieee80211_chswitch_done(vif, false); } + /* invalidate keep-alive template */ + wl1271_acx_keep_alive_config(wl, wlvif, + CMD_TEMPL_KLV_IDX_NULL_DATA, + ACX_KEEP_ALIVE_TPL_INVALID); + /* to stop listening to a channel, we disconnect */ ret = wl12xx_cmd_role_stop_sta(wl, wlvif); if (ret < 0) From 001e39a8effd5a9774153ca6ca67849a93b95852 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Thu, 16 Aug 2012 13:52:47 +0300 Subject: [PATCH 30/73] wlcore: use dynamic keep-alive template ids Currently, all the (station) roles use the same keep-alive template id (0). However, the klv template ids shouldn't be shared by different roles. Implement a simple klv_templates bitmap, and let each role allocate its own klv template id on role initialization. [Arik - remove invalidation of KLV template when getting into "idle". This is already handled in unjoin] Signed-off-by: Eliad Peller Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/cmd.c | 2 +- drivers/net/wireless/ti/wlcore/cmd.h | 5 ---- drivers/net/wireless/ti/wlcore/init.c | 12 ++------- drivers/net/wireless/ti/wlcore/main.c | 32 ++++++++++++++++++----- drivers/net/wireless/ti/wlcore/wlcore.h | 2 ++ drivers/net/wireless/ti/wlcore/wlcore_i.h | 3 +++ 6 files changed, 33 insertions(+), 23 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 4c07a5bced9c..eaef3f41b252 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c @@ -993,7 +993,7 @@ int wl12xx_cmd_build_klv_null_data(struct wl1271 *wl, ret = wl1271_cmd_template_set(wl, wlvif->role_id, CMD_TEMPL_KLV, skb->data, skb->len, - CMD_TEMPL_KLV_IDX_NULL_DATA, + wlvif->sta.klv_template_id, wlvif->basic_rate); out: diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index 4ef0b095f0d6..2409f3d71f63 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h @@ -157,11 +157,6 @@ enum wl1271_commands { #define MAX_CMD_PARAMS 572 -enum { - CMD_TEMPL_KLV_IDX_NULL_DATA = 0, - CMD_TEMPL_KLV_IDX_MAX = 4 -}; - enum cmd_templ { CMD_TEMPL_NULL_DATA = 0, CMD_TEMPL_BEACON, diff --git a/drivers/net/wireless/ti/wlcore/init.c b/drivers/net/wireless/ti/wlcore/init.c index a3c867786df8..32d157f62f31 100644 --- a/drivers/net/wireless/ti/wlcore/init.c +++ b/drivers/net/wireless/ti/wlcore/init.c @@ -141,7 +141,7 @@ int wl1271_init_templates_config(struct wl1271 *wl) if (ret < 0) return ret; - for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { + for (i = 0; i < WLCORE_MAX_KLV_TEMPLATES; i++) { ret = wl1271_cmd_template_set(wl, WL12XX_INVALID_ROLE_ID, CMD_TEMPL_KLV, NULL, sizeof(struct ieee80211_qos_hdr), @@ -371,15 +371,7 @@ static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl, struct ieee80211_vif *vif) { struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); - int ret, i; - - /* disable all keep-alive templates */ - for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) { - ret = wl1271_acx_keep_alive_config(wl, wlvif, i, - ACX_KEEP_ALIVE_TPL_INVALID); - if (ret < 0) - return ret; - } + int ret; /* disable the keep-alive feature */ ret = wl1271_acx_keep_alive_mode(wl, wlvif, false); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 7c04b0b15b60..419c399a272e 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -1965,6 +1965,27 @@ static void wl12xx_free_rate_policy(struct wl1271 *wl, u8 *idx) *idx = WL12XX_MAX_RATE_POLICIES; } +static int wlcore_allocate_klv_template(struct wl1271 *wl, u8 *idx) +{ + u8 policy = find_first_zero_bit(wl->klv_templates_map, + WLCORE_MAX_KLV_TEMPLATES); + if (policy >= WLCORE_MAX_KLV_TEMPLATES) + return -EBUSY; + + __set_bit(policy, wl->klv_templates_map); + *idx = policy; + return 0; +} + +static void wlcore_free_klv_template(struct wl1271 *wl, u8 *idx) +{ + if (WARN_ON(*idx >= WLCORE_MAX_KLV_TEMPLATES)) + return; + + __clear_bit(*idx, wl->klv_templates_map); + *idx = WLCORE_MAX_KLV_TEMPLATES; +} + static u8 wl12xx_get_role_type(struct wl1271 *wl, struct wl12xx_vif *wlvif) { switch (wlvif->bss_type) { @@ -2029,6 +2050,7 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif) wl12xx_allocate_rate_policy(wl, &wlvif->sta.basic_rate_idx); wl12xx_allocate_rate_policy(wl, &wlvif->sta.ap_rate_idx); wl12xx_allocate_rate_policy(wl, &wlvif->sta.p2p_rate_idx); + wlcore_allocate_klv_template(wl, &wlvif->sta.klv_template_id); wlvif->basic_rate_set = CONF_TX_RATE_MASK_BASIC; wlvif->basic_rate = CONF_TX_RATE_MASK_BASIC; wlvif->rate_set = CONF_TX_RATE_MASK_BASIC; @@ -2360,6 +2382,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl, wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx); wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx); wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx); + wlcore_free_klv_template(wl, &wlvif->sta.klv_template_id); } else { wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID; wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID; @@ -2524,7 +2547,7 @@ static int wl1271_join(struct wl1271 *wl, struct wl12xx_vif *wlvif, goto out; ret = wl1271_acx_keep_alive_config(wl, wlvif, - CMD_TEMPL_KLV_IDX_NULL_DATA, + wlvif->sta.klv_template_id, ACX_KEEP_ALIVE_TPL_VALID); if (ret < 0) goto out; @@ -2546,7 +2569,7 @@ static int wl1271_unjoin(struct wl1271 *wl, struct wl12xx_vif *wlvif) /* invalidate keep-alive template */ wl1271_acx_keep_alive_config(wl, wlvif, - CMD_TEMPL_KLV_IDX_NULL_DATA, + wlvif->sta.klv_template_id, ACX_KEEP_ALIVE_TPL_INVALID); /* to stop listening to a channel, we disconnect */ @@ -2587,11 +2610,6 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, struct wl12xx_vif *wlvif, wlvif->rate_set = wl1271_tx_min_rate_get(wl, wlvif->basic_rate_set); ret = wl1271_acx_sta_rate_policies(wl, wlvif); - if (ret < 0) - goto out; - ret = wl1271_acx_keep_alive_config( - wl, wlvif, CMD_TEMPL_KLV_IDX_NULL_DATA, - ACX_KEEP_ALIVE_TPL_INVALID); if (ret < 0) goto out; clear_bit(WLVIF_FLAG_IN_USE, &wlvif->flags); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 165afae2d9ad..8ad5f37329d7 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -196,6 +196,8 @@ struct wl1271 { unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)]; unsigned long rate_policies_map[ BITS_TO_LONGS(WL12XX_MAX_RATE_POLICIES)]; + unsigned long klv_templates_map[ + BITS_TO_LONGS(WLCORE_MAX_KLV_TEMPLATES)]; struct list_head wlvif_list; diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h index 496e7c666332..6678d4b18611 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore_i.h +++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h @@ -66,6 +66,7 @@ #define WLCORE_NUM_BANDS 2 #define WL12XX_MAX_RATE_POLICIES 16 +#define WLCORE_MAX_KLV_TEMPLATES 4 /* Defined by FW as 0. Will not be freed or allocated. */ #define WL12XX_SYSTEM_HLID 0 @@ -337,6 +338,8 @@ struct wl12xx_vif { u8 ap_rate_idx; u8 p2p_rate_idx; + u8 klv_template_id; + bool qos; } sta; struct { From d556023895c8968fd97ccb08300006b78975a23b Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Tue, 21 Aug 2012 17:17:13 +0300 Subject: [PATCH 31/73] wlcore: Allow memory access when the FW crashes When the no_recovery flag is used, the recovery work will not restart the FW and the state will not be set to 'on'. To enable post-mortem analysis, allow memory access in the 'restarting' state. Also, since the FW might not be operational, don't fail the read/write operations if elp_wakeup fails. Reported-by: Arkady Miasnikov Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/debugfs.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/debugfs.c b/drivers/net/wireless/ti/wlcore/debugfs.c index 3d39784d639b..c86bb00c2488 100644 --- a/drivers/net/wireless/ti/wlcore/debugfs.c +++ b/drivers/net/wireless/ti/wlcore/debugfs.c @@ -1064,14 +1064,16 @@ static ssize_t dev_mem_read(struct file *file, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (unlikely(wl->state == WLCORE_STATE_OFF)) { ret = -EFAULT; goto skip_read; } - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto skip_read; + /* + * Don't fail if elp_wakeup returns an error, so the device's memory + * could be read even if the FW crashed + */ + wl1271_ps_elp_wakeup(wl); /* store current partition and switch partition */ memcpy(&old_part, &wl->curr_part, sizeof(old_part)); @@ -1149,14 +1151,16 @@ static ssize_t dev_mem_write(struct file *file, const char __user *user_buf, mutex_lock(&wl->mutex); - if (unlikely(wl->state != WLCORE_STATE_ON)) { + if (unlikely(wl->state == WLCORE_STATE_OFF)) { ret = -EFAULT; goto skip_write; } - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto skip_write; + /* + * Don't fail if elp_wakeup returns an error, so the device's memory + * could be read even if the FW crashed + */ + wl1271_ps_elp_wakeup(wl); /* store current partition and switch partition */ memcpy(&old_part, &wl->curr_part, sizeof(old_part)); From 3992eb2bf2b1f6d244cf527c922c0cbd810e69c5 Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Sun, 2 Sep 2012 12:29:27 +0300 Subject: [PATCH 32/73] wlcore: Refactor probe Move most of the device-specific probe functionality into setup(), a new op. By doing this, wlcore_probe will be the first to request a firmware from userspace, making it easier to load the NVS file asynchronously. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl12xx/main.c | 52 +++++++++++++++------- drivers/net/wireless/ti/wl18xx/main.c | 59 +++++++++++++++---------- drivers/net/wireless/ti/wlcore/main.c | 18 ++++---- drivers/net/wireless/ti/wlcore/wlcore.h | 2 + 4 files changed, 83 insertions(+), 48 deletions(-) diff --git a/drivers/net/wireless/ti/wl12xx/main.c b/drivers/net/wireless/ti/wl12xx/main.c index 630b4d4cea04..dadf1dbb002a 100644 --- a/drivers/net/wireless/ti/wl12xx/main.c +++ b/drivers/net/wireless/ti/wl12xx/main.c @@ -1589,7 +1589,10 @@ static int wl12xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, return wlcore_set_key(wl, cmd, vif, sta, key_conf); } +static int wl12xx_setup(struct wl1271 *wl); + static struct wlcore_ops wl12xx_ops = { + .setup = wl12xx_setup, .identify_chip = wl12xx_identify_chip, .identify_fw = wl12xx_identify_fw, .boot = wl12xx_boot, @@ -1630,23 +1633,11 @@ static struct ieee80211_sta_ht_cap wl12xx_ht_cap = { }, }; -static int __devinit wl12xx_probe(struct platform_device *pdev) +static int wl12xx_setup(struct wl1271 *wl) { - struct wl12xx_platform_data *pdata = pdev->dev.platform_data; - struct wl1271 *wl; - struct ieee80211_hw *hw; - struct wl12xx_priv *priv; + struct wl12xx_priv *priv = wl->priv; + struct wl12xx_platform_data *pdata = wl->pdev->dev.platform_data; - hw = wlcore_alloc_hw(sizeof(*priv), WL12XX_AGGR_BUFFER_SIZE); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - return PTR_ERR(hw); - } - - wl = hw->priv; - priv = wl->priv; - wl->ops = &wl12xx_ops; - wl->ptable = wl12xx_ptable; wl->rtable = wl12xx_rtable; wl->num_tx_desc = WL12XX_NUM_TX_DESCRIPTORS; wl->num_rx_desc = WL12XX_NUM_RX_DESCRIPTORS; @@ -1702,7 +1693,36 @@ static int __devinit wl12xx_probe(struct platform_device *pdev) wl1271_error("Invalid tcxo parameter %s", tcxo_param); } - return wlcore_probe(wl, pdev); + return 0; +} + +static int __devinit wl12xx_probe(struct platform_device *pdev) +{ + struct wl1271 *wl; + struct ieee80211_hw *hw; + int ret; + + hw = wlcore_alloc_hw(sizeof(struct wl12xx_priv), + WL12XX_AGGR_BUFFER_SIZE); + if (IS_ERR(hw)) { + wl1271_error("can't allocate hw"); + ret = PTR_ERR(hw); + goto out; + } + + wl = hw->priv; + wl->ops = &wl12xx_ops; + wl->ptable = wl12xx_ptable; + ret = wlcore_probe(wl, pdev); + if (ret) + goto out_free; + + return ret; + +out_free: + wlcore_free_hw(wl); +out: + return ret; } static const struct platform_device_id wl12xx_id_table[] __devinitconst = { diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 44e5cadc8f32..9e3e10a13498 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1304,7 +1304,10 @@ static u32 wl18xx_pre_pkt_send(struct wl1271 *wl, return buf_offset; } +static int wl18xx_setup(struct wl1271 *wl); + static struct wlcore_ops wl18xx_ops = { + .setup = wl18xx_setup, .identify_chip = wl18xx_identify_chip, .boot = wl18xx_boot, .plt_init = wl18xx_plt_init, @@ -1385,24 +1388,11 @@ static struct ieee80211_sta_ht_cap wl18xx_mimo_ht_cap_2ghz = { }, }; -static int __devinit wl18xx_probe(struct platform_device *pdev) +static int wl18xx_setup(struct wl1271 *wl) { - struct wl1271 *wl; - struct ieee80211_hw *hw; - struct wl18xx_priv *priv; + struct wl18xx_priv *priv = wl->priv; int ret; - hw = wlcore_alloc_hw(sizeof(*priv), WL18XX_AGGR_BUFFER_SIZE); - if (IS_ERR(hw)) { - wl1271_error("can't allocate hw"); - ret = PTR_ERR(hw); - goto out; - } - - wl = hw->priv; - priv = wl->priv; - wl->ops = &wl18xx_ops; - wl->ptable = wl18xx_ptable; wl->rtable = wl18xx_rtable; wl->num_tx_desc = WL18XX_NUM_TX_DESCRIPTORS; wl->num_rx_desc = WL18XX_NUM_TX_DESCRIPTORS; @@ -1417,9 +1407,9 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) if (num_rx_desc_param != -1) wl->num_rx_desc = num_rx_desc_param; - ret = wl18xx_conf_init(wl, &pdev->dev); + ret = wl18xx_conf_init(wl, wl->dev); if (ret < 0) - goto out_free; + return ret; /* If the module param is set, update it in conf */ if (board_type_param) { @@ -1436,16 +1426,14 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) } else { wl1271_error("invalid board type '%s'", board_type_param); - ret = -EINVAL; - goto out_free; + return -EINVAL; } } if (priv->conf.phy.board_type >= NUM_BOARD_TYPES) { wl1271_error("invalid board type '%d'", priv->conf.phy.board_type); - ret = -EINVAL; - goto out_free; + return -EINVAL; } if (low_band_component_param != -1) @@ -1477,8 +1465,7 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) priv->conf.ht.mode = HT_MODE_SISO20; else { wl1271_error("invalid ht_mode '%s'", ht_mode_param); - ret = -EINVAL; - goto out_free; + return -EINVAL; } } @@ -1517,7 +1504,31 @@ static int __devinit wl18xx_probe(struct platform_device *pdev) /* Enable 11a Band only if we have 5G antennas */ wl->enable_11a = (priv->conf.phy.number_of_assembled_ant5 != 0); - return wlcore_probe(wl, pdev); + return 0; +} + +static int __devinit wl18xx_probe(struct platform_device *pdev) +{ + struct wl1271 *wl; + struct ieee80211_hw *hw; + int ret; + + hw = wlcore_alloc_hw(sizeof(struct wl18xx_priv), + WL18XX_AGGR_BUFFER_SIZE); + if (IS_ERR(hw)) { + wl1271_error("can't allocate hw"); + ret = PTR_ERR(hw); + goto out; + } + + wl = hw->priv; + wl->ops = &wl18xx_ops; + wl->ptable = wl18xx_ptable; + ret = wlcore_probe(wl, pdev); + if (ret) + goto out_free; + + return ret; out_free: wlcore_free_hw(wl); diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 419c399a272e..7db6384a2457 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -5547,9 +5547,17 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) if (!wl->ops || !wl->ptable) { ret = -EINVAL; - goto out_free_hw; + goto out; } + wl->dev = &pdev->dev; + wl->pdev = pdev; + platform_set_drvdata(pdev, wl); + + ret = wl->ops->setup(wl); + if (ret < 0) + goto out; + BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS); /* adjust some runtime configuration parameters */ @@ -5558,11 +5566,8 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) wl->irq = platform_get_irq(pdev, 0); wl->platform_quirks = pdata->platform_quirks; wl->set_power = pdata->set_power; - wl->dev = &pdev->dev; wl->if_ops = pdata->ops; - platform_set_drvdata(pdev, wl); - if (wl->platform_quirks & WL12XX_PLATFORM_QUIRK_EDGE_IRQ) irqflags = IRQF_TRIGGER_RISING; else @@ -5573,7 +5578,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) pdev->name, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); - goto out_free_hw; + goto out; } #ifdef CONFIG_PM @@ -5646,9 +5651,6 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) out_irq: free_irq(wl->irq, wl); -out_free_hw: - wlcore_free_hw(wl); - out: return ret; } diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 8ad5f37329d7..6a0455616289 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -43,6 +43,7 @@ enum wl_rx_buf_align; struct wl1271_rx_descriptor; struct wlcore_ops { + int (*setup)(struct wl1271 *wl); int (*identify_chip)(struct wl1271 *wl); int (*identify_fw)(struct wl1271 *wl); int (*boot)(struct wl1271 *wl); @@ -149,6 +150,7 @@ struct wl1271 { bool mac80211_registered; struct device *dev; + struct platform_device *pdev; void *if_priv; From 6f8d6b20bb0bdda333e781faf775db14cb4660dd Mon Sep 17 00:00:00 2001 From: Ido Yariv Date: Sun, 2 Sep 2012 01:32:47 +0300 Subject: [PATCH 33/73] wlcore: Load the NVS file asynchronously The NVS file is loaded by the device's probe callback with the help of request_firmware(). Since request_firmware() relies on udevd, the modules cannot be loaded before hotplug events are handled. Fix this by loading the NVS file asynchronously and continue initialization only after the firmware request is over. Signed-off-by: Ido Yariv Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/main.c | 88 ++++++++++++++----------- drivers/net/wireless/ti/wlcore/wlcore.h | 3 + 2 files changed, 53 insertions(+), 38 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 7db6384a2457..6ada018fe4a4 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -744,32 +744,6 @@ static int wl12xx_fetch_firmware(struct wl1271 *wl, bool plt) return ret; } -static void wl1271_fetch_nvs(struct wl1271 *wl) -{ - const struct firmware *fw; - int ret; - - ret = request_firmware(&fw, WL12XX_NVS_NAME, wl->dev); - - if (ret < 0) { - wl1271_debug(DEBUG_BOOT, "could not get nvs file %s: %d", - WL12XX_NVS_NAME, ret); - return; - } - - wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); - - if (!wl->nvs) { - wl1271_error("could not allocate memory for the nvs file"); - goto out; - } - - wl->nvs_len = fw->size; - -out: - release_firmware(fw); -} - void wl12xx_queue_recovery_work(struct wl1271 *wl) { WARN_ON(!test_bit(WL1271_FLAG_INTENDED_FW_RECOVERY, &wl->flags)); @@ -5153,8 +5127,7 @@ static int wl1271_register_hw(struct wl1271 *wl) if (wl->mac80211_registered) return 0; - wl1271_fetch_nvs(wl); - if (wl->nvs != NULL) { + if (wl->nvs_len >= 12) { /* NOTE: The wl->nvs->nvs element must be first, in * order to simplify the casting, we assume it is at * the beginning of the wl->nvs structure. @@ -5419,6 +5392,7 @@ struct ieee80211_hw *wlcore_alloc_hw(size_t priv_size, u32 aggr_buf_size) wl->fw_type = WL12XX_FW_TYPE_NONE; mutex_init(&wl->mutex); mutex_init(&wl->flush_mutex); + init_completion(&wl->nvs_loading_complete); order = get_order(aggr_buf_size); wl->aggr_buf = (u8 *)__get_free_pages(GFP_KERNEL, order); @@ -5539,24 +5513,31 @@ static irqreturn_t wl12xx_hardirq(int irq, void *cookie) return IRQ_WAKE_THREAD; } -int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) +static void wlcore_nvs_cb(const struct firmware *fw, void *context) { + struct wl1271 *wl = context; + struct platform_device *pdev = wl->pdev; struct wl12xx_platform_data *pdata = pdev->dev.platform_data; unsigned long irqflags; int ret; - if (!wl->ops || !wl->ptable) { - ret = -EINVAL; - goto out; + if (fw) { + wl->nvs = kmemdup(fw->data, fw->size, GFP_KERNEL); + if (!wl->nvs) { + wl1271_error("Could not allocate nvs data"); + goto out; + } + wl->nvs_len = fw->size; + } else { + wl1271_debug(DEBUG_BOOT, "Could not get nvs file %s", + WL12XX_NVS_NAME); + wl->nvs = NULL; + wl->nvs_len = 0; } - wl->dev = &pdev->dev; - wl->pdev = pdev; - platform_set_drvdata(pdev, wl); - ret = wl->ops->setup(wl); if (ret < 0) - goto out; + goto out_free_nvs; BUG_ON(wl->num_tx_desc > WLCORE_MAX_TX_DESCRIPTORS); @@ -5578,7 +5559,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) pdev->name, wl); if (ret < 0) { wl1271_error("request_irq() failed: %d", ret); - goto out; + goto out_free_nvs; } #ifdef CONFIG_PM @@ -5637,6 +5618,7 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) goto out_hw_pg_ver; } + wl->initialized = true; goto out; out_hw_pg_ver: @@ -5651,7 +5633,33 @@ int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) out_irq: free_irq(wl->irq, wl); +out_free_nvs: + kfree(wl->nvs); + out: + release_firmware(fw); + complete_all(&wl->nvs_loading_complete); +} + +int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev) +{ + int ret; + + if (!wl->ops || !wl->ptable) + return -EINVAL; + + wl->dev = &pdev->dev; + wl->pdev = pdev; + platform_set_drvdata(pdev, wl); + + ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_HOTPLUG, + WL12XX_NVS_NAME, &pdev->dev, GFP_KERNEL, + wl, wlcore_nvs_cb); + if (ret < 0) { + wl1271_error("request_firmware_nowait failed: %d", ret); + complete_all(&wl->nvs_loading_complete); + } + return ret; } EXPORT_SYMBOL_GPL(wlcore_probe); @@ -5660,6 +5668,10 @@ int __devexit wlcore_remove(struct platform_device *pdev) { struct wl1271 *wl = platform_get_drvdata(pdev); + wait_for_completion(&wl->nvs_loading_complete); + if (!wl->initialized) + return 0; + if (wl->irq_wake_enabled) { device_init_wakeup(wl->dev, 0); disable_irq_wake(wl->irq); diff --git a/drivers/net/wireless/ti/wlcore/wlcore.h b/drivers/net/wireless/ti/wlcore/wlcore.h index 6a0455616289..68584aa0f2b0 100644 --- a/drivers/net/wireless/ti/wlcore/wlcore.h +++ b/drivers/net/wireless/ti/wlcore/wlcore.h @@ -146,6 +146,7 @@ struct wl1271_stats { }; struct wl1271 { + bool initialized; struct ieee80211_hw *hw; bool mac80211_registered; @@ -409,6 +410,8 @@ struct wl1271 { /* the minimum FW version required for the driver to work */ unsigned int min_fw_ver[NUM_FW_VER]; + + struct completion nvs_loading_complete; }; int __devinit wlcore_probe(struct wl1271 *wl, struct platform_device *pdev); From ab2c4f37dcef5bd517a95a32da50d5ed0cc24cb5 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Sun, 2 Sep 2012 13:30:04 +0300 Subject: [PATCH 34/73] wlcore: decrease elp timeout The current elp timeout (the same as the dynamic ps timeout - 1500ms) is too high. Usually, wl1271_ps_elp_sleep() get called right after tx/rx, which is fine, but some command might get sent even when there is no traffic (e.g. ht changes triggered by beacon frames), and leaving the device awake for 1500ms in this case is redundant. Use a timeout of 30ms. The fw won't enter elp anyway before the dynamic-ps timeout was expired as well (and it entered ps successfully). Signed-off-by: Eliad Peller Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wlcore/ps.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/ti/wlcore/ps.c b/drivers/net/wireless/ti/wlcore/ps.c index e904d68767e2..4d1414a673fb 100644 --- a/drivers/net/wireless/ti/wlcore/ps.c +++ b/drivers/net/wireless/ti/wlcore/ps.c @@ -28,7 +28,7 @@ #define WL1271_WAKEUP_TIMEOUT 500 -#define ELP_ENTRY_DELAY 5 +#define ELP_ENTRY_DELAY 30 void wl1271_elp_work(struct work_struct *work) { @@ -98,11 +98,7 @@ void wl1271_ps_elp_sleep(struct wl1271 *wl) return; } - if (wl->conf.conn.forced_ps) - timeout = ELP_ENTRY_DELAY; - else - timeout = wl->conf.conn.dynamic_ps_timeout; - + timeout = ELP_ENTRY_DELAY; ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, msecs_to_jiffies(timeout)); } From af390f4dd35373b3ca32bafc12d7f2ad12840529 Mon Sep 17 00:00:00 2001 From: Eliad Peller Date: Mon, 3 Sep 2012 18:27:58 +0300 Subject: [PATCH 35/73] wlcore: protect wlcore_op_set_key with mutex wlcore_op_set_key() calls wl18xx_set_key(), which in turn executes some of his function calls without acquiring wl->mutex and making sure the fw is awake. Adding mutex_lock()/ps_elp_wakeup() calls is not enough, as wl18xx_set_key() calls wl1271_tx_flush() which can't be called while the mutex is taken. Add the required calls to wlcore_op_set_key, but limit the queues_stop and flushing to the only encryption types in which a spare block might be needed (GEM and TKIP). [Arik - move state != ON check] Signed-off-by: Eliad Peller Signed-off-by: Arik Nemtsov Signed-off-by: Luciano Coelho --- drivers/net/wireless/ti/wl18xx/main.c | 8 ---- drivers/net/wireless/ti/wlcore/main.c | 68 +++++++++++++++++---------- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/drivers/net/wireless/ti/wl18xx/main.c b/drivers/net/wireless/ti/wl18xx/main.c index 9e3e10a13498..a39682a7c25f 100644 --- a/drivers/net/wireless/ti/wl18xx/main.c +++ b/drivers/net/wireless/ti/wl18xx/main.c @@ -1252,13 +1252,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, if (!change_spare) return wlcore_set_key(wl, cmd, vif, sta, key_conf); - /* - * stop the queues and flush to ensure the next packets are - * in sync with FW spare block accounting - */ - wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); - wl1271_tx_flush(wl); - ret = wlcore_set_key(wl, cmd, vif, sta, key_conf); if (ret < 0) goto out; @@ -1281,7 +1274,6 @@ static int wl18xx_set_key(struct wl1271 *wl, enum set_key_cmd cmd, } out: - wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); return ret; } diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 6ada018fe4a4..25530c8760cb 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c @@ -3063,8 +3063,45 @@ static int wlcore_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, struct ieee80211_key_conf *key_conf) { struct wl1271 *wl = hw->priv; + int ret; + bool might_change_spare = + key_conf->cipher == WL1271_CIPHER_SUITE_GEM || + key_conf->cipher == WLAN_CIPHER_SUITE_TKIP; - return wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); + if (might_change_spare) { + /* + * stop the queues and flush to ensure the next packets are + * in sync with FW spare block accounting + */ + mutex_lock(&wl->mutex); + wlcore_stop_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); + mutex_unlock(&wl->mutex); + + wl1271_tx_flush(wl); + } + + mutex_lock(&wl->mutex); + + if (unlikely(wl->state != WLCORE_STATE_ON)) { + ret = -EAGAIN; + goto out_wake_queues; + } + + ret = wl1271_ps_elp_wakeup(wl); + if (ret < 0) + goto out_wake_queues; + + ret = wlcore_hw_set_key(wl, cmd, vif, sta, key_conf); + + wl1271_ps_elp_sleep(wl); + +out_wake_queues: + if (might_change_spare) + wlcore_wake_queues(wl, WLCORE_QUEUE_STOP_REASON_SPARE_BLK); + + mutex_unlock(&wl->mutex); + + return ret; } int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, @@ -3086,17 +3123,6 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, key_conf->keylen, key_conf->flags); wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen); - mutex_lock(&wl->mutex); - - if (unlikely(wl->state != WLCORE_STATE_ON)) { - ret = -EAGAIN; - goto out_unlock; - } - - ret = wl1271_ps_elp_wakeup(wl); - if (ret < 0) - goto out_unlock; - switch (key_conf->cipher) { case WLAN_CIPHER_SUITE_WEP40: case WLAN_CIPHER_SUITE_WEP104: @@ -3126,8 +3152,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, default: wl1271_error("Unknown key algo 0x%x", key_conf->cipher); - ret = -EOPNOTSUPP; - goto out_sleep; + return -EOPNOTSUPP; } switch (cmd) { @@ -3138,7 +3163,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, tx_seq_32, tx_seq_16, sta); if (ret < 0) { wl1271_error("Could not add or replace key"); - goto out_sleep; + return ret; } /* @@ -3152,7 +3177,7 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, ret = wl1271_cmd_build_arp_rsp(wl, wlvif); if (ret < 0) { wl1271_warning("build arp rsp failed: %d", ret); - goto out_sleep; + return ret; } } break; @@ -3164,22 +3189,15 @@ int wlcore_set_key(struct wl1271 *wl, enum set_key_cmd cmd, 0, 0, sta); if (ret < 0) { wl1271_error("Could not remove key"); - goto out_sleep; + return ret; } break; default: wl1271_error("Unsupported key cmd 0x%x", cmd); - ret = -EOPNOTSUPP; - break; + return -EOPNOTSUPP; } -out_sleep: - wl1271_ps_elp_sleep(wl); - -out_unlock: - mutex_unlock(&wl->mutex); - return ret; } EXPORT_SYMBOL_GPL(wlcore_set_key); From 1fd41a65f19bdabb31549af00ce23d4c5c14781a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Tue, 25 Sep 2012 10:17:22 +0200 Subject: [PATCH 36/73] bcma: change delays to follow timers-howto guide MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: RafaÅ‚ MiÅ‚ecki Cc: Hauke Mehrtens Signed-off-by: John W. Linville --- drivers/bcma/core.c | 2 +- drivers/bcma/driver_chipcommon_pmu.c | 5 ++++- drivers/bcma/driver_pci.c | 6 +++--- drivers/bcma/driver_pci_host.c | 8 ++++---- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/bcma/core.c b/drivers/bcma/core.c index 63c8b470536f..03bbe104338f 100644 --- a/drivers/bcma/core.c +++ b/drivers/bcma/core.c @@ -65,7 +65,7 @@ void bcma_core_set_clockmode(struct bcma_device *core, switch (clkmode) { case BCMA_CLKMODE_FAST: bcma_set32(core, BCMA_CLKCTLST, BCMA_CLKCTLST_FORCEHT); - udelay(64); + usleep_range(64, 300); for (i = 0; i < 1500; i++) { if (bcma_read32(core, BCMA_CLKCTLST) & BCMA_CLKCTLST_HAVEHT) { diff --git a/drivers/bcma/driver_chipcommon_pmu.c b/drivers/bcma/driver_chipcommon_pmu.c index 8b8f2f3862a2..201faf106b3f 100644 --- a/drivers/bcma/driver_chipcommon_pmu.c +++ b/drivers/bcma/driver_chipcommon_pmu.c @@ -76,7 +76,10 @@ static void bcma_pmu_resources_init(struct bcma_drv_cc *cc) if (max_msk) bcma_cc_write32(cc, BCMA_CC_PMU_MAXRES_MSK, max_msk); - /* Add some delay; allow resources to come up and settle. */ + /* + * Add some delay; allow resources to come up and settle. + * Delay is required for SoC (early init). + */ mdelay(2); } diff --git a/drivers/bcma/driver_pci.c b/drivers/bcma/driver_pci.c index c32ebd537abe..c39ee6d45850 100644 --- a/drivers/bcma/driver_pci.c +++ b/drivers/bcma/driver_pci.c @@ -51,7 +51,7 @@ static void bcma_pcie_mdio_set_phy(struct bcma_drv_pci *pc, u8 phy) v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) break; - msleep(1); + usleep_range(1000, 2000); } } @@ -92,7 +92,7 @@ static u16 bcma_pcie_mdio_read(struct bcma_drv_pci *pc, u8 device, u8 address) ret = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_DATA); break; } - msleep(1); + usleep_range(1000, 2000); } pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); return ret; @@ -132,7 +132,7 @@ static void bcma_pcie_mdio_write(struct bcma_drv_pci *pc, u8 device, v = pcicore_read32(pc, BCMA_CORE_PCI_MDIO_CONTROL); if (v & BCMA_CORE_PCI_MDIOCTL_ACCESS_DONE) break; - msleep(1); + usleep_range(1000, 2000); } pcicore_write32(pc, BCMA_CORE_PCI_MDIO_CONTROL, 0); } diff --git a/drivers/bcma/driver_pci_host.c b/drivers/bcma/driver_pci_host.c index cbae2c231336..9baf886e82df 100644 --- a/drivers/bcma/driver_pci_host.c +++ b/drivers/bcma/driver_pci_host.c @@ -425,9 +425,9 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) pc_host->io_resource.flags = IORESOURCE_IO | IORESOURCE_PCI_FIXED; /* Reset RC */ - udelay(3000); + usleep_range(3000, 5000); pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST_OE); - udelay(1000); + usleep_range(1000, 2000); pcicore_write32(pc, BCMA_CORE_PCI_CTL, BCMA_CORE_PCI_CTL_RST | BCMA_CORE_PCI_CTL_RST_OE); @@ -481,7 +481,7 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) * before issuing configuration requests to PCI Express * devices. */ - udelay(100000); + msleep(100); bcma_core_pci_enable_crs(pc); @@ -501,7 +501,7 @@ void __devinit bcma_core_pci_hostmode_init(struct bcma_drv_pci *pc) set_io_port_base(pc_host->pci_controller.io_map_base); /* Give some time to the PCI controller to configure itself with the new * values. Not waiting at this point causes crashes of the machine. */ - mdelay(10); + usleep_range(10000, 15000); register_pci_controller(&pc_host->pci_controller); return; } From a549459c96ba99a691aa1cafeabdd327a7a2bfcf Mon Sep 17 00:00:00 2001 From: Thomas Wagner Date: Tue, 25 Sep 2012 21:32:55 +0530 Subject: [PATCH 37/73] ath9k: Fix rx filtering issue for older chips We need to have the promiscuous mode enabled for older chipsets so that the olderchips hardware does not filters out some valid/necessary frames that need to be sent to mac80211. Fix this by enabling promiscus mode for all the chipsets whose macversion <= AR9160 chipsets. This should fix https://bugzilla.kernel.org/show_bug.cgi?id=45591 shafi: made the fix generic by having the frame filtering disabled for chipsets older than AR9280. Cc: Javier Cardona Signed-off-by: Thomas Wagner Signed-off-by: Mohammed Shafi Shajakhan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/recv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 4480c0cc655f..83d16e7ed272 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -424,8 +424,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc) rfilt |= ATH9K_RX_FILTER_COMP_BAR; if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) { - /* The following may also be needed for other older chips */ - if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160) + /* This is needed for older chips */ + if (sc->sc_ah->hw_version.macVersion <= AR_SREV_VERSION_9160) rfilt |= ATH9K_RX_FILTER_PROM; rfilt |= ATH9K_RX_FILTER_MCAST_BCAST_ALL; } From 69c6ac60f559f85ed47fbfc2bcaa43a7bc1583ff Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 26 Sep 2012 07:54:43 +0530 Subject: [PATCH 38/73] ath9k: Handle errors properly in MCI initialization The MCI initialization path has various points of failures, handle these to ensure that we bail out correctly in such cases. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mci.c | 21 +++++++++++---------- drivers/net/wireless/ath/ath9k/ar9003_mci.h | 8 ++++---- drivers/net/wireless/ath/ath9k/mci.c | 11 ++++++++--- 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c index 8dbb60b53f1a..44c202ce6c66 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c @@ -813,8 +813,8 @@ static void ar9003_mci_osla_setup(struct ath_hw *ah, bool enable) AR_BTCOEX_CTRL_ONE_STEP_LOOK_AHEAD_EN, 1); } -void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, - bool is_full_sleep) +int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, + bool is_full_sleep) { struct ath_common *common = ath9k_hw_common(ah); struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; @@ -824,14 +824,13 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, is_full_sleep, is_2g); if (!mci->gpm_addr && !mci->sched_addr) { - ath_dbg(common, MCI, - "MCI GPM and schedule buffers are not allocated\n"); - return; + ath_err(common, "MCI GPM and schedule buffers are not allocated\n"); + return -ENOMEM; } if (REG_READ(ah, AR_BTCOEX_CTRL) == 0xdeadbeef) { - ath_dbg(common, MCI, "BTCOEX control register is dead\n"); - return; + ath_err(common, "BTCOEX control register is dead\n"); + return -EINVAL; } /* Program MCI DMA related registers */ @@ -913,6 +912,8 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, if (en_int) ar9003_mci_enable_interrupt(ah); + + return 0; } void ar9003_mci_stop_bt(struct ath_hw *ah, bool save_fullsleep) @@ -1144,8 +1145,8 @@ void ar9003_mci_init_cal_done(struct ath_hw *ah) ar9003_mci_send_message(ah, MCI_GPM, 0, pld, 16, true, false); } -void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, - u16 len, u32 sched_addr) +int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, + u16 len, u32 sched_addr) { struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci; @@ -1154,7 +1155,7 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, mci->gpm_len = len; mci->sched_addr = sched_addr; - ar9003_mci_reset(ah, true, true, true); + return ar9003_mci_reset(ah, true, true, true); } EXPORT_SYMBOL(ar9003_mci_setup); diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.h b/drivers/net/wireless/ath/ath9k/ar9003_mci.h index 30acf2869aa4..2a2d01889613 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mci.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.h @@ -249,8 +249,8 @@ bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag, u32 *payload, u8 len, bool wait_done, bool check_bt); u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type); -void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, - u16 len, u32 sched_addr); +int ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf, + u16 len, u32 sched_addr); void ar9003_mci_cleanup(struct ath_hw *ah); void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr, u32 *rx_msg_intr); @@ -272,8 +272,8 @@ void ar9003_mci_check_bt(struct ath_hw *ah); bool ar9003_mci_start_reset(struct ath_hw *ah, struct ath9k_channel *chan); int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan, struct ath9k_hw_cal_data *caldata); -void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, - bool is_full_sleep); +int ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g, + bool is_full_sleep); void ar9003_mci_get_isr(struct ath_hw *ah, enum ath9k_int *masked); void ar9003_mci_bt_gain_ctrl(struct ath_hw *ah); void ar9003_mci_set_power_awake(struct ath_hw *ah); diff --git a/drivers/net/wireless/ath/ath9k/mci.c b/drivers/net/wireless/ath/ath9k/mci.c index 8f51e9e358fd..ec2d7c807567 100644 --- a/drivers/net/wireless/ath/ath9k/mci.c +++ b/drivers/net/wireless/ath/ath9k/mci.c @@ -392,6 +392,7 @@ int ath_mci_setup(struct ath_softc *sc) struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_mci_coex *mci = &sc->mci_coex; struct ath_mci_buf *buf = &mci->sched_buf; + int ret; buf->bf_addr = dma_alloc_coherent(sc->dev, ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE, @@ -411,9 +412,13 @@ int ath_mci_setup(struct ath_softc *sc) mci->gpm_buf.bf_addr = (u8 *)mci->sched_buf.bf_addr + mci->sched_buf.bf_len; mci->gpm_buf.bf_paddr = mci->sched_buf.bf_paddr + mci->sched_buf.bf_len; - ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr, - mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), - mci->sched_buf.bf_paddr); + ret = ar9003_mci_setup(sc->sc_ah, mci->gpm_buf.bf_paddr, + mci->gpm_buf.bf_addr, (mci->gpm_buf.bf_len >> 4), + mci->sched_buf.bf_paddr); + if (ret) { + ath_err(common, "Failed to initialize MCI\n"); + return ret; + } INIT_WORK(&sc->mci_work, ath9k_mci_work); ath_dbg(common, MCI, "MCI Initialized\n"); From 302a3c3a387eb01cc055684094e9450a79780acd Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 26 Sep 2012 07:55:18 +0530 Subject: [PATCH 39/73] ath9k: Add a debugfs file to adjust antenna diversity Location: //ieee80211/phy#/ath9k/diversity Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_phy.c | 2 +- drivers/net/wireless/ath/ath9k/debug.c | 55 ++++++++++++++++++++- 2 files changed, 54 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index fc67844a1430..759f5f5a7154 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -1360,7 +1360,7 @@ static void ar9003_hw_antctrl_shared_chain_lnadiv(struct ath_hw *ah, if (enable) { REG_SET_BIT(ah, AR_PHY_MC_GAIN_CTRL, (1 << AR_PHY_ANT_SW_RX_PROT_S)); - if (IS_CHAN_2GHZ(ah->curchan)) + if (ah->curchan && IS_CHAN_2GHZ(ah->curchan)) REG_SET_BIT(ah, AR_PHY_RESTART, AR_PHY_RESTART_ENABLE_DIV_M2FLAG); REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index ab3bc85a1f8a..ed38216c3ca3 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -222,6 +222,57 @@ static const struct file_operations fops_disable_ani = { .llseek = default_llseek, }; +static ssize_t read_file_ant_diversity(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + char buf[32]; + unsigned int len; + + len = sprintf(buf, "%d\n", common->antenna_diversity); + return simple_read_from_buffer(user_buf, count, ppos, buf, len); +} + +static ssize_t write_file_ant_diversity(struct file *file, + const char __user *user_buf, + size_t count, loff_t *ppos) +{ + struct ath_softc *sc = file->private_data; + struct ath_common *common = ath9k_hw_common(sc->sc_ah); + unsigned long antenna_diversity; + char buf[32]; + ssize_t len; + + len = min(count, sizeof(buf) - 1); + if (copy_from_user(buf, user_buf, len)) + return -EFAULT; + + if (!AR_SREV_9565(sc->sc_ah)) + goto exit; + + buf[len] = '\0'; + if (strict_strtoul(buf, 0, &antenna_diversity)) + return -EINVAL; + + common->antenna_diversity = !!antenna_diversity; + ath9k_ps_wakeup(sc); + ath_ant_comb_update(sc); + ath_dbg(common, CONFIG, "Antenna diversity: %d\n", + common->antenna_diversity); + ath9k_ps_restore(sc); +exit: + return count; +} + +static const struct file_operations fops_ant_diversity = { + .read = read_file_ant_diversity, + .write = write_file_ant_diversity, + .open = simple_open, + .owner = THIS_MODULE, + .llseek = default_llseek, +}; + static ssize_t read_file_dma(struct file *file, char __user *user_buf, size_t count, loff_t *ppos) { @@ -1599,12 +1650,12 @@ int ath9k_init_debug(struct ath_hw *ah) debugfs_create_file("samples", S_IRUSR, sc->debug.debugfs_phy, sc, &fops_samps); #endif - debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); - debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, &sc->sc_ah->gpio_val); + debugfs_create_file("diversity", S_IRUSR | S_IWUSR, + sc->debug.debugfs_phy, sc, &fops_ant_diversity); return 0; } From a8aa69dca7f754c9a2b524c90fda0209187ae9d7 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:31 -0700 Subject: [PATCH 40/73] mwifiex: fix coding style issue Remove unnecessary blank lines and extra tab. Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 3 --- drivers/net/wireless/mwifiex/wmm.c | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index c24824f8c8a1..6fd4fa6705d9 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -688,7 +688,6 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, } /* Supported rates to be advertised to the cfg80211 */ - static struct ieee80211_rate mwifiex_rates[] = { {.bitrate = 10, .hw_value = 2, }, {.bitrate = 20, .hw_value = 4, }, @@ -705,7 +704,6 @@ static struct ieee80211_rate mwifiex_rates[] = { }; /* Channel definitions to be advertised to cfg80211 */ - static struct ieee80211_channel mwifiex_channels_2ghz[] = { {.center_freq = 2412, .hw_value = 1, }, {.center_freq = 2417, .hw_value = 2, }, @@ -773,7 +771,6 @@ static struct ieee80211_supported_band mwifiex_band_5ghz = { /* Supported crypto cipher suits to be advertised to cfg80211 */ - static const u32 mwifiex_cipher_suites[] = { WLAN_CIPHER_SUITE_WEP40, WLAN_CIPHER_SUITE_WEP104, diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 766d45294c86..07a45407d3b4 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -462,7 +462,7 @@ mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) for (i = 0; i < adapter->priv_num; ++i) { priv = adapter->priv[i]; if (priv && atomic_read(&priv->wmm.tx_pkts_queued)) - return false; + return false; } return true; From e39faa73ef14f67d11d1ed19e398964c4ecebbb9 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:32 -0700 Subject: [PATCH 41/73] mwifiex: implement cfg80211 mgmt_tx handler Implement mgmt_tx in cfg80211 ops through data path. Advertise probe resp offload and skip to send probe resp in AP or GO mode. Signed-off-by: Stone Piao Signed-off-by: Yogesh Ashok Powar Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 92 ++++++++++++++++++++++++- drivers/net/wireless/mwifiex/decl.h | 3 + drivers/net/wireless/mwifiex/main.c | 34 +++++---- drivers/net/wireless/mwifiex/main.h | 12 ++++ drivers/net/wireless/mwifiex/sta_tx.c | 12 +++- drivers/net/wireless/mwifiex/wmm.c | 7 +- 6 files changed, 143 insertions(+), 17 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 6fd4fa6705d9..11942e5e33cf 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -138,6 +138,94 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, return 0; } +/* + * This function forms an skb for management frame. + */ +static int +mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) +{ + u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + u16 pkt_len; + u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT; + struct timeval tv; + + pkt_len = len + ETH_ALEN; + + skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN + + MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); + memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len)); + + memcpy(skb_push(skb, sizeof(tx_control)), + &tx_control, sizeof(tx_control)); + + memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type)); + + /* Add packet data and address4 */ + memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf, + sizeof(struct ieee80211_hdr_3addr)); + memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN); + memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)), + buf + sizeof(struct ieee80211_hdr_3addr), + len - sizeof(struct ieee80211_hdr_3addr)); + + skb->priority = LOW_PRIO_TID; + do_gettimeofday(&tv); + skb->tstamp = timeval_to_ktime(tv); + + return 0; +} + +/* + * CFG802.11 operation handler to transmit a management frame. + */ +static int +mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, + struct ieee80211_channel *chan, bool offchan, + enum nl80211_channel_type channel_type, + bool channel_type_valid, unsigned int wait, + const u8 *buf, size_t len, bool no_cck, + bool dont_wait_for_ack, u64 *cookie) +{ + struct sk_buff *skb; + u16 pkt_len; + const struct ieee80211_mgmt *mgmt; + struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); + + if (!buf || !len) { + wiphy_err(wiphy, "invalid buffer and length\n"); + return -EFAULT; + } + + mgmt = (const struct ieee80211_mgmt *)buf; + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA && + ieee80211_is_probe_resp(mgmt->frame_control)) { + /* Since we support offload probe resp, we need to skip probe + * resp in AP or GO mode */ + wiphy_dbg(wiphy, + "info: skip to send probe resp in AP or GO mode\n"); + return 0; + } + + pkt_len = len + ETH_ALEN; + skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN + + MWIFIEX_MGMT_FRAME_HEADER_SIZE + + pkt_len + sizeof(pkt_len)); + + if (!skb) { + wiphy_err(wiphy, "allocate skb failed for management frame\n"); + return -ENOMEM; + } + + mwifiex_form_mgmt_frame(skb, buf, len); + mwifiex_queue_tx_pkt(priv, skb); + + *cookie = random32() | 1; + cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, GFP_ATOMIC); + + wiphy_dbg(wiphy, "info: management frame transmitted\n"); + return 0; +} + /* * CFG802.11 operation handler to set Tx power. */ @@ -1810,6 +1898,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .leave_ibss = mwifiex_cfg80211_leave_ibss, .add_key = mwifiex_cfg80211_add_key, .del_key = mwifiex_cfg80211_del_key, + .mgmt_tx = mwifiex_cfg80211_mgmt_tx, .set_default_key = mwifiex_cfg80211_set_default_key, .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, .set_tx_power = mwifiex_cfg80211_set_tx_power, @@ -1872,7 +1961,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2; + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | + NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index 400d360ac91f..d21bcc146f4b 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -33,6 +33,9 @@ #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) * + 4 byte alignment */ +#define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8 /* sizeof(pkt_type) + * + sizeof(tx_control) + */ #define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 #define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index bfd6667be01e..3bb3417932d0 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -468,6 +468,27 @@ mwifiex_close(struct net_device *dev) return 0; } +/* + * Add buffer into wmm tx queue and queue work to transmit it. + */ +int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) +{ + mwifiex_wmm_add_buf_txqueue(priv, skb); + atomic_inc(&priv->adapter->tx_pending); + + if (priv->adapter->scan_delay_cnt) + atomic_set(&priv->adapter->is_tx_received, true); + + if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { + mwifiex_set_trans_start(priv->netdev); + mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); + } + + queue_work(priv->adapter->workqueue, &priv->adapter->main_work); + + return 0; +} + /* * CFG802.11 network device handler for data transmission. */ @@ -516,18 +537,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) tx_info->bss_type = priv->bss_type; mwifiex_fill_buffer(skb); - mwifiex_wmm_add_buf_txqueue(priv, skb); - atomic_inc(&priv->adapter->tx_pending); - - if (priv->adapter->scan_delay_cnt) - atomic_set(&priv->adapter->is_tx_received, true); - - if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) { - mwifiex_set_trans_start(dev); - mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); - } - - queue_work(priv->adapter->workqueue, &priv->adapter->main_work); + mwifiex_queue_tx_pkt(priv, skb); return 0; } diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 90b64b015447..092fbfaeb882 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -98,6 +98,8 @@ enum { #define MWIFIEX_OUI_NOT_PRESENT 0 #define MWIFIEX_OUI_PRESENT 1 +#define PKT_TYPE_MGMT 0xE5 + /* * Do not check for data_received for USB, as data_received * is handled in mwifiex_usb_recv for USB @@ -960,6 +962,14 @@ mwifiex_netdev_get_priv(struct net_device *dev) return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); } +/* + * This function checks if a skb holds a management frame. + */ +static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb) +{ + return (*(u32 *)skb->data == PKT_TYPE_MGMT); +} + int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, u32 func_init_shutdown); int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); @@ -1022,6 +1032,8 @@ int mwifiex_set_tx_power(struct mwifiex_private *priv, int mwifiex_main_process(struct mwifiex_adapter *); +int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb); + int mwifiex_get_bss_info(struct mwifiex_private *, struct mwifiex_bss_info *); int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c index 0a046d3a0c16..7b581af24f5f 100644 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ b/drivers/net/wireless/mwifiex/sta_tx.c @@ -48,6 +48,7 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, struct txpd *local_tx_pd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); u8 pad; + u16 pkt_type, pkt_offset; if (!skb->len) { dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); @@ -55,6 +56,8 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, return skb->data; } + pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; + /* If skb->data is not aligned; add padding */ pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4; @@ -93,7 +96,14 @@ void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, } /* Offset of actual data */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + pad); + pkt_offset = sizeof(struct txpd) + pad; + if (pkt_type == PKT_TYPE_MGMT) { + /* Set the packet type and add header for management frame */ + local_tx_pd->tx_pkt_type = cpu_to_le16(pkt_type); + pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE; + } + + local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset); /* make space for INTF_HEADER_LEN */ skb_push(skb, INTF_HEADER_LEN); diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c index 07a45407d3b4..600d8194610e 100644 --- a/drivers/net/wireless/mwifiex/wmm.c +++ b/drivers/net/wireless/mwifiex/wmm.c @@ -648,7 +648,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, u8 ra[ETH_ALEN], tid_down; unsigned long flags; - if (!priv->media_connected) { + if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { dev_dbg(adapter->dev, "data: drop packet in disconnect\n"); mwifiex_write_data_complete(adapter, skb, -1); return; @@ -663,7 +663,8 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, /* In case of infra as we have already created the list during association we just don't have to call get_queue_raptr, we will have only 1 raptr for a tid in case of infra */ - if (!mwifiex_queuing_ra_based(priv)) { + if (!mwifiex_queuing_ra_based(priv) && + !mwifiex_is_skb_mgmt_frame(skb)) { if (!list_empty(&priv->wmm.tid_tbl_ptr[tid_down].ra_list)) ra_list = list_first_entry( &priv->wmm.tid_tbl_ptr[tid_down].ra_list, @@ -672,7 +673,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, ra_list = NULL; } else { memcpy(ra, skb->data, ETH_ALEN); - if (ra[0] & 0x01) + if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) memset(ra, 0xff, ETH_ALEN); ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); } From 83719be861d23013ae73e126f5cd422ec584c53a Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:33 -0700 Subject: [PATCH 42/73] mwifiex: advertise mgmt_stype to cfg80211 Advertise supported management frame types to cfg80211. Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 30 +++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 11942e5e33cf..2befac5659cc 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -867,6 +867,35 @@ static const u32 mwifiex_cipher_suites[] = { WLAN_CIPHER_SUITE_AES_CMAC, }; +/* Supported mgmt frame types to be advertised to cfg80211 */ +static const struct ieee80211_txrx_stypes +mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = { + [NL80211_IFTYPE_STATION] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + }, + [NL80211_IFTYPE_AP] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + }, + [NL80211_IFTYPE_P2P_CLIENT] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + }, + [NL80211_IFTYPE_P2P_GO] = { + .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_RESP >> 4), + .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | + BIT(IEEE80211_STYPE_PROBE_REQ >> 4), + }, +}; + /* * CFG802.11 operation handler for setting bit rates. * @@ -1935,6 +1964,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) } wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; + wiphy->mgmt_stypes = mwifiex_mgmt_stypes; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); From 3cec68701a104c8aa0b5c38b6bfad4193cdff3fe Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:34 -0700 Subject: [PATCH 43/73] mwifiex: implement cfg80211 mgmt_frame_register handler Add a new command to implement mgmt_frame_register. Signed-off-by: Stone Piao Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 22 ++++++++++++++++++++++ drivers/net/wireless/mwifiex/fw.h | 7 +++++++ drivers/net/wireless/mwifiex/main.h | 1 + drivers/net/wireless/mwifiex/sta_cmd.c | 9 +++++++++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 1 + 5 files changed, 40 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 2befac5659cc..f86043df8d4d 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -226,6 +226,27 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, return 0; } +/* + * CFG802.11 operation handler to register a mgmt frame. + */ +static void +mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, + struct wireless_dev *wdev, + u16 frame_type, bool reg) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); + + if (reg) + priv->mgmt_frame_mask |= BIT(frame_type >> 4); + else + priv->mgmt_frame_mask &= ~BIT(frame_type >> 4); + + mwifiex_send_cmd_async(priv, HostCmd_CMD_MGMT_FRAME_REG, + HostCmd_ACT_GEN_SET, 0, &priv->mgmt_frame_mask); + + wiphy_dbg(wiphy, "info: mgmt frame registered\n"); +} + /* * CFG802.11 operation handler to set Tx power. */ @@ -1928,6 +1949,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .add_key = mwifiex_cfg80211_add_key, .del_key = mwifiex_cfg80211_del_key, .mgmt_tx = mwifiex_cfg80211_mgmt_tx, + .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register, .set_default_key = mwifiex_cfg80211_set_default_key, .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, .set_tx_power = mwifiex_cfg80211_set_tx_power, diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index b8ce78e2ba47..41b304a33a07 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -263,6 +263,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed #define HostCmd_CMD_SET_BSS_MODE 0x00f7 #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa +#define HostCmd_CMD_MGMT_FRAME_REG 0x010c #define PROTOCOL_NO_SECURITY 0x01 #define PROTOCOL_STATIC_WEP 0x02 @@ -1336,6 +1337,11 @@ struct host_cmd_ds_version_ext { char version_str[128]; } __packed; +struct host_cmd_ds_mgmt_frame_reg { + __le16 action; + __le32 mask; +} __packed; + struct host_cmd_ds_802_11_ibss_status { __le16 action; __le16 enable; @@ -1444,6 +1450,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_wmm_get_status get_wmm_status; struct host_cmd_ds_802_11_key_material key_material; struct host_cmd_ds_version_ext verext; + struct host_cmd_ds_mgmt_frame_reg reg_mask; struct host_cmd_ds_802_11_ibss_status ibss_coalescing; struct host_cmd_ds_mac_reg_access mac_reg; struct host_cmd_ds_bbp_reg_access bbp_reg; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 092fbfaeb882..6e0806244b82 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -496,6 +496,7 @@ struct mwifiex_private { u16 rsn_idx; struct timer_list scan_delay_timer; u8 ap_11n_enabled; + u32 mgmt_frame_mask; }; enum mwifiex_ba_status { diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 3a4161cfeed7..dc4fe8c320fd 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1167,6 +1167,15 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, S_DS_GEN); ret = 0; break; + case HostCmd_CMD_MGMT_FRAME_REG: + cmd_ptr->command = cpu_to_le16(cmd_no); + cmd_ptr->params.reg_mask.action = cpu_to_le16(cmd_action); + cmd_ptr->params.reg_mask.mask = cpu_to_le32(*(u32 *)data_buf); + cmd_ptr->size = + cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) + + S_DS_GEN); + ret = 0; + break; case HostCmd_CMD_FUNC_INIT: if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 31f80e10e29e..d1f53e39028f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -875,6 +875,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_VERSION_EXT: ret = mwifiex_ret_ver_ext(priv, resp, data_buf); break; + case HostCmd_CMD_MGMT_FRAME_REG: case HostCmd_CMD_FUNC_INIT: case HostCmd_CMD_FUNC_SHUTDOWN: break; From 2dbaf751b1dec3a603130a475f94cc4d3f404362 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:35 -0700 Subject: [PATCH 44/73] mwifiex: report received management frames to cfg80211 Process the management frames received from firmware and report them to cfg80211. Signed-off-by: Stone Piao Signed-off-by: Kiran Divekar Signed-off-by: Kevin Gan Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 1 + drivers/net/wireless/mwifiex/init.c | 1 + drivers/net/wireless/mwifiex/main.h | 4 +++ drivers/net/wireless/mwifiex/sta_rx.c | 6 ++++ drivers/net/wireless/mwifiex/uap_txrx.c | 6 ++++ drivers/net/wireless/mwifiex/util.c | 40 +++++++++++++++++++++++++ 6 files changed, 58 insertions(+) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 41b304a33a07..b587ea3feffa 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -94,6 +94,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { }; #define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) +#define CAL_RSSI(SNR, NF) ((s16)((s16)(SNR)+(s16)(NF))) #define UAP_BSS_PARAMS_I 0 #define UAP_CUSTOM_IE_I 1 diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index b2ba262f8a13..105a5c5d7d5d 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -214,6 +214,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->wps_ie = NULL; priv->wps_ie_len = 0; priv->ap_11n_enabled = 0; + priv->mgmt_rx_freq = 2437; priv->scan_block = false; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 6e0806244b82..ec5794ef4366 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -497,6 +497,7 @@ struct mwifiex_private { struct timer_list scan_delay_timer; u8 ap_11n_enabled; u32 mgmt_frame_mask; + u32 mgmt_rx_freq; }; enum mwifiex_ba_status { @@ -741,6 +742,9 @@ int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); int mwifiex_recv_packet(struct mwifiex_adapter *, struct sk_buff *skb); +int mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb); + int mwifiex_process_event(struct mwifiex_adapter *adapter); int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index d91d5c08c73a..07d32b73783e 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c @@ -174,6 +174,12 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter, dev_err(adapter->dev, "Rx of A-MSDU failed"); } return 0; + } else if (rx_pkt_type == PKT_TYPE_MGMT) { + ret = mwifiex_process_mgmt_packet(adapter, skb); + if (ret) + dev_err(adapter->dev, "Rx of mgmt packet failed"); + dev_kfree_skb_any(skb); + return ret; } /* diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index df17d08715fe..012c1433d126 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -217,6 +217,12 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter, } return 0; + } else if (rx_pkt_type == PKT_TYPE_MGMT) { + ret = mwifiex_process_mgmt_packet(adapter, skb); + if (ret) + dev_err(adapter->dev, "Rx of mgmt packet failed"); + dev_kfree_skb_any(skb); + return ret; } memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index 2864c74bdb6f..e1dc3e41c65d 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -141,6 +141,46 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, return 0; } +/* + * This function processes the received management packet and send it + * to the kernel. + */ +int +mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, + struct sk_buff *skb) +{ + struct rxpd *rx_pd; + struct mwifiex_private *priv; + u16 pkt_len; + + if (!skb) + return -1; + + rx_pd = (struct rxpd *)skb->data; + priv = mwifiex_get_priv_by_id(adapter, rx_pd->bss_num, rx_pd->bss_type); + if (!priv) + return -1; + + skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); + skb_pull(skb, sizeof(pkt_len)); + + pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); + + /* Remove address4 */ + memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), + skb->data + sizeof(struct ieee80211_hdr), + pkt_len - sizeof(struct ieee80211_hdr)); + + pkt_len -= ETH_ALEN + sizeof(pkt_len); + rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); + + cfg80211_rx_mgmt(priv->wdev, priv->mgmt_rx_freq, + CAL_RSSI(rx_pd->snr, rx_pd->nf), + skb->data, pkt_len, GFP_ATOMIC); + + return 0; +} + /* * This function processes the received packet before sending it to the * kernel. From 7feb4c48313d58b445a91a598d99c025029ce00b Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:36 -0700 Subject: [PATCH 45/73] mwifiex: implement remain_on_channel and cancel_remain_on_channel Add a new command to implement remain_on_channel and cancel_remain_on_channel. Signed-off-by: Stone Piao Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 82 +++++++++++++++++++++- drivers/net/wireless/mwifiex/fw.h | 12 ++++ drivers/net/wireless/mwifiex/init.c | 2 +- drivers/net/wireless/mwifiex/main.h | 15 +++- drivers/net/wireless/mwifiex/sta_cmd.c | 8 +++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 19 +++++ drivers/net/wireless/mwifiex/sta_ioctl.c | 29 ++++++++ drivers/net/wireless/mwifiex/util.c | 2 +- 8 files changed, 163 insertions(+), 6 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index f86043df8d4d..261d7c548a5e 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -77,8 +77,7 @@ static const struct ieee80211_regdomain mwifiex_world_regdom_custom = { * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE */ -static u8 -mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) +u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) { switch (chan_type) { case NL80211_CHAN_NO_HT: @@ -247,6 +246,79 @@ mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, wiphy_dbg(wiphy, "info: mgmt frame registered\n"); } +/* + * CFG802.11 operation handler to remain on channel. + */ +static int +mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, + struct ieee80211_channel *chan, + enum nl80211_channel_type channel_type, + unsigned int duration, u64 *cookie) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); + int ret; + + if (!chan || !cookie) { + wiphy_err(wiphy, "Invalid parameter for ROC\n"); + return -EINVAL; + } + + if (priv->roc_cfg.cookie) { + wiphy_dbg(wiphy, "info: ongoing ROC, cookie = 0x%llu\n", + priv->roc_cfg.cookie); + return -EBUSY; + } + + ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan, + &channel_type, duration); + + if (!ret) { + *cookie = random32() | 1; + priv->roc_cfg.cookie = *cookie; + priv->roc_cfg.chan = *chan; + priv->roc_cfg.chan_type = channel_type; + + cfg80211_ready_on_channel(wdev, *cookie, chan, channel_type, + duration, GFP_ATOMIC); + + wiphy_dbg(wiphy, "info: ROC, cookie = 0x%llx\n", *cookie); + } + + return ret; +} + +/* + * CFG802.11 operation handler to cancel remain on channel. + */ +static int +mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, + struct wireless_dev *wdev, u64 cookie) +{ + struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); + int ret; + + if (cookie != priv->roc_cfg.cookie) + return -ENOENT; + + ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE, + &priv->roc_cfg.chan, + &priv->roc_cfg.chan_type, 0); + + if (!ret) { + cfg80211_remain_on_channel_expired(wdev, cookie, + &priv->roc_cfg.chan, + priv->roc_cfg.chan_type, + GFP_ATOMIC); + + memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg)); + + wiphy_dbg(wiphy, "info: cancel ROC, cookie = 0x%llx\n", cookie); + } + + return ret; +} + /* * CFG802.11 operation handler to set Tx power. */ @@ -1950,6 +2022,8 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { .del_key = mwifiex_cfg80211_del_key, .mgmt_tx = mwifiex_cfg80211_mgmt_tx, .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register, + .remain_on_channel = mwifiex_cfg80211_remain_on_channel, + .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel, .set_default_key = mwifiex_cfg80211_set_default_key, .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, .set_tx_power = mwifiex_cfg80211_set_tx_power, @@ -1987,6 +2061,7 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; wiphy->mgmt_stypes = mwifiex_mgmt_stypes; + wiphy->max_remain_on_channel_duration = 5000; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); @@ -2008,7 +2083,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | - WIPHY_FLAG_CUSTOM_REGULATORY; + WIPHY_FLAG_CUSTOM_REGULATORY | + WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL; wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index b587ea3feffa..9818cae7faf7 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -265,6 +265,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_SET_BSS_MODE 0x00f7 #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa #define HostCmd_CMD_MGMT_FRAME_REG 0x010c +#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d #define PROTOCOL_NO_SECURITY 0x01 #define PROTOCOL_STATIC_WEP 0x02 @@ -293,6 +294,7 @@ enum ENH_PS_MODES { #define HostCmd_RET_BIT 0x8000 #define HostCmd_ACT_GEN_GET 0x0000 #define HostCmd_ACT_GEN_SET 0x0001 +#define HostCmd_ACT_GEN_REMOVE 0x0004 #define HostCmd_ACT_BITWISE_SET 0x0002 #define HostCmd_ACT_BITWISE_CLR 0x0003 #define HostCmd_RESULT_OK 0x0000 @@ -1343,6 +1345,15 @@ struct host_cmd_ds_mgmt_frame_reg { __le32 mask; } __packed; +struct host_cmd_ds_remain_on_chan { + __le16 action; + u8 status; + u8 reserved; + u8 band_cfg; + u8 channel; + __le32 duration; +} __packed; + struct host_cmd_ds_802_11_ibss_status { __le16 action; __le16 enable; @@ -1452,6 +1463,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_802_11_key_material key_material; struct host_cmd_ds_version_ext verext; struct host_cmd_ds_mgmt_frame_reg reg_mask; + struct host_cmd_ds_remain_on_chan roc_cfg; struct host_cmd_ds_802_11_ibss_status ibss_coalescing; struct host_cmd_ds_mac_reg_access mac_reg; struct host_cmd_ds_bbp_reg_access bbp_reg; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 105a5c5d7d5d..fa96dc328a5b 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -214,7 +214,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv) priv->wps_ie = NULL; priv->wps_ie_len = 0; priv->ap_11n_enabled = 0; - priv->mgmt_rx_freq = 2437; + memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); priv->scan_block = false; diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index ec5794ef4366..89ba66e56143 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -370,6 +370,12 @@ struct wps { u8 session_enable; }; +struct mwifiex_roc_cfg { + u64 cookie; + struct ieee80211_channel chan; + enum nl80211_channel_type chan_type; +}; + struct mwifiex_adapter; struct mwifiex_private; @@ -497,7 +503,7 @@ struct mwifiex_private { struct timer_list scan_delay_timer; u8 ap_11n_enabled; u32 mgmt_frame_mask; - u32 mgmt_rx_freq; + struct mwifiex_roc_cfg roc_cfg; }; enum mwifiex_ba_status { @@ -1007,6 +1013,11 @@ int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len); int mwifiex_get_ver_ext(struct mwifiex_private *priv); +int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, + struct ieee80211_channel *chan, + enum nl80211_channel_type *channel_type, + unsigned int duration); + int mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log); @@ -1049,6 +1060,8 @@ int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, int mwifiex_check_network_compatibility(struct mwifiex_private *priv, struct mwifiex_bssdescriptor *bss_desc); +u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type); + struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, const char *name, enum nl80211_iftype type, diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index dc4fe8c320fd..025244639bfc 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1176,6 +1176,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, S_DS_GEN); ret = 0; break; + case HostCmd_CMD_REMAIN_ON_CHAN: + cmd_ptr->command = cpu_to_le16(cmd_no); + memcpy(&cmd_ptr->params, data_buf, + sizeof(struct host_cmd_ds_remain_on_chan)); + cmd_ptr->size = + cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + + S_DS_GEN); + break; case HostCmd_CMD_FUNC_INIT: if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index d1f53e39028f..621d36e437f5 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -653,6 +653,22 @@ static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, return 0; } +/* + * This function handles the command response of remain on channel. + */ +static int +mwifiex_ret_remain_on_chan(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + struct host_cmd_ds_remain_on_chan *roc_cfg) +{ + struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg; + + if (roc_cfg) + memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg)); + + return 0; +} + /* * This function handles the command response of register access. * @@ -875,6 +891,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_VERSION_EXT: ret = mwifiex_ret_ver_ext(priv, resp, data_buf); break; + case HostCmd_CMD_REMAIN_ON_CHAN: + ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); + break; case HostCmd_CMD_MGMT_FRAME_REG: case HostCmd_CMD_FUNC_INIT: case HostCmd_CMD_FUNC_SHUTDOWN: diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 731562f026f5..fd09a21b8824 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1043,6 +1043,35 @@ mwifiex_get_ver_ext(struct mwifiex_private *priv) return 0; } +int +mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, + struct ieee80211_channel *chan, + enum nl80211_channel_type *ct, + unsigned int duration) +{ + struct host_cmd_ds_remain_on_chan roc_cfg; + u8 sc; + + memset(&roc_cfg, 0, sizeof(roc_cfg)); + roc_cfg.action = cpu_to_le16(action); + if (action == HostCmd_ACT_GEN_SET) { + roc_cfg.band_cfg = chan->band; + sc = mwifiex_chan_type_to_sec_chan_offset(*ct); + roc_cfg.band_cfg |= (sc << 2); + + roc_cfg.channel = + ieee80211_frequency_to_channel(chan->center_freq); + roc_cfg.duration = cpu_to_le32(duration); + } + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_REMAIN_ON_CHAN, + action, 0, &roc_cfg)) { + dev_err(priv->adapter->dev, "failed to remain on channel\n"); + return -1; + } + + return roc_cfg.status; +} + /* * Sends IOCTL request to get statistics information. * diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index e1dc3e41c65d..ae88f80cf86b 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c @@ -174,7 +174,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_adapter *adapter, pkt_len -= ETH_ALEN + sizeof(pkt_len); rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); - cfg80211_rx_mgmt(priv->wdev, priv->mgmt_rx_freq, + cfg80211_rx_mgmt(priv->wdev, priv->roc_cfg.chan.center_freq, CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, GFP_ATOMIC); From eab1c76bfc40904ddc9edc4f076ff7749696870a Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:37 -0700 Subject: [PATCH 46/73] mwifiex: process remain on channel expired event Process remain on channel expired event, and notify cfg80211. Signed-off-by: Stone Piao Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/fw.h | 1 + drivers/net/wireless/mwifiex/sta_event.c | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 9818cae7faf7..b8a07ade2e68 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -392,6 +392,7 @@ enum ENH_PS_MODES { #define EVENT_BW_CHANGE 0x00000048 #define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c #define EVENT_HOSTWAKE_STAIE 0x0000004d +#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f #define EVENT_ID_MASK 0xffff #define BSS_NUM_MASK 0xf diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index dff51d55271c..aafde30e714a 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c @@ -410,6 +410,18 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv) dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause); break; + case EVENT_REMAIN_ON_CHAN_EXPIRED: + dev_dbg(adapter->dev, "event: Remain on channel expired\n"); + cfg80211_remain_on_channel_expired(priv->wdev, + priv->roc_cfg.cookie, + &priv->roc_cfg.chan, + priv->roc_cfg.chan_type, + GFP_ATOMIC); + + memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg)); + + break; + default: dev_dbg(adapter->dev, "event: unknown event id: %#x\n", eventcause); From ea021f56009207e8023c1c4ac4939be3dbe80dbf Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:38 -0700 Subject: [PATCH 47/73] mwifiex: append each IE into a seperate IE buffer When scan is triggered from cfg80211, the request contains some IEs and we should parse all the IEs and append each IE into a seperate IE buffer. Signed-off-by: Stone Piao Signed-off-by: Kiran Divekar Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 261d7c548a5e..1f4bd67dffa7 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1704,8 +1704,9 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, { struct net_device *dev = request->wdev->netdev; struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int i; + int i, offset; struct ieee80211_channel *chan; + struct ieee_types_header *ie; wiphy_dbg(wiphy, "info: received scan request on %s\n", dev->name); @@ -1728,13 +1729,17 @@ mwifiex_cfg80211_scan(struct wiphy *wiphy, priv->user_scan_cfg->ssid_list = request->ssids; if (request->ie && request->ie_len) { + offset = 0; for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR) continue; priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN; - memcpy(&priv->vs_ie[i].ie, request->ie, - request->ie_len); - break; + ie = (struct ieee_types_header *)(request->ie + offset); + memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); + offset += sizeof(*ie) + ie->len; + + if (offset >= request->ie_len) + break; } } From 7bff9c974e1a70819c30c37d8ec0d84d456f8237 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:39 -0700 Subject: [PATCH 48/73] mwifiex: send firmware initialization commands synchronously The driver will send some commands to firmware during the initialization. Currently these commands are sent asynchronously, which means that we firstly insert all of them to a pre-allocated command queue, and then start to process them one by one. The command queue will soon be exhausted if we keep adding new initialization commands. This issue can be resolved by sending initialization commands synchronously because each command is consumed and the buffer is recycled before queuing next command. Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/sta_cmd.c | 65 +++++++++++++------------- 1 file changed, 33 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 025244639bfc..c2198a798b9f 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1302,35 +1302,35 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) if (first_sta) { if (priv->adapter->iface_type == MWIFIEX_PCIE) { - ret = mwifiex_send_cmd_async(priv, + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_PCIE_DESC_DETAILS, HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return -1; } - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_FUNC_INIT, - HostCmd_ACT_GEN_SET, 0, NULL); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_FUNC_INIT, + HostCmd_ACT_GEN_SET, 0, NULL); if (ret) return -1; /* Read MAC address from HW */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_GET_HW_SPEC, - HostCmd_ACT_GEN_GET, 0, NULL); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_GET_HW_SPEC, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; /* Reconfigure tx buf size */ - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, - &priv->adapter->tx_buf_size); + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_RECONFIGURE_TX_BUFF, + HostCmd_ACT_GEN_SET, 0, + &priv->adapter->tx_buf_size); if (ret) return -1; if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { /* Enable IEEE PS by default */ priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - ret = mwifiex_send_cmd_async( + ret = mwifiex_send_cmd_sync( priv, HostCmd_CMD_802_11_PS_MODE_ENH, EN_AUTO_PS, BITMAP_STA_PS, NULL); if (ret) @@ -1339,21 +1339,21 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) } /* get tx rate */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_GET, 0, NULL); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_TX_RATE_CFG, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; priv->data_rate = 0; /* get tx power */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_RF_TX_PWR, - HostCmd_ACT_GEN_GET, 0, NULL); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_RF_TX_PWR, + HostCmd_ACT_GEN_GET, 0, NULL); if (ret) return -1; if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { /* set ibss coalescing_status */ - ret = mwifiex_send_cmd_async( + ret = mwifiex_send_cmd_sync( priv, HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, HostCmd_ACT_GEN_SET, 0, &enable); if (ret) @@ -1363,16 +1363,16 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); amsdu_aggr_ctrl.enable = true; /* Send request to firmware */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, - HostCmd_ACT_GEN_SET, 0, - &amsdu_aggr_ctrl); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, + HostCmd_ACT_GEN_SET, 0, + &amsdu_aggr_ctrl); if (ret) return -1; /* MAC Control must be the last command in init_fw */ /* set MAC Control */ - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_MAC_CONTROL, + HostCmd_ACT_GEN_SET, 0, + &priv->curr_pkt_filter); if (ret) return -1; @@ -1381,10 +1381,10 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) /* Enable auto deep sleep */ auto_ds.auto_ds = DEEP_SLEEP_ON; auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; - ret = mwifiex_send_cmd_async(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_AUTO_DS, - &auto_ds); + ret = mwifiex_send_cmd_sync(priv, + HostCmd_CMD_802_11_PS_MODE_ENH, + EN_AUTO_PS, BITMAP_AUTO_DS, + &auto_ds); if (ret) return -1; } @@ -1392,23 +1392,24 @@ int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta) if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { /* Send cmd to FW to enable/disable 11D function */ state_11d = ENABLE_11D; - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11D_I, - &state_11d); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_SNMP_MIB, + HostCmd_ACT_GEN_SET, DOT11D_I, + &state_11d); if (ret) dev_err(priv->adapter->dev, "11D: failed to enable 11D\n"); } + /* set last_init_cmd before sending the command */ + priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; + /* Send cmd to FW to configure 11n specific configuration * (Short GI, Channel BW, Green field support etc.) for transmit */ tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; - ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_CFG, - HostCmd_ACT_GEN_SET, 0, &tx_cfg); + ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_11N_CFG, + HostCmd_ACT_GEN_SET, 0, &tx_cfg); - /* set last_init_cmd */ - priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; ret = -EINPROGRESS; return ret; From 197f4a2ec99dd3a70b27fba7e827d1fa98114ce3 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:40 -0700 Subject: [PATCH 49/73] mwifiex: add P2P interface Due to firmware design, driver needs to add a default P2P interface to implement find phase and action frame handshake. Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 39 ++++++++++++++++++++++++- drivers/net/wireless/mwifiex/decl.h | 3 +- drivers/net/wireless/mwifiex/main.c | 7 +++++ 3 files changed, 47 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 1f4bd67dffa7..ece267a36380 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -22,7 +22,7 @@ static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { { - .max = 1, .types = BIT(NL80211_IFTYPE_STATION), + .max = 2, .types = BIT(NL80211_IFTYPE_STATION), }, { .max = 1, .types = BIT(NL80211_IFTYPE_AP), @@ -1917,6 +1917,41 @@ struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, priv->bss_num = 0; priv->bss_mode = type; + break; + case NL80211_IFTYPE_P2P_CLIENT: + priv = adapter->priv[MWIFIEX_BSS_TYPE_P2P]; + + if (priv->bss_mode) { + wiphy_err(wiphy, "Can't create multiple P2P ifaces"); + return ERR_PTR(-EINVAL); + } + + wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL); + if (!wdev) + return ERR_PTR(-ENOMEM); + + priv->wdev = wdev; + wdev->wiphy = wiphy; + + /* At start-up, wpa_supplicant tries to change the interface + * to NL80211_IFTYPE_STATION if it is not managed mode. + * So, we initialize it to STA mode. + */ + wdev->iftype = NL80211_IFTYPE_STATION; + priv->bss_mode = NL80211_IFTYPE_STATION; + + /* Setting bss_type to P2P tells firmware that this interface + * is receiving P2P peers found during find phase and doing + * action frame handshake. + */ + priv->bss_type = MWIFIEX_BSS_TYPE_P2P; + + priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; + priv->bss_priority = MWIFIEX_BSS_ROLE_STA; + priv->bss_role = MWIFIEX_BSS_ROLE_STA; + priv->bss_started = 0; + priv->bss_num = 0; + break; default: wiphy_err(wiphy, "type not supported\n"); @@ -2069,6 +2104,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->max_remain_on_channel_duration = 5000; wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | BIT(NL80211_IFTYPE_AP); wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index d21bcc146f4b..e9357d87d327 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h @@ -28,7 +28,7 @@ #include -#define MWIFIEX_MAX_BSS_NUM (2) +#define MWIFIEX_MAX_BSS_NUM (3) #define MWIFIEX_MIN_DATA_HEADER_LEN 36 /* sizeof(mwifiex_txpd) * + 4 byte alignment @@ -70,6 +70,7 @@ enum mwifiex_bss_type { MWIFIEX_BSS_TYPE_STA = 0, MWIFIEX_BSS_TYPE_UAP = 1, + MWIFIEX_BSS_TYPE_P2P = 2, MWIFIEX_BSS_TYPE_ANY = 0xff, }; diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index 3bb3417932d0..eb22dd248d54 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c @@ -369,6 +369,13 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) dev_err(adapter->dev, "cannot create default AP interface\n"); goto err_add_intf; } + + /* Create P2P interface by default */ + if (!mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", + NL80211_IFTYPE_P2P_CLIENT, NULL, NULL)) { + dev_err(adapter->dev, "cannot create default P2P interface\n"); + goto err_add_intf; + } rtnl_unlock(); mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); From e1a2b7a394ad8c2da9d7f4276680aa9c42e0bd97 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:41 -0700 Subject: [PATCH 50/73] mwifiex: add support for P2P client in interface type change When cfg80211 calls to change interface type for P2P client, send P2P mode config commands to firmware. Signed-off-by: Stone Piao Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 54 ++++++++++++++++++++++ drivers/net/wireless/mwifiex/fw.h | 14 ++++++ drivers/net/wireless/mwifiex/sta_cmd.c | 8 ++++ drivers/net/wireless/mwifiex/sta_cmdresp.c | 19 ++++++++ 4 files changed, 95 insertions(+) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index ece267a36380..499060304d15 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -674,6 +674,44 @@ mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return 0; } +static int +mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) +{ + u16 mode = P2P_MODE_DISABLE; + + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode)) + return -1; + + return 0; +} + +/* + * This function initializes the functionalities for P2P client. + * The P2P client initialization sequence is: + * disable -> device -> client + */ +static int +mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) +{ + u16 mode; + + if (mwifiex_cfg80211_deinit_p2p(priv)) + return -1; + + mode = P2P_MODE_DEVICE; + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode)) + return -1; + + mode = P2P_MODE_CLIENT; + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode)) + return -1; + + return 0; +} + /* * CFG802.11 operation handler to change interface type. */ @@ -706,6 +744,11 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, switch (type) { case NL80211_IFTYPE_ADHOC: break; + case NL80211_IFTYPE_P2P_CLIENT: + if (mwifiex_cfg80211_init_p2p_client(priv)) + return -EFAULT; + dev->ieee80211_ptr->iftype = type; + return 0; case NL80211_IFTYPE_UNSPECIFIED: wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); case NL80211_IFTYPE_STATION: /* This shouldn't happen */ @@ -731,6 +774,17 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return -EOPNOTSUPP; } break; + case NL80211_IFTYPE_P2P_CLIENT: + switch (type) { + case NL80211_IFTYPE_STATION: + if (mwifiex_cfg80211_deinit_p2p(priv)) + return -EFAULT; + dev->ieee80211_ptr->iftype = type; + return 0; + default: + return -EOPNOTSUPP; + } + break; default: wiphy_err(wiphy, "%s: unknown iftype: %d\n", dev->name, dev->ieee80211_ptr->iftype); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index b8a07ade2e68..7887848448e9 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -261,6 +261,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define HostCmd_CMD_TX_RATE_CFG 0x00d6 #define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 #define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 +#define HostCmd_CMD_P2P_MODE_CFG 0x00eb #define HostCmd_CMD_CAU_REG_ACCESS 0x00ed #define HostCmd_CMD_SET_BSS_MODE 0x00f7 #define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa @@ -291,6 +292,13 @@ enum ENH_PS_MODES { DIS_AUTO_PS = 0xfe, }; +enum P2P_MODES { + P2P_MODE_DISABLE = 0, + P2P_MODE_DEVICE = 1, + P2P_MODE_GO = 2, + P2P_MODE_CLIENT = 3, +}; + #define HostCmd_RET_BIT 0x8000 #define HostCmd_ACT_GEN_GET 0x0000 #define HostCmd_ACT_GEN_SET 0x0001 @@ -1346,6 +1354,11 @@ struct host_cmd_ds_mgmt_frame_reg { __le32 mask; } __packed; +struct host_cmd_ds_p2p_mode_cfg { + __le16 action; + __le16 mode; +} __packed; + struct host_cmd_ds_remain_on_chan { __le16 action; u8 status; @@ -1465,6 +1478,7 @@ struct host_cmd_ds_command { struct host_cmd_ds_version_ext verext; struct host_cmd_ds_mgmt_frame_reg reg_mask; struct host_cmd_ds_remain_on_chan roc_cfg; + struct host_cmd_ds_p2p_mode_cfg mode_cfg; struct host_cmd_ds_802_11_ibss_status ibss_coalescing; struct host_cmd_ds_mac_reg_access mac_reg; struct host_cmd_ds_bbp_reg_access bbp_reg; diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index c2198a798b9f..704cfaaeba14 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1184,6 +1184,14 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + S_DS_GEN); break; + case HostCmd_CMD_P2P_MODE_CFG: + cmd_ptr->command = cpu_to_le16(cmd_no); + cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); + cmd_ptr->params.mode_cfg.mode = cpu_to_le16(*(u16 *)data_buf); + cmd_ptr->size = + cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) + + S_DS_GEN); + break; case HostCmd_CMD_FUNC_INIT: if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 621d36e437f5..e380171c4c5d 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c @@ -669,6 +669,22 @@ mwifiex_ret_remain_on_chan(struct mwifiex_private *priv, return 0; } +/* + * This function handles the command response of P2P mode cfg. + */ +static int +mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv, + struct host_cmd_ds_command *resp, + void *data_buf) +{ + struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg; + + if (data_buf) + *((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode); + + return 0; +} + /* * This function handles the command response of register access. * @@ -894,6 +910,9 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, case HostCmd_CMD_REMAIN_ON_CHAN: ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); break; + case HostCmd_CMD_P2P_MODE_CFG: + ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); + break; case HostCmd_CMD_MGMT_FRAME_REG: case HostCmd_CMD_FUNC_INIT: case HostCmd_CMD_FUNC_SHUTDOWN: From 9197ab9e5f3016ad05e1aa3e627ddf7d08927ccf Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:42 -0700 Subject: [PATCH 51/73] mwifiex: add support for P2P GO in interface type change When cfg80211 calls to change interface type for P2P GO, send P2P mode config commands to firmware and set bss role and bss mode accordingly. Signed-off-by: Stone Piao Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 42 ++++++++++++++++++++++-- drivers/net/wireless/mwifiex/fw.h | 1 + drivers/net/wireless/mwifiex/init.c | 13 +++++++- drivers/net/wireless/mwifiex/main.h | 5 +++ drivers/net/wireless/mwifiex/sta_cmd.c | 2 ++ drivers/net/wireless/mwifiex/sta_ioctl.c | 30 +++++++++++++++++ 6 files changed, 90 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 499060304d15..94ac40c50062 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -679,6 +679,9 @@ mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) { u16 mode = P2P_MODE_DISABLE; + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) + mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_STA); + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, HostCmd_ACT_GEN_SET, 0, &mode)) return -1; @@ -712,6 +715,35 @@ mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) return 0; } +/* + * This function initializes the functionalities for P2P GO. + * The P2P GO initialization sequence is: + * disable -> device -> GO + */ +static int +mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) +{ + u16 mode; + + if (mwifiex_cfg80211_deinit_p2p(priv)) + return -1; + + mode = P2P_MODE_DEVICE; + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode)) + return -1; + + mode = P2P_MODE_GO; + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_P2P_MODE_CFG, + HostCmd_ACT_GEN_SET, 0, &mode)) + return -1; + + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) + mwifiex_set_bss_role(priv, MWIFIEX_BSS_ROLE_UAP); + + return 0; +} + /* * CFG802.11 operation handler to change interface type. */ @@ -749,6 +781,11 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, return -EFAULT; dev->ieee80211_ptr->iftype = type; return 0; + case NL80211_IFTYPE_P2P_GO: + if (mwifiex_cfg80211_init_p2p_go(priv)) + return -EFAULT; + dev->ieee80211_ptr->iftype = type; + return 0; case NL80211_IFTYPE_UNSPECIFIED: wiphy_warn(wiphy, "%s: kept type as STA\n", dev->name); case NL80211_IFTYPE_STATION: /* This shouldn't happen */ @@ -775,6 +812,7 @@ mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, } break; case NL80211_IFTYPE_P2P_CLIENT: + case NL80211_IFTYPE_P2P_GO: switch (type) { case NL80211_IFTYPE_STATION: if (mwifiex_cfg80211_deinit_p2p(priv)) @@ -1135,7 +1173,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, { struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) { wiphy_err(wiphy, "%s: bss_type mismatched\n", __func__); return -EINVAL; } @@ -1223,7 +1261,7 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); u8 config_bands = 0; - if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) + if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) return -1; if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) return -1; diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 7887848448e9..857af0f9542c 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -1379,6 +1379,7 @@ struct host_cmd_ds_802_11_ibss_status { #define CONNECTION_TYPE_INFRA 0 #define CONNECTION_TYPE_ADHOC 1 +#define CONNECTION_TYPE_AP 2 struct host_cmd_ds_set_bss_mode { u8 con_type; diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index fa96dc328a5b..b5d37a8caa09 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c @@ -144,7 +144,7 @@ static void scan_delay_timer_fn(unsigned long data) * Additionally, it also initializes all the locks and sets up all the * lists. */ -static int mwifiex_init_priv(struct mwifiex_private *priv) +int mwifiex_init_priv(struct mwifiex_private *priv) { u32 i; @@ -648,6 +648,17 @@ static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) } } +/* + * This function frees the private structure, including cleans + * up the TX and RX queues and frees the BSS priority tables. + */ +void mwifiex_free_priv(struct mwifiex_private *priv) +{ + mwifiex_clean_txrx(priv); + mwifiex_delete_bss_prio_tbl(priv); + mwifiex_free_curr_bcn(priv); +} + /* * This function is used to shutdown the driver. * diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 89ba66e56143..956312f45e60 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -736,6 +736,9 @@ void mwifiex_stop_net_dev_queue(struct net_device *netdev, void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, struct mwifiex_adapter *adapter); +int mwifiex_init_priv(struct mwifiex_private *priv); +void mwifiex_free_priv(struct mwifiex_private *priv); + int mwifiex_init_fw(struct mwifiex_adapter *adapter); int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); @@ -1018,6 +1021,8 @@ int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, enum nl80211_channel_type *channel_type, unsigned int duration); +int mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role); + int mwifiex_get_stats_info(struct mwifiex_private *priv, struct mwifiex_ds_get_stats *log); diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c index 704cfaaeba14..5d87195390f8 100644 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ b/drivers/net/wireless/mwifiex/sta_cmd.c @@ -1261,6 +1261,8 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, else if (priv->bss_mode == NL80211_IFTYPE_STATION) cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_INFRA; + else if (priv->bss_mode == NL80211_IFTYPE_AP) + cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP; cmd_ptr->size = cpu_to_le16(sizeof(struct host_cmd_ds_set_bss_mode) + S_DS_GEN); ret = 0; diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index fd09a21b8824..0c9f70b2cbe6 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c @@ -1072,6 +1072,36 @@ mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, return roc_cfg.status; } +int +mwifiex_set_bss_role(struct mwifiex_private *priv, u8 bss_role) +{ + if (GET_BSS_ROLE(priv) == bss_role) { + dev_dbg(priv->adapter->dev, + "info: already in the desired role.\n"); + return 0; + } + + mwifiex_free_priv(priv); + mwifiex_init_priv(priv); + + priv->bss_role = bss_role; + switch (bss_role) { + case MWIFIEX_BSS_ROLE_UAP: + priv->bss_mode = NL80211_IFTYPE_AP; + break; + case MWIFIEX_BSS_ROLE_STA: + case MWIFIEX_BSS_ROLE_ANY: + default: + priv->bss_mode = NL80211_IFTYPE_STATION; + break; + } + + mwifiex_send_cmd_sync(priv, HostCmd_CMD_SET_BSS_MODE, + HostCmd_ACT_GEN_SET, 0, NULL); + + return mwifiex_sta_init_cmd(priv, false); +} + /* * Sends IOCTL request to get statistics information. * From 8a6e231766bdd2e1d228a14af89e36dc190be3a6 Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:43 -0700 Subject: [PATCH 52/73] mwifiex: parse P2P IEs from beacon_data Parse P2P IEs and set them to FW with related masks. Signed-off-by: Stone Piao Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/ie.c | 86 +++++++++++++++++++------------ 1 file changed, 54 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c index fa3a80fb8c01..e38342f86c51 100644 --- a/drivers/net/wireless/mwifiex/ie.c +++ b/drivers/net/wireless/mwifiex/ie.c @@ -114,9 +114,6 @@ mwifiex_update_autoindex_ies(struct mwifiex_private *priv, cpu_to_le16(mask); ie->ie_index = cpu_to_le16(index); - ie->ie_length = priv->mgmt_ie[index].ie_length; - memcpy(&ie->ie_buffer, &priv->mgmt_ie[index].ie_buffer, - le16_to_cpu(priv->mgmt_ie[index].ie_length)); } else { if (mask != MWIFIEX_DELETE_MASK) return -1; @@ -214,30 +211,35 @@ mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, return ret; } -/* This function checks if WPS IE is present in passed buffer and copies it to - * mwifiex_ie structure. +/* This function checks if the vendor specified IE is present in passed buffer + * and copies it to mwifiex_ie structure. * Function takes pointer to struct mwifiex_ie pointer as argument. - * If WPS IE is present memory is allocated for mwifiex_ie pointer and filled - * in with WPS IE. Caller should take care of freeing this memory. + * If the vendor specified IE is present then memory is allocated for + * mwifiex_ie pointer and filled in with IE. Caller should take care of freeing + * this memory. */ -static int mwifiex_update_wps_ie(const u8 *ies, int ies_len, - struct mwifiex_ie **ie_ptr, u16 mask) +static int mwifiex_update_vs_ie(const u8 *ies, int ies_len, + struct mwifiex_ie **ie_ptr, u16 mask, + unsigned int oui, u8 oui_type) { - struct ieee_types_header *wps_ie; - struct mwifiex_ie *ie = NULL; + struct ieee_types_header *vs_ie; + struct mwifiex_ie *ie = *ie_ptr; const u8 *vendor_ie; - vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS, - ies, ies_len); + vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len); if (vendor_ie) { - ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); - if (!ie) - return -ENOMEM; + if (!*ie_ptr) { + *ie_ptr = kzalloc(sizeof(struct mwifiex_ie), + GFP_KERNEL); + if (!*ie_ptr) + return -ENOMEM; + ie = *ie_ptr; + } - wps_ie = (struct ieee_types_header *)vendor_ie; - memcpy(ie->ie_buffer, wps_ie, wps_ie->len + 2); - ie->ie_length = cpu_to_le16(wps_ie->len + 2); + vs_ie = (struct ieee_types_header *)vendor_ie; + memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length), + vs_ie, vs_ie->len + 2); + le16_add_cpu(&ie->ie_length, vs_ie->len + 2); ie->mgmt_subtype_mask = cpu_to_le16(mask); ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK); } @@ -257,20 +259,40 @@ static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv, u16 ar_idx = MWIFIEX_AUTO_IDX_MASK; int ret = 0; - if (data->beacon_ies && data->beacon_ies_len) - mwifiex_update_wps_ie(data->beacon_ies, data->beacon_ies_len, - &beacon_ie, MGMT_MASK_BEACON); + if (data->beacon_ies && data->beacon_ies_len) { + mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len, + &beacon_ie, MGMT_MASK_BEACON, + WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS); + mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len, + &beacon_ie, MGMT_MASK_BEACON, + WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); + } - if (data->proberesp_ies && data->proberesp_ies_len) - mwifiex_update_wps_ie(data->proberesp_ies, - data->proberesp_ies_len, &pr_ie, - MGMT_MASK_PROBE_RESP); + if (data->proberesp_ies && data->proberesp_ies_len) { + mwifiex_update_vs_ie(data->proberesp_ies, + data->proberesp_ies_len, &pr_ie, + MGMT_MASK_PROBE_RESP, WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS); + mwifiex_update_vs_ie(data->proberesp_ies, + data->proberesp_ies_len, &pr_ie, + MGMT_MASK_PROBE_RESP, + WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); + } - if (data->assocresp_ies && data->assocresp_ies_len) - mwifiex_update_wps_ie(data->assocresp_ies, - data->assocresp_ies_len, &ar_ie, - MGMT_MASK_ASSOC_RESP | - MGMT_MASK_REASSOC_RESP); + if (data->assocresp_ies && data->assocresp_ies_len) { + mwifiex_update_vs_ie(data->assocresp_ies, + data->assocresp_ies_len, &ar_ie, + MGMT_MASK_ASSOC_RESP | + MGMT_MASK_REASSOC_RESP, + WLAN_OUI_MICROSOFT, + WLAN_OUI_TYPE_MICROSOFT_WPS); + mwifiex_update_vs_ie(data->assocresp_ies, + data->assocresp_ies_len, &ar_ie, + MGMT_MASK_ASSOC_RESP | + MGMT_MASK_REASSOC_RESP, WLAN_OUI_WFA, + WLAN_OUI_TYPE_WFA_P2P); + } if (beacon_ie || pr_ie || ar_ie) { ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, From 3215215a9e7cd8010ba83bbaf75a718aad5aec0d Mon Sep 17 00:00:00 2001 From: Stone Piao Date: Tue, 25 Sep 2012 20:23:44 -0700 Subject: [PATCH 53/73] mwifiex: set txpd when send a mgmt frame for AP and GO mode Set packet type and packet offset in txpd when send a mgmt frame in AP and GO mode. Signed-off-by: Stone Piao Signed-off-by: Kevin Gan Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/uap_txrx.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c index 012c1433d126..0966ac24b3b4 100644 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ b/drivers/net/wireless/mwifiex/uap_txrx.c @@ -284,6 +284,7 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, struct uap_txpd *txpd; struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); int pad, len; + u16 pkt_type; if (!skb->len) { dev_err(adapter->dev, "Tx: bad packet length: %d\n", skb->len); @@ -291,6 +292,8 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, return skb->data; } + pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; + /* If skb->data is not aligned, add padding */ pad = (4 - (((void *)skb->data - NULL) & 0x3)) % 4; @@ -318,6 +321,12 @@ void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]); /* Offset of actual data */ + if (pkt_type == PKT_TYPE_MGMT) { + /* Set the packet type and add header for management frame */ + txpd->tx_pkt_type = cpu_to_le16(pkt_type); + len += MWIFIEX_MGMT_FRAME_HEADER_SIZE; + } + txpd->tx_pkt_offset = cpu_to_le16(len); /* make space for INTF_HEADER_LEN */ From 8b4509f642743e87f9a5c34bacb5d4b63ac730b4 Mon Sep 17 00:00:00 2001 From: Kevin Gan Date: Tue, 25 Sep 2012 20:23:45 -0700 Subject: [PATCH 54/73] mwifiex: add inactivity deauth support for ap The firmware has support for this feature, so we offload it to firmware. In start_ap, driver passes the inactivity timeout value to firmware via TLVs and firmware will report STA_DEAUTH event to driver when inactivity timer is fired. Signed-off-by: Kevin Gan Signed-off-by: Avinash Patil Signed-off-by: Nishant Sarmukadam Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/cfg80211.c | 9 ++++++++- drivers/net/wireless/mwifiex/fw.h | 7 +++++++ drivers/net/wireless/mwifiex/ioctl.h | 2 ++ drivers/net/wireless/mwifiex/uap_cmd.c | 22 ++++++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 94ac40c50062..2691620393ea 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c @@ -1331,6 +1331,12 @@ static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, mwifiex_set_ht_params(priv, bss_cfg, params); + if (params->inactivity_timeout > 0) { + /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ + bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; + bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; + } + if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP, HostCmd_ACT_GEN_SET, 0, NULL)) { wiphy_err(wiphy, "Failed to stop the BSS\n"); @@ -2229,7 +2235,8 @@ int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; - wiphy->features = NL80211_FEATURE_HT_IBSS; + wiphy->features = NL80211_FEATURE_HT_IBSS | + NL80211_FEATURE_INACTIVITY_TIMER; /* Reserve space for mwifiex specific private data for BSS */ wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 857af0f9542c..dda588b35570 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h @@ -128,6 +128,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) #define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) #define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) +#define TLV_TYPE_UAP_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 57) #define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59) #define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) #define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) @@ -142,6 +143,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { #define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) #define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) #define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) +#define TLV_TYPE_UAP_PS_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 123) #define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) #define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) @@ -1344,6 +1346,11 @@ struct host_cmd_tlv_channel_band { u8 channel; } __packed; +struct host_cmd_tlv_ageout_timer { + struct host_cmd_tlv tlv; + __le32 sta_ao_timer; +} __packed; + struct host_cmd_ds_version_ext { u8 version_str_sel; char version_str[128]; diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h index 8688535e95eb..4e31c6013ebe 100644 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ b/drivers/net/wireless/mwifiex/ioctl.h @@ -105,6 +105,8 @@ struct mwifiex_uap_bss_param { struct wep_key wep_cfg[NUM_WEP_KEYS]; struct ieee80211_ht_cap ht_cap; u8 rates[MWIFIEX_SUPPORTED_RATES]; + u32 sta_ao_timer; + u32 ps_sta_ao_timer; }; enum { diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 8a627d856d18..d95a2d558fcf 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c @@ -343,6 +343,7 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; struct host_cmd_tlv_auth_type *auth_type; struct host_cmd_tlv_rates *tlv_rates; + struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; struct mwifiex_ie_types_htcap *htcap; struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; int i; @@ -497,6 +498,27 @@ mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) tlv += sizeof(struct mwifiex_ie_types_htcap); } + if (bss_cfg->sta_ao_timer) { + ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; + ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); + ao_timer->tlv.len = cpu_to_le16(sizeof(*ao_timer) - + sizeof(struct host_cmd_tlv)); + ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer); + cmd_size += sizeof(*ao_timer); + tlv += sizeof(*ao_timer); + } + + if (bss_cfg->ps_sta_ao_timer) { + ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; + ps_ao_timer->tlv.type = cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER); + ps_ao_timer->tlv.len = cpu_to_le16(sizeof(*ps_ao_timer) - + sizeof(struct host_cmd_tlv)); + ps_ao_timer->sta_ao_timer = + cpu_to_le32(bss_cfg->ps_sta_ao_timer); + cmd_size += sizeof(*ps_ao_timer); + tlv += sizeof(*ps_ao_timer); + } + *param_size = cmd_size; return 0; From 365d2ebcaba5f08590b8a988d137f7139a8163a5 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Wed, 26 Sep 2012 12:22:08 +0530 Subject: [PATCH 55/73] ath9k: Fix chainmask selection for AR9462 Force chain 1 to be used for CCK rates since the target power table stored in EEPROM is too high to transmit with both chains. This is needed to avoid regulatory violation. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ath9k.h | 2 ++ drivers/net/wireless/ath/ath9k/xmit.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8e27f4fb21fe..dfe6a4707fd2 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -173,6 +173,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, #define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) +#define IS_CCK_RATE(rate) ((rate >= 0x18) && (rate <= 0x1e)) + #define ATH_TX_COMPLETE_POLL_INT 1000 enum ATH_AGGR_STATUS { diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index b088fa0eb022..36618e3a5e60 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -1820,10 +1820,14 @@ u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate) { struct ath_hw *ah = sc->sc_ah; struct ath9k_channel *curchan = ah->curchan; + if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (curchan->channelFlags & CHANNEL_5GHZ) && (chainmask == 0x7) && (rate < 0x90)) return 0x3; + else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && + IS_CCK_RATE(rate)) + return 0x2; else return chainmask; } From 58901d181f12807d6bfa7ef29547b560740dd305 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Wed, 26 Sep 2012 10:21:48 +0300 Subject: [PATCH 56/73] brcmfmac: use kcalloc() to prevent integer overflow The multiplication here looks like it could overflow. I've changed it to use kcalloc() to prevent that. Signed-off-by: Dan Carpenter Acked-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index e40cfe846a48..24e8f8d708ad 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3297,8 +3297,8 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv, int i; request = kzalloc(sizeof(*request), GFP_KERNEL); - ssid = kzalloc(sizeof(*ssid) * result_count, GFP_KERNEL); - channel = kzalloc(sizeof(*channel) * result_count, GFP_KERNEL); + ssid = kcalloc(result_count, sizeof(*ssid), GFP_KERNEL); + channel = kcalloc(result_count, sizeof(*channel), GFP_KERNEL); if (!request || !ssid || !channel) { err = -ENOMEM; goto out_err; From 6a73f507cf51a6a9e327fd9e36690072c657d36e Mon Sep 17 00:00:00 2001 From: Bala Shanmugam Date: Wed, 26 Sep 2012 17:04:26 +0530 Subject: [PATCH 57/73] ath9k: Enable MCI for AR9565 Signed-off-by: Bala Shanmugam Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/btcoex.c | 6 +++--- drivers/net/wireless/ath/ath9k/gpio.c | 2 +- drivers/net/wireless/ath/ath9k/wow.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index acd437384fe4..4ef610e63fcb 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -282,7 +282,7 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah) ath9k_hw_btcoex_enable_2wire(ah); break; case ATH_BTCOEX_CFG_3WIRE: - if (AR_SREV_9462(ah)) { + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { ath9k_hw_btcoex_enable_mci(ah); return; } @@ -304,7 +304,7 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) int i; btcoex_hw->enabled = false; - if (AR_SREV_9462(ah)) { + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE); for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++) REG_WRITE(ah, AR_MCI_COEX_WL_WEIGHTS(i), @@ -339,7 +339,7 @@ static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, const u32 *weight = ar9003_wlan_weights[stomp_type]; int i; - if (AR_SREV_9462(ah)) { + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && btcoex->mci.stomp_ftp) stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index bf7d29ec1a87..5faa4f777122 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -412,7 +412,7 @@ void ath9k_stop_btcoex(struct ath_softc *sc) if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) ath9k_btcoex_timer_pause(sc); ath9k_hw_btcoex_disable(ah); - if (AR_SREV_9462(ah)) + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) ath_mci_flush_profile(&sc->btcoex.mci); } } diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c index 44a08eb53c62..a483d518758c 100644 --- a/drivers/net/wireless/ath/ath9k/wow.c +++ b/drivers/net/wireless/ath/ath9k/wow.c @@ -497,7 +497,7 @@ void ath9k_hw_wow_enable(struct ath_hw *ah, u32 pattern_enable) REG_RMW(ah, AR_PCIE_PM_CTRL, set, clr); - if (AR_SREV_9462(ah)) { + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { /* * this is needed to prevent the chip waking up * the host within 3-4 seconds with certain From 2d838bb608e2d1f6cb4280e76748cb812dc822e7 Mon Sep 17 00:00:00 2001 From: Larry Finger Date: Wed, 26 Sep 2012 12:32:02 -0500 Subject: [PATCH 58/73] b43legacy: Fix crash on unload when firmware not available When b43legacy is loaded without the firmware being available, a following unload generates a kernel NULL pointer dereference BUG as follows: [ 214.330789] BUG: unable to handle kernel NULL pointer dereference at 0000004c [ 214.330997] IP: [] drain_workqueue+0x15/0x170 [ 214.331179] *pde = 00000000 [ 214.331311] Oops: 0000 [#1] SMP [ 214.331471] Modules linked in: b43legacy(-) ssb pcmcia mac80211 cfg80211 af_packet mperf arc4 ppdev sr_mod cdrom sg shpchp yenta_socket pcmcia_rsrc pci_hotplug pcmcia_core battery parport_pc parport floppy container ac button edd autofs4 ohci_hcd ehci_hcd usbcore usb_common thermal processor scsi_dh_rdac scsi_dh_hp_sw scsi_dh_emc scsi_dh_alua scsi_dh fan thermal_sys hwmon ata_generic pata_ali libata [last unloaded: cfg80211] [ 214.333421] Pid: 3639, comm: modprobe Not tainted 3.6.0-rc6-wl+ #163 Source Technology VIC 9921/ALI Based Notebook [ 214.333580] EIP: 0060:[] EFLAGS: 00010246 CPU: 0 [ 214.333687] EIP is at drain_workqueue+0x15/0x170 [ 214.333788] EAX: c162ac40 EBX: cdfb8360 ECX: 0000002a EDX: 00002a2a [ 214.333890] ESI: 00000000 EDI: 00000000 EBP: cd767e7c ESP: cd767e5c [ 214.333957] DS: 007b ES: 007b FS: 00d8 GS: 0033 SS: 0068 [ 214.333957] CR0: 8005003b CR2: 0000004c CR3: 0c96a000 CR4: 00000090 [ 214.333957] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 214.333957] DR6: ffff0ff0 DR7: 00000400 [ 214.333957] Process modprobe (pid: 3639, ti=cd766000 task=cf802e90 task.ti=cd766000) [ 214.333957] Stack: [ 214.333957] 00000292 cd767e74 c12c5e09 00000296 00000296 cdfb8360 cdfb9220 00000000 [ 214.333957] cd767e90 c104c4fd cdfb8360 cdfb9220 cd682800 cd767ea4 d0c10184 cd682800 [ 214.333957] cd767ea4 cba31064 cd767eb8 d0867908 cba31064 d087e09c cd96f034 cd767ec4 [ 214.333957] Call Trace: [ 214.333957] [] ? skb_dequeue+0x49/0x60 [ 214.333957] [] destroy_workqueue+0xd/0x150 [ 214.333957] [] ieee80211_unregister_hw+0xc4/0x100 [mac80211] [ 214.333957] [] b43legacy_remove+0x78/0x80 [b43legacy] [ 214.333957] [] ssb_device_remove+0x1d/0x30 [ssb] [ 214.333957] [] __device_release_driver+0x5a/0xb0 [ 214.333957] [] driver_detach+0x87/0x90 [ 214.333957] [] bus_remove_driver+0x6c/0xe0 [ 214.333957] [] driver_unregister+0x40/0x70 [ 214.333957] [] ssb_driver_unregister+0xb/0x10 [ssb] [ 214.333957] [] b43legacy_exit+0xd/0xf [b43legacy] [ 214.333957] [] sys_delete_module+0x14e/0x2b0 [ 214.333957] [] ? vfs_write+0xf7/0x150 [ 214.333957] [] ? tty_write_lock+0x50/0x50 [ 214.333957] [] ? sys_write+0x38/0x70 [ 214.333957] [] syscall_call+0x7/0xb [ 214.333957] Code: bc 27 00 00 00 00 a1 74 61 56 c1 55 89 e5 e8 a3 fc ff ff 5d c3 90 55 89 e5 57 56 89 c6 53 b8 40 ac 62 c1 83 ec 14 e8 bb b7 34 00 <8b> 46 4c 8d 50 01 85 c0 89 56 4c 75 03 83 0e 40 80 05 40 ac 62 [ 214.333957] EIP: [] drain_workqueue+0x15/0x170 SS:ESP 0068:cd767e5c [ 214.333957] CR2: 000000000000004c [ 214.341110] ---[ end trace c7e90ec026d875a6 ]---Index: wireless-testing/drivers/net/wireless/b43legacy/main.c The problem is fixed by making certain that the ucode pointer is not NULL before deregistering the driver in mac80211. Signed-off-by: Larry Finger Cc: Stable [v 3.3.0+] Signed-off-by: John W. Linville --- drivers/net/wireless/b43legacy/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c index 291cdf654088..18e208e3eca1 100644 --- a/drivers/net/wireless/b43legacy/main.c +++ b/drivers/net/wireless/b43legacy/main.c @@ -3895,6 +3895,8 @@ static void b43legacy_remove(struct ssb_device *dev) cancel_work_sync(&wl->firmware_load); B43legacy_WARN_ON(!wl); + if (!wldev->fw.ucode) + return; /* NULL if fw never loaded */ if (wl->current_dev == wldev) ieee80211_unregister_hw(wl->hw); From 70398a59297965d4af1a0022660bb103dfa59c42 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 27 Sep 2012 14:17:47 +0200 Subject: [PATCH 59/73] brcmfmac: use wait_event_timeout for fw control packets over usb. firmware control packets over usb are async acked. This is awaited for by using interruptible wait. This can be interrupted by signal which results in undesirable behavior. Instead wait_event_timeout is used. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 46 ++++--------------- 1 file changed, 9 insertions(+), 37 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 5fe6ec7f838e..555ccdd12210 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -160,40 +160,17 @@ static struct brcmf_usbdev_info *brcmf_usb_get_businfo(struct device *dev) return brcmf_usb_get_buspub(dev)->devinfo; } -static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo, - uint *condition, bool *pending) +static int brcmf_usb_ioctl_resp_wait(struct brcmf_usbdev_info *devinfo) { - DECLARE_WAITQUEUE(wait, current); - int timeout = IOCTL_RESP_TIMEOUT; - - /* Convert timeout in millsecond to jiffies */ - timeout = msecs_to_jiffies(timeout); - /* Wait until control frame is available */ - add_wait_queue(&devinfo->ioctl_resp_wait, &wait); - set_current_state(TASK_INTERRUPTIBLE); - - smp_mb(); - while (!(*condition) && (!signal_pending(current) && timeout)) { - timeout = schedule_timeout(timeout); - /* Wait until control frame is available */ - smp_mb(); - } - - if (signal_pending(current)) - *pending = true; - - set_current_state(TASK_RUNNING); - remove_wait_queue(&devinfo->ioctl_resp_wait, &wait); - - return timeout; + return wait_event_timeout(devinfo->ioctl_resp_wait, + devinfo->ctl_completed, + msecs_to_jiffies(IOCTL_RESP_TIMEOUT)); } -static int brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo) +static void brcmf_usb_ioctl_resp_wake(struct brcmf_usbdev_info *devinfo) { if (waitqueue_active(&devinfo->ioctl_resp_wait)) - wake_up_interruptible(&devinfo->ioctl_resp_wait); - - return 0; + wake_up(&devinfo->ioctl_resp_wait); } static void @@ -322,7 +299,6 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) { int err = 0; int timeout = 0; - bool pending; struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { @@ -340,9 +316,7 @@ static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len) clear_bit(0, &devinfo->ctl_op); return err; } - - timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, - &pending); + timeout = brcmf_usb_ioctl_resp_wait(devinfo); clear_bit(0, &devinfo->ctl_op); if (!timeout) { brcmf_dbg(ERROR, "Txctl wait timed out\n"); @@ -355,7 +329,6 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) { int err = 0; int timeout = 0; - bool pending; struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); if (devinfo->bus_pub.state != BCMFMAC_USB_STATE_UP) { @@ -365,15 +338,14 @@ static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len) if (test_and_set_bit(0, &devinfo->ctl_op)) return -EIO; + devinfo->ctl_completed = false; err = brcmf_usb_recv_ctl(devinfo, buf, len); if (err) { brcmf_dbg(ERROR, "fail %d bytes: %d\n", err, len); clear_bit(0, &devinfo->ctl_op); return err; } - devinfo->ctl_completed = false; - timeout = brcmf_usb_ioctl_resp_wait(devinfo, &devinfo->ctl_completed, - &pending); + timeout = brcmf_usb_ioctl_resp_wait(devinfo); err = devinfo->ctl_urb_status; clear_bit(0, &devinfo->ctl_op); if (!timeout) { From f09d0c02b63d9fd9873087b21311507988674221 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 27 Sep 2012 14:17:48 +0200 Subject: [PATCH 60/73] brcmfmac: use different fw api for encryption,auth. config This patch changes the commands being used to configure encryption and authentication. These new methods are needed for when p2p and hostap support are added. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 2 + .../wireless/brcm80211/brcmfmac/dhd_common.c | 46 +++ .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 266 +++++++++++------- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 2 + 4 files changed, 219 insertions(+), 97 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 55e489d2147d..9bb23b3854aa 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -658,6 +658,8 @@ extern const struct bcmevent_name bcmevent_names[]; extern uint brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint len); +extern uint brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, + char *buf, uint buflen, s32 bssidx); extern int brcmf_netdev_wait_pend8021x(struct net_device *ndev); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c index fbecde73f904..efcb5056f295 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c @@ -88,6 +88,52 @@ brcmf_c_mkiovar(char *name, char *data, uint datalen, char *buf, uint buflen) return len; } +uint +brcmf_c_mkiovar_bsscfg(char *name, char *data, uint datalen, + char *buf, uint buflen, s32 bssidx) +{ + const s8 *prefix = "bsscfg:"; + s8 *p; + u32 prefixlen; + u32 namelen; + u32 iolen; + __le32 bssidx_le; + + if (bssidx == 0) + return brcmf_c_mkiovar(name, data, datalen, buf, buflen); + + prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */ + namelen = (u32) strlen(name) + 1; /* lengh of iovar name + null */ + iolen = prefixlen + namelen + sizeof(bssidx_le) + datalen; + + if (buflen < 0 || iolen > (u32)buflen) { + brcmf_dbg(ERROR, "buffer is too short\n"); + return 0; + } + + p = buf; + + /* copy prefix, no null */ + memcpy(p, prefix, prefixlen); + p += prefixlen; + + /* copy iovar name including null */ + memcpy(p, name, namelen); + p += namelen; + + /* bss config index as first data */ + bssidx_le = cpu_to_le32(bssidx); + memcpy(p, &bssidx_le, sizeof(bssidx_le)); + p += sizeof(bssidx_le); + + /* parameter buffer follows */ + if (datalen) + memcpy(p, data, datalen); + + return iolen; + +} + bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, struct sk_buff *pkt, int prec) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 24e8f8d708ad..d0a2fa0babbf 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -366,6 +366,44 @@ brcmf_exec_dcmd_u32(struct net_device *ndev, u32 cmd, u32 *par) return err; } +static s32 +brcmf_dev_iovar_setbuf_bsscfg(struct net_device *ndev, s8 *name, + void *param, s32 paramlen, + void *buf, s32 buflen, s32 bssidx) +{ + s32 err = -ENOMEM; + u32 len; + + len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, + buf, buflen, bssidx); + BUG_ON(!len); + if (len > 0) + err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, buf, len); + if (err) + WL_ERR("error (%d)\n", err); + + return err; +} + +static s32 +brcmf_dev_iovar_getbuf_bsscfg(struct net_device *ndev, s8 *name, + void *param, s32 paramlen, + void *buf, s32 buflen, s32 bssidx) +{ + s32 err = -ENOMEM; + u32 len; + + len = brcmf_c_mkiovar_bsscfg(name, param, paramlen, + buf, buflen, bssidx); + BUG_ON(!len); + if (len > 0) + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, buf, len); + if (err) + WL_ERR("error (%d)\n", err); + + return err; +} + static void convert_key_from_CPU(struct brcmf_wsec_key *key, struct brcmf_wsec_key_le *key_le) { @@ -380,16 +418,22 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, memcpy(key_le->ea, key->ea, sizeof(key->ea)); } -static int send_key_to_dongle(struct net_device *ndev, - struct brcmf_wsec_key *key) +static int +send_key_to_dongle(struct brcmf_cfg80211_priv *cfg_priv, s32 bssidx, + struct net_device *ndev, struct brcmf_wsec_key *key) { int err; struct brcmf_wsec_key_le key_le; convert_key_from_CPU(key, &key_le); - err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, sizeof(key_le)); + + err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, + sizeof(key_le), + cfg_priv->extra_buf, + WL_EXTRA_BUF_MAX, bssidx); + if (err) - WL_ERR("WLC_SET_KEY error (%d)\n", err); + WL_ERR("wsec_key error (%d)\n", err); return err; } @@ -487,6 +531,49 @@ brcmf_dev_intvar_get(struct net_device *ndev, s8 *name, s32 *retval) return err; } +static s32 +brcmf_dev_intvar_set_bsscfg(struct net_device *ndev, s8 *name, u32 val, + s32 bssidx) +{ + s8 buf[BRCMF_DCMD_SMLEN]; + __le32 val_le; + + val_le = cpu_to_le32(val); + + return brcmf_dev_iovar_setbuf_bsscfg(ndev, name, &val_le, + sizeof(val_le), buf, sizeof(buf), + bssidx); +} + +static s32 +brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val, + s32 bssidx) +{ + s8 buf[BRCMF_DCMD_SMLEN]; + s32 err; + __le32 val_le; + + memset(buf, 0, sizeof(buf)); + err = brcmf_dev_iovar_getbuf_bsscfg(ndev, name, val, sizeof(*val), buf, + sizeof(buf), bssidx); + if (err == 0) { + memcpy(&val_le, buf, sizeof(val_le)); + *val = le32_to_cpu(val_le); + } + return err; +} + + +/* + * For now brcmf_find_bssidx will return 0. Once p2p gets implemented this + * should return the ndev matching bssidx. + */ +static s32 +brcmf_find_bssidx(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev) +{ + return 0; +} + static void brcmf_set_mpc(struct net_device *ndev, int mpc) { s32 err = 0; @@ -1600,14 +1687,15 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) } static s32 -brcmf_set_wep_sharedkey(struct net_device *ndev, - struct cfg80211_connect_params *sme) +brcmf_set_sharedkey(struct net_device *ndev, + struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; struct brcmf_wsec_key key; s32 val; s32 err = 0; + s32 bssidx; WL_CONN("key len (%d)\n", sme->key_len); @@ -1621,46 +1709,46 @@ brcmf_set_wep_sharedkey(struct net_device *ndev, if (sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) return 0; - if (sec->cipher_pairwise & - (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104)) { - memset(&key, 0, sizeof(key)); - key.len = (u32) sme->key_len; - key.index = (u32) sme->key_idx; - if (key.len > sizeof(key.data)) { - WL_ERR("Too long key length (%u)\n", key.len); - return -EINVAL; - } - memcpy(key.data, sme->key, key.len); - key.flags = BRCMF_PRIMARY_KEY; - switch (sec->cipher_pairwise) { - case WLAN_CIPHER_SUITE_WEP40: - key.algo = CRYPTO_ALGO_WEP1; - break; - case WLAN_CIPHER_SUITE_WEP104: - key.algo = CRYPTO_ALGO_WEP128; - break; - default: - WL_ERR("Invalid algorithm (%d)\n", - sme->crypto.ciphers_pairwise[0]); - return -EINVAL; - } - /* Set the new key/index */ - WL_CONN("key length (%d) key index (%d) algo (%d)\n", - key.len, key.index, key.algo); - WL_CONN("key \"%s\"\n", key.data); - err = send_key_to_dongle(ndev, &key); - if (err) - return err; + if (!(sec->cipher_pairwise & + (WLAN_CIPHER_SUITE_WEP40 | WLAN_CIPHER_SUITE_WEP104))) + return 0; - if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) { - WL_CONN("set auth_type to shared key\n"); - val = 1; /* shared key */ - err = brcmf_dev_intvar_set(ndev, "auth", val); - if (err) { - WL_ERR("set auth failed (%d)\n", err); - return err; - } - } + memset(&key, 0, sizeof(key)); + key.len = (u32) sme->key_len; + key.index = (u32) sme->key_idx; + if (key.len > sizeof(key.data)) { + WL_ERR("Too long key length (%u)\n", key.len); + return -EINVAL; + } + memcpy(key.data, sme->key, key.len); + key.flags = BRCMF_PRIMARY_KEY; + switch (sec->cipher_pairwise) { + case WLAN_CIPHER_SUITE_WEP40: + key.algo = CRYPTO_ALGO_WEP1; + break; + case WLAN_CIPHER_SUITE_WEP104: + key.algo = CRYPTO_ALGO_WEP128; + break; + default: + WL_ERR("Invalid algorithm (%d)\n", + sme->crypto.ciphers_pairwise[0]); + return -EINVAL; + } + /* Set the new key/index */ + WL_CONN("key length (%d) key index (%d) algo (%d)\n", + key.len, key.index, key.algo); + WL_CONN("key \"%s\"\n", key.data); + bssidx = brcmf_find_bssidx(cfg_priv, ndev); + err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); + if (err) + return err; + + if (sec->auth_type == NL80211_AUTHTYPE_SHARED_KEY) { + WL_CONN("set auth_type to shared key\n"); + val = WL_AUTH_SHARED_KEY; /* shared key */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", val, bssidx); + if (err) + WL_ERR("set auth failed (%d)\n", err); } return err; } @@ -1722,9 +1810,9 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - err = brcmf_set_wep_sharedkey(ndev, sme); + err = brcmf_set_sharedkey(ndev, sme); if (err) { - WL_ERR("brcmf_set_wep_sharedkey failed (%d)\n", err); + WL_ERR("brcmf_set_sharedkey failed (%d)\n", err); goto done; } @@ -1863,16 +1951,19 @@ static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool unicast, bool multicast) { + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); u32 index; u32 wsec; s32 err = 0; + s32 bssidx; WL_TRACE("Enter\n"); WL_CONN("key index (%d)\n", key_idx); if (!check_sys_up(wiphy)) return -EIO; - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); + bssidx = brcmf_find_bssidx(cfg_priv, ndev); + err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); if (err) { WL_ERR("WLC_GET_WSEC error (%d)\n", err); goto done; @@ -1895,9 +1986,11 @@ static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, const u8 *mac_addr, struct key_params *params) { + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; struct brcmf_wsec_key_le key_le; s32 err = 0; + s32 bssidx; memset(&key, 0, sizeof(key)); key.index = (u32) key_idx; @@ -1906,12 +1999,13 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, if (!is_multicast_ether_addr(mac_addr)) memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); key.len = (u32) params->key_len; + bssidx = brcmf_find_bssidx(cfg_priv, ndev); /* check for key index change */ if (key.len == 0) { /* key delete */ - err = send_key_to_dongle(ndev, &key); + err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); if (err) - return err; + WL_ERR("key delete error (%d)\n", err); } else { if (key.len > sizeof(key.data)) { WL_ERR("Invalid key length (%d)\n", key.len); @@ -1967,12 +2061,12 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, convert_key_from_CPU(&key, &key_le); brcmf_netdev_wait_pend8021x(ndev); - err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_KEY, &key_le, - sizeof(key_le)); - if (err) { - WL_ERR("WLC_SET_KEY error (%d)\n", err); - return err; - } + err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, + sizeof(key_le), + cfg_priv->extra_buf, + WL_EXTRA_BUF_MAX, bssidx); + if (err) + WL_ERR("wsec_key error (%d)\n", err); } return err; } @@ -1982,11 +2076,13 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params) { + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; s32 val; s32 wsec; s32 err = 0; u8 keybuf[8]; + s32 bssidx; WL_TRACE("Enter\n"); WL_CONN("key index (%d)\n", key_idx); @@ -2013,10 +2109,12 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, switch (params->cipher) { case WLAN_CIPHER_SUITE_WEP40: key.algo = CRYPTO_ALGO_WEP1; + val = WEP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); break; case WLAN_CIPHER_SUITE_WEP104: key.algo = CRYPTO_ALGO_WEP128; + val = WEP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); break; case WLAN_CIPHER_SUITE_TKIP: @@ -2024,14 +2122,17 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); memcpy(&key.data[16], keybuf, sizeof(keybuf)); key.algo = CRYPTO_ALGO_TKIP; + val = TKIP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); break; case WLAN_CIPHER_SUITE_AES_CMAC: key.algo = CRYPTO_ALGO_AES_CCM; + val = AES_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_AES_CMAC\n"); break; case WLAN_CIPHER_SUITE_CCMP: key.algo = CRYPTO_ALGO_AES_CCM; + val = AES_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_CCMP\n"); break; default: @@ -2040,28 +2141,23 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, goto done; } - err = send_key_to_dongle(ndev, &key); /* Set the new key/index */ + bssidx = brcmf_find_bssidx(cfg_priv, ndev); + err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); if (err) goto done; - val = WEP_ENABLED; - err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); + err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); if (err) { WL_ERR("get wsec error (%d)\n", err); goto done; } - wsec &= ~(WEP_ENABLED); wsec |= val; - err = brcmf_dev_intvar_set(ndev, "wsec", wsec); + err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); if (err) { WL_ERR("set wsec error (%d)\n", err); goto done; } - val = 1; /* assume shared key. otherwise 0 */ - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); - if (err) - WL_ERR("WLC_SET_AUTH error (%d)\n", err); done: WL_TRACE("Exit\n"); return err; @@ -2071,10 +2167,10 @@ static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr) { + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; s32 err = 0; - s32 val; - s32 wsec; + s32 bssidx; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) @@ -2089,7 +2185,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("key index (%d)\n", key_idx); /* Set the new key/index */ - err = send_key_to_dongle(ndev, &key); + bssidx = brcmf_find_bssidx(cfg_priv, ndev); + err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); if (err) { if (err == -EINVAL) { if (key.index >= DOT11_MAX_DEFAULT_KEYS) @@ -2098,35 +2195,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, } /* Ignore this error, may happen during DISASSOC */ err = -EAGAIN; - goto done; } - val = 0; - err = brcmf_dev_intvar_get(ndev, "wsec", &wsec); - if (err) { - WL_ERR("get wsec error (%d)\n", err); - /* Ignore this error, may happen during DISASSOC */ - err = -EAGAIN; - goto done; - } - wsec &= ~(WEP_ENABLED); - wsec |= val; - err = brcmf_dev_intvar_set(ndev, "wsec", wsec); - if (err) { - WL_ERR("set wsec error (%d)\n", err); - /* Ignore this error, may happen during DISASSOC */ - err = -EAGAIN; - goto done; - } - - val = 0; /* assume open key. otherwise 1 */ - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AUTH, &val); - if (err) { - WL_ERR("WLC_SET_AUTH error (%d)\n", err); - /* Ignore this error, may happen during DISASSOC */ - err = -EAGAIN; - } -done: WL_TRACE("Exit\n"); return err; } @@ -2141,6 +2211,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_cfg80211_security *sec; s32 wsec; s32 err = 0; + s32 bssidx; WL_TRACE("Enter\n"); WL_CONN("key index (%d)\n", key_idx); @@ -2149,14 +2220,15 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, memset(¶ms, 0, sizeof(params)); - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_WSEC, &wsec); + bssidx = brcmf_find_bssidx(cfg_priv, ndev); + err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); if (err) { WL_ERR("WLC_GET_WSEC error (%d)\n", err); /* Ignore this error, may happen during DISASSOC */ err = -EAGAIN; goto done; } - switch (wsec) { + switch (wsec & ~SES_OW_ENABLED) { case WEP_ENABLED: sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 52e408ed6f41..f2069e89137f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -130,6 +130,8 @@ do { \ #define WL_ESCAN_ACTION_CONTINUE 2 #define WL_ESCAN_ACTION_ABORT 3 +#define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ + /* dongle status */ enum wl_status { WL_STATUS_READY, From 040128950595d3e71ff84810044b8ed35208232f Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 27 Sep 2012 14:17:49 +0200 Subject: [PATCH 61/73] brcmfmac: use define instead of hardcoded values. brcmf_parse_tlvs was using hardcoded values. Reviewed-by: Arend Van Spriel Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index d0a2fa0babbf..8674d344f245 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -48,6 +48,8 @@ #define BRCMF_PNO_SCAN_COMPLETE 1 #define BRCMF_PNO_SCAN_INCOMPLETE 0 +#define TLV_HDR_LEN 2 /* header length */ + #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) @@ -2608,15 +2610,15 @@ static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) totlen = buflen; /* find tagged parameter */ - while (totlen >= 2) { + while (totlen >= TLV_HDR_LEN) { int len = elt->len; /* validate remaining totlen */ - if ((elt->id == key) && (totlen >= (len + 2))) + if ((elt->id == key) && (totlen >= (len + TLV_HDR_LEN))) return elt; - elt = (struct brcmf_tlv *) ((u8 *) elt + (len + 2)); - totlen -= (len + 2); + elt = (struct brcmf_tlv *) ((u8 *) elt + (len + TLV_HDR_LEN)); + totlen -= (len + TLV_HDR_LEN); } return NULL; From 1e2d958b5108ac40d7fb0b33355ec37480fdbe55 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 27 Sep 2012 14:17:50 +0200 Subject: [PATCH 62/73] brcmfmac: notify common driver about usb tx completion. brcmf_usb_tx_complete now calls brcmf_txcomplete to correct eapol counter. Reviewed-by: Arend Van Spriel Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/usb.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index 555ccdd12210..a2b4b1e71017 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c @@ -465,6 +465,8 @@ static void brcmf_usb_tx_complete(struct urb *urb) else devinfo->bus_pub.bus->dstats.tx_errors++; + brcmf_txcomplete(devinfo->dev, req->skb, urb->status == 0); + brcmu_pkt_buf_free_skb(req->skb); req->skb = NULL; brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req, &devinfo->tx_freecount); From c3567a04cd63c98a27a7b5f2d9059f159943de5f Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 27 Sep 2012 14:17:51 +0200 Subject: [PATCH 63/73] brcmfmac: get rid of extern keyword in wl_cfg80211.h The function declarations in wl_cfg80211.h used the extern keyword but it is redundant as that is implicit so they were removed. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index f2069e89137f..9e478e0f1a89 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -497,15 +497,15 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) return &cfg->conn_info; } -extern struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, - struct device *busdev, - struct brcmf_pub *drvr); -extern void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); +struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, + struct device *busdev, + struct brcmf_pub *drvr); +void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); /* event handler from dongle */ -extern void brcmf_cfg80211_event(struct net_device *ndev, - const struct brcmf_event_msg *e, void *data); -extern s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); -extern s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); +void brcmf_cfg80211_event(struct net_device *ndev, + const struct brcmf_event_msg *e, void *data); +s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); +s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); #endif /* _wl_cfg80211_h_ */ From b451ec94de3338da33aedd1768a197790bf23eca Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 27 Sep 2012 14:17:52 +0200 Subject: [PATCH 64/73] brcmfmac: use brcmf_cfg80211_priv to interface with wl_cfg80211 code The low-level driver part interfaces with wl_cfg80211 part using brcmf_cfg80211_dev structure as handle. As brcmf_cfg80211_priv is defined in interface it is more efficient to use that as handle in function calls. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 2 +- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 48 ++++--------------- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 12 ++--- 3 files changed, 15 insertions(+), 47 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index 9bb23b3854aa..fc4bc6d6cb82 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -585,7 +585,7 @@ struct brcmf_pub { /* Linkage ponters */ struct brcmf_bus *bus_if; struct brcmf_proto *prot; - struct brcmf_cfg80211_dev *config; + struct brcmf_cfg80211_priv *config; struct device *dev; /* fullmac dongle device pointer */ /* Internal brcmf items */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 8674d344f245..0a30f9c67821 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -57,27 +57,6 @@ static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255}; static u32 brcmf_dbg_level = WL_DBG_ERR; -static void brcmf_set_drvdata(struct brcmf_cfg80211_dev *dev, void *data) -{ - dev->driver_data = data; -} - -static void *brcmf_get_drvdata(struct brcmf_cfg80211_dev *dev) -{ - void *data = NULL; - - if (dev) - data = dev->driver_data; - return data; -} - -static -struct brcmf_cfg80211_priv *brcmf_priv_get(struct brcmf_cfg80211_dev *cfg_dev) -{ - struct brcmf_cfg80211_iface *ci = brcmf_get_drvdata(cfg_dev); - return ci->cfg_priv; -} - static bool check_sys_up(struct wiphy *wiphy) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); @@ -4338,9 +4317,9 @@ static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) brcmf_deinit_priv_mem(cfg_priv); } -struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, - struct device *busdev, - struct brcmf_pub *drvr) +struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, + struct device *busdev, + struct brcmf_pub *drvr) { struct wireless_dev *wdev; struct brcmf_cfg80211_priv *cfg_priv; @@ -4376,9 +4355,8 @@ struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, WL_ERR("Failed to init iwm_priv (%d)\n", err); goto cfg80211_attach_out; } - brcmf_set_drvdata(cfg_dev, ci); - - return cfg_dev; + kfree(cfg_dev); + return cfg_priv; cfg80211_attach_out: brcmf_free_wdev(cfg_priv); @@ -4386,16 +4364,10 @@ struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, return NULL; } -void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg_dev) +void brcmf_cfg80211_detach(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_priv *cfg_priv; - - cfg_priv = brcmf_priv_get(cfg_dev); - wl_deinit_priv(cfg_priv); brcmf_free_wdev(cfg_priv); - brcmf_set_drvdata(cfg_dev, NULL); - kfree(cfg_dev); } void @@ -4754,12 +4726,10 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) return 0; } -s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev) +s32 brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_priv *cfg_priv; s32 err = 0; - cfg_priv = brcmf_priv_get(cfg_dev); mutex_lock(&cfg_priv->usr_sync); err = __brcmf_cfg80211_up(cfg_priv); mutex_unlock(&cfg_priv->usr_sync); @@ -4767,12 +4737,10 @@ s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev) return err; } -s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev) +s32 brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) { - struct brcmf_cfg80211_priv *cfg_priv; s32 err = 0; - cfg_priv = brcmf_priv_get(cfg_dev); mutex_lock(&cfg_priv->usr_sync); err = __brcmf_cfg80211_down(cfg_priv); mutex_unlock(&cfg_priv->usr_sync); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 9e478e0f1a89..618a600c640c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -497,15 +497,15 @@ brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) return &cfg->conn_info; } -struct brcmf_cfg80211_dev *brcmf_cfg80211_attach(struct net_device *ndev, - struct device *busdev, - struct brcmf_pub *drvr); -void brcmf_cfg80211_detach(struct brcmf_cfg80211_dev *cfg); +struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, + struct device *busdev, + struct brcmf_pub *drvr); +void brcmf_cfg80211_detach(struct brcmf_cfg80211_priv *cfg_priv); /* event handler from dongle */ void brcmf_cfg80211_event(struct net_device *ndev, const struct brcmf_event_msg *e, void *data); -s32 brcmf_cfg80211_up(struct brcmf_cfg80211_dev *cfg_dev); -s32 brcmf_cfg80211_down(struct brcmf_cfg80211_dev *cfg_dev); +s32 brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv); +s32 brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv); #endif /* _wl_cfg80211_h_ */ From 5db6e95645553ff027ad5a093a61cc4a33596574 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 27 Sep 2012 14:17:53 +0200 Subject: [PATCH 65/73] brcmfmac: remove two obsolete structure definitions The structures brcmf_cfg80211_dev and brcmf_cfg80211_iface are only adding complexity and provide no additional value. These have been removed in this patch. Reviewed-by: Pieter-Paul Giesberts Reviewed-by: Hante Meuleman Reviewed-by: Franky (Zhenhui) Lin Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 21 +++++-------------- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 19 +++-------------- 2 files changed, 8 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 0a30f9c67821..1c464a57e9f3 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -3646,8 +3646,7 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) #endif } -static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, - struct device *ndev) +static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) { struct wireless_dev *wdev; s32 err = 0; @@ -3656,9 +3655,8 @@ static struct wireless_dev *brcmf_alloc_wdev(s32 sizeof_iface, if (!wdev) return ERR_PTR(-ENOMEM); - wdev->wiphy = - wiphy_new(&wl_cfg80211_ops, - sizeof(struct brcmf_cfg80211_priv) + sizeof_iface); + wdev->wiphy = wiphy_new(&wl_cfg80211_ops, + sizeof(struct brcmf_cfg80211_priv)); if (!wdev->wiphy) { WL_ERR("Could not allocate wiphy device\n"); err = -ENOMEM; @@ -4323,21 +4321,15 @@ struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, { struct wireless_dev *wdev; struct brcmf_cfg80211_priv *cfg_priv; - struct brcmf_cfg80211_iface *ci; - struct brcmf_cfg80211_dev *cfg_dev; s32 err = 0; if (!ndev) { WL_ERR("ndev is invalid\n"); return NULL; } - cfg_dev = kzalloc(sizeof(struct brcmf_cfg80211_dev), GFP_KERNEL); - if (!cfg_dev) - return NULL; - wdev = brcmf_alloc_wdev(sizeof(struct brcmf_cfg80211_iface), busdev); + wdev = brcmf_alloc_wdev(busdev); if (IS_ERR(wdev)) { - kfree(cfg_dev); return NULL; } @@ -4345,8 +4337,6 @@ struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, cfg_priv = wdev_to_cfg(wdev); cfg_priv->wdev = wdev; cfg_priv->pub = drvr; - ci = (struct brcmf_cfg80211_iface *)&cfg_priv->ci; - ci->cfg_priv = cfg_priv; ndev->ieee80211_ptr = wdev; SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; @@ -4355,12 +4345,11 @@ struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, WL_ERR("Failed to init iwm_priv (%d)\n", err); goto cfg80211_attach_out; } - kfree(cfg_dev); + return cfg_priv; cfg80211_attach_out: brcmf_free_wdev(cfg_priv); - kfree(cfg_dev); return NULL; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 618a600c640c..97f36d329456 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -17,12 +17,6 @@ #ifndef _wl_cfg80211_h_ #define _wl_cfg80211_h_ -struct brcmf_cfg80211_conf; -struct brcmf_cfg80211_iface; -struct brcmf_cfg80211_priv; -struct brcmf_cfg80211_security; -struct brcmf_cfg80211_ibss; - #define WL_DBG_NONE 0 #define WL_DBG_CONN (1 << 5) #define WL_DBG_SCAN (1 << 4) @@ -178,6 +172,9 @@ struct brcmf_cfg80211_conf { struct ieee80211_channel channel; }; +/* forward declaration */ +struct brcmf_cfg80211_priv; + /* cfg80211 main event loop */ struct brcmf_cfg80211_event_loop { s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv, @@ -186,15 +183,6 @@ struct brcmf_cfg80211_event_loop { void *data); }; -/* representing interface of cfg80211 plane */ -struct brcmf_cfg80211_iface { - struct brcmf_cfg80211_priv *cfg_priv; -}; - -struct brcmf_cfg80211_dev { - void *driver_data; /* to store cfg80211 object information */ -}; - /* basic structure of scan request */ struct brcmf_cfg80211_scan_req { struct brcmf_ssid_le ssid_le; @@ -460,7 +448,6 @@ struct brcmf_cfg80211_priv { struct timer_list escan_timeout; struct work_struct escan_timeout_work; u8 *escan_ioctl_buf; - u8 ci[0] __aligned(NETDEV_ALIGN); }; static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) From 1a87334239757b69eb9885979c32bbf871b3ec88 Mon Sep 17 00:00:00 2001 From: Hante Meuleman Date: Thu, 27 Sep 2012 14:17:54 +0200 Subject: [PATCH 66/73] brcmfmac: add hostap supoort. This patch adds support for host AP mode. Reviewed-by: Arend Van Spriel Reviewed-by: Franky (Zhenhui) Lin Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Hante Meuleman Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 29 + .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 972 +++++++++++++++++- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 18 +- 3 files changed, 965 insertions(+), 54 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index fc4bc6d6cb82..eed695a97323 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -27,6 +27,7 @@ * IO codes that are interpreted by dongle firmware ******************************************************************************/ #define BRCMF_C_UP 2 +#define BRCMF_C_DOWN 3 #define BRCMF_C_SET_PROMISC 10 #define BRCMF_C_GET_RATE 12 #define BRCMF_C_GET_INFRA 19 @@ -50,7 +51,10 @@ #define BRCMF_C_REASSOC 53 #define BRCMF_C_SET_ROAM_TRIGGER 55 #define BRCMF_C_SET_ROAM_DELTA 57 +#define BRCMF_C_GET_BCNPRD 75 +#define BRCMF_C_SET_BCNPRD 76 #define BRCMF_C_GET_DTIMPRD 77 +#define BRCMF_C_SET_DTIMPRD 78 #define BRCMF_C_SET_COUNTRY 84 #define BRCMF_C_GET_PM 85 #define BRCMF_C_SET_PM 86 @@ -134,6 +138,9 @@ #define WLC_BSS_RSSI_ON_CHANNEL 0x0002 +#define BRCMF_MAXRATES_IN_SET 16 /* max # of rates in rateset */ +#define BRCMF_STA_ASSOC 0x10 /* Associated */ + struct brcmf_event_msg { __be16 version; __be16 flags; @@ -566,6 +573,28 @@ struct brcmf_channel_info_le { __le32 scan_channel; }; +struct brcmf_sta_info_le { + __le16 ver; /* version of this struct */ + __le16 len; /* length in bytes of this structure */ + __le16 cap; /* sta's advertised capabilities */ + __le32 flags; /* flags defined below */ + __le32 idle; /* time since data pkt rx'd from sta */ + u8 ea[ETH_ALEN]; /* Station address */ + __le32 count; /* # rates in this set */ + u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units */ + /* w/hi bit set if basic */ + __le32 in; /* seconds elapsed since associated */ + __le32 listen_interval_inms; /* Min Listen interval in ms for STA */ + __le32 tx_pkts; /* # of packets transmitted */ + __le32 tx_failures; /* # of packets failed */ + __le32 rx_ucast_pkts; /* # of unicast packets received */ + __le32 rx_mcast_pkts; /* # of multicast packets received */ + __le32 tx_rate; /* Rate of last successful tx frame */ + __le32 rx_rate; /* Rate of last successful rx frame */ + __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */ + __le32 rx_decrypt_failures; /* # of packet decrypted failed */ +}; + /* Bus independent dongle command */ struct brcmf_dcmd { uint cmd; /* common dongle cmd definition */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 1c464a57e9f3..0ecd0dfa6557 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -48,7 +48,45 @@ #define BRCMF_PNO_SCAN_COMPLETE 1 #define BRCMF_PNO_SCAN_INCOMPLETE 0 +#define TLV_LEN_OFF 1 /* length offset */ #define TLV_HDR_LEN 2 /* header length */ +#define TLV_BODY_OFF 2 /* body offset */ +#define TLV_OUI_LEN 3 /* oui id length */ +#define WPA_OUI "\x00\x50\xF2" /* WPA OUI */ +#define WPA_OUI_TYPE 1 +#define RSN_OUI "\x00\x0F\xAC" /* RSN OUI */ +#define WME_OUI_TYPE 2 + +#define VS_IE_FIXED_HDR_LEN 6 +#define WPA_IE_VERSION_LEN 2 +#define WPA_IE_MIN_OUI_LEN 4 +#define WPA_IE_SUITE_COUNT_LEN 2 + +#define WPA_CIPHER_NONE 0 /* None */ +#define WPA_CIPHER_WEP_40 1 /* WEP (40-bit) */ +#define WPA_CIPHER_TKIP 2 /* TKIP: default for WPA */ +#define WPA_CIPHER_AES_CCM 4 /* AES (CCM) */ +#define WPA_CIPHER_WEP_104 5 /* WEP (104-bit) */ + +#define RSN_AKM_NONE 0 /* None (IBSS) */ +#define RSN_AKM_UNSPECIFIED 1 /* Over 802.1x */ +#define RSN_AKM_PSK 2 /* Pre-shared Key */ +#define RSN_CAP_LEN 2 /* Length of RSN capabilities */ +#define RSN_CAP_PTK_REPLAY_CNTR_MASK 0x000C + +#define VNDR_IE_CMD_LEN 4 /* length of the set command + * string :"add", "del" (+ NUL) + */ +#define VNDR_IE_COUNT_OFFSET 4 +#define VNDR_IE_PKTFLAG_OFFSET 8 +#define VNDR_IE_VSIE_OFFSET 12 +#define VNDR_IE_HDR_SIZE 12 +#define VNDR_IE_BEACON_FLAG 0x1 +#define VNDR_IE_PRBRSP_FLAG 0x2 +#define MAX_VNDR_IE_NUMBER 5 + +#define DOT11_MGMT_HDR_LEN 24 /* d11 management header len */ +#define DOT11_BCN_PRB_FIXED_LEN 12 /* beacon/probe fixed length */ #define BRCMF_ASSOC_PARAMS_FIXED_SIZE \ (sizeof(struct brcmf_assoc_params_le) - sizeof(u16)) @@ -250,6 +288,25 @@ struct brcmf_tlv { u8 data[1]; }; +/* Vendor specific ie. id = 221, oui and type defines exact ie */ +struct brcmf_vs_tlv { + u8 id; + u8 len; + u8 oui[3]; + u8 oui_type; +}; + +struct parsed_vndr_ie_info { + u8 *ie_ptr; + u32 ie_len; /* total length including id & length field */ + struct brcmf_vs_tlv vndrie; +}; + +struct parsed_vndr_ies { + u32 count; + struct parsed_vndr_ie_info ie_info[MAX_VNDR_IE_NUMBER]; +}; + /* Quarter dBm units to mW * Table starts at QDBM_OFFSET, so the first entry is mW for qdBm=153 * Table is offset so the last entry is largest mW value that fits in @@ -424,13 +481,11 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, struct vif_params *params) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct wireless_dev *wdev; s32 infra = 0; + s32 ap = 0; s32 err = 0; - WL_TRACE("Enter\n"); - if (!check_sys_up(wiphy)) - return -EIO; + WL_TRACE("Enter, ndev=%p, type=%d\n", ndev, type); switch (type) { case NL80211_IFTYPE_MONITOR: @@ -446,22 +501,37 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, cfg_priv->conf->mode = WL_MODE_BSS; infra = 1; break; + case NL80211_IFTYPE_AP: + cfg_priv->conf->mode = WL_MODE_AP; + ap = 1; + break; default: err = -EINVAL; goto done; } - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); - if (err) { - WL_ERR("WLC_SET_INFRA error (%d)\n", err); - err = -EAGAIN; + if (ap) { + set_bit(WL_STATUS_AP_CREATING, &cfg_priv->status); + if (!cfg_priv->ap_info) + cfg_priv->ap_info = kzalloc(sizeof(*cfg_priv->ap_info), + GFP_KERNEL); + if (!cfg_priv->ap_info) { + err = -ENOMEM; + goto done; + } + WL_INFO("IF Type = AP\n"); } else { - wdev = ndev->ieee80211_ptr; - wdev->iftype = type; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &infra); + if (err) { + WL_ERR("WLC_SET_INFRA error (%d)\n", err); + err = -EAGAIN; + goto done; + } + WL_INFO("IF Type = %s\n", + (cfg_priv->conf->mode == WL_MODE_IBSS) ? + "Adhoc" : "Infra"); } - - WL_INFO("IF Type = %s\n", - (cfg_priv->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); + ndev->ieee80211_ptr->iftype = type; done: WL_TRACE("Exit\n"); @@ -2099,9 +2169,12 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); break; case WLAN_CIPHER_SUITE_TKIP: - memcpy(keybuf, &key.data[24], sizeof(keybuf)); - memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); - memcpy(&key.data[16], keybuf, sizeof(keybuf)); + if (cfg_priv->conf->mode != WL_MODE_AP) { + WL_CONN("Swapping key\n"); + memcpy(keybuf, &key.data[24], sizeof(keybuf)); + memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); + memcpy(&key.data[16], keybuf, sizeof(keybuf)); + } key.algo = CRYPTO_ALGO_TKIP; val = TKIP_ENABLED; WL_CONN("WLAN_CIPHER_SUITE_TKIP\n"); @@ -2251,7 +2324,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, - u8 *mac, struct station_info *sinfo) + u8 *mac, struct station_info *sinfo) { struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scb_val; @@ -2259,45 +2332,64 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, s32 rate; s32 err = 0; u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID); + struct brcmf_sta_info_le *sta_info_le; - WL_TRACE("Enter\n"); + WL_TRACE("Enter, MAC %pM\n", mac); if (!check_sys_up(wiphy)) return -EIO; - if (memcmp(mac, bssid, ETH_ALEN)) { - WL_ERR("Wrong Mac address cfg_mac-%X:%X:%X:%X:%X:%X" - "wl_bssid-%X:%X:%X:%X:%X:%X\n", - mac[0], mac[1], mac[2], mac[3], mac[4], mac[5], - bssid[0], bssid[1], bssid[2], bssid[3], - bssid[4], bssid[5]); - err = -ENOENT; - goto done; - } - - /* Report the current tx rate */ - err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); - if (err) { - WL_ERR("Could not get rate (%d)\n", err); - } else { - sinfo->filled |= STATION_INFO_TX_BITRATE; - sinfo->txrate.legacy = rate * 5; - WL_CONN("Rate %d Mbps\n", rate / 2); - } - - if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { - memset(&scb_val, 0, sizeof(scb_val)); - err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, - sizeof(struct brcmf_scb_val_le)); - if (err) { - WL_ERR("Could not get rssi (%d)\n", err); - } else { - rssi = le32_to_cpu(scb_val.val); - sinfo->filled |= STATION_INFO_SIGNAL; - sinfo->signal = rssi; - WL_CONN("RSSI %d dBm\n", rssi); + if (cfg_priv->conf->mode == WL_MODE_AP) { + err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN, + cfg_priv->dcmd_buf, + WL_DCMD_LEN_MAX); + if (err < 0) { + WL_ERR("GET STA INFO failed, %d\n", err); + goto done; } - } + sta_info_le = (struct brcmf_sta_info_le *)cfg_priv->dcmd_buf; + sinfo->filled = STATION_INFO_INACTIVE_TIME; + sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000; + if (le32_to_cpu(sta_info_le->flags) & BRCMF_STA_ASSOC) { + sinfo->filled |= STATION_INFO_CONNECTED_TIME; + sinfo->connected_time = le32_to_cpu(sta_info_le->in); + } + WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", + sinfo->inactive_time, sinfo->connected_time); + } else if (cfg_priv->conf->mode == WL_MODE_BSS) { + if (memcmp(mac, bssid, ETH_ALEN)) { + WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", + mac, bssid); + err = -ENOENT; + goto done; + } + /* Report the current tx rate */ + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_GET_RATE, &rate); + if (err) { + WL_ERR("Could not get rate (%d)\n", err); + goto done; + } else { + sinfo->filled |= STATION_INFO_TX_BITRATE; + sinfo->txrate.legacy = rate * 5; + WL_CONN("Rate %d Mbps\n", rate / 2); + } + + if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { + memset(&scb_val, 0, sizeof(scb_val)); + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, + sizeof(scb_val)); + if (err) { + WL_ERR("Could not get rssi (%d)\n", err); + goto done; + } else { + rssi = le32_to_cpu(scb_val.val); + sinfo->filled |= STATION_INFO_SIGNAL; + sinfo->signal = rssi; + WL_CONN("RSSI %d dBm\n", rssi); + } + } + } else + err = -EPERM; done: WL_TRACE("Exit\n"); return err; @@ -2603,6 +2695,45 @@ static struct brcmf_tlv *brcmf_parse_tlvs(void *buf, int buflen, uint key) return NULL; } +/* Is any of the tlvs the expected entry? If + * not update the tlvs buffer pointer/length. + */ +static bool +brcmf_tlv_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, + u8 *oui, u32 oui_len, u8 type) +{ + /* If the contents match the OUI and the type */ + if (ie[TLV_LEN_OFF] >= oui_len + 1 && + !memcmp(&ie[TLV_BODY_OFF], oui, oui_len) && + type == ie[TLV_BODY_OFF + oui_len]) { + return true; + } + + if (tlvs == NULL) + return false; + /* point to the next ie */ + ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN; + /* calculate the length of the rest of the buffer */ + *tlvs_len -= (int)(ie - *tlvs); + /* update the pointer to the start of the buffer */ + *tlvs = ie; + + return false; +} + +struct brcmf_vs_tlv * +brcmf_find_wpaie(u8 *parse, u32 len) +{ + struct brcmf_tlv *ie; + + while ((ie = brcmf_parse_tlvs(parse, len, WLAN_EID_WPA))) { + if (brcmf_tlv_has_ie((u8 *)ie, &parse, &len, + WPA_OUI, TLV_OUI_LEN, WPA_OUI_TYPE)) + return (struct brcmf_vs_tlv *)ie; + } + return NULL; +} + static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) { struct brcmf_bss_info_le *bi; @@ -3586,6 +3717,682 @@ static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) } #endif +static s32 brcmf_configure_opensecurity(struct net_device *ndev, s32 bssidx) +{ + s32 err; + + /* set auth */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", 0, bssidx); + if (err < 0) { + WL_ERR("auth error %d\n", err); + return err; + } + /* set wsec */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", 0, bssidx); + if (err < 0) { + WL_ERR("wsec error %d\n", err); + return err; + } + /* set upper-layer auth */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", + WPA_AUTH_NONE, bssidx); + if (err < 0) { + WL_ERR("wpa_auth error %d\n", err); + return err; + } + + return 0; +} + +static bool brcmf_valid_wpa_oui(u8 *oui, bool is_rsn_ie) +{ + if (is_rsn_ie) + return (memcmp(oui, RSN_OUI, TLV_OUI_LEN) == 0); + + return (memcmp(oui, WPA_OUI, TLV_OUI_LEN) == 0); +} + +static s32 +brcmf_configure_wpaie(struct net_device *ndev, struct brcmf_vs_tlv *wpa_ie, + bool is_rsn_ie, s32 bssidx) +{ + u32 auth = 0; /* d11 open authentication */ + u16 count; + s32 err = 0; + s32 len = 0; + u32 i; + u32 wsec; + u32 pval = 0; + u32 gval = 0; + u32 wpa_auth = 0; + u32 offset; + u8 *data; + u16 rsn_cap; + u32 wme_bss_disable; + + WL_TRACE("Enter\n"); + if (wpa_ie == NULL) + goto exit; + + len = wpa_ie->len + TLV_HDR_LEN; + data = (u8 *)wpa_ie; + offset = 0; + if (!is_rsn_ie) + offset += VS_IE_FIXED_HDR_LEN; + offset += WPA_IE_VERSION_LEN; + + /* check for multicast cipher suite */ + if (offset + WPA_IE_MIN_OUI_LEN > len) { + err = -EINVAL; + WL_ERR("no multicast cipher suite\n"); + goto exit; + } + + if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + err = -EINVAL; + WL_ERR("ivalid OUI\n"); + goto exit; + } + offset += TLV_OUI_LEN; + + /* pick up multicast cipher */ + switch (data[offset]) { + case WPA_CIPHER_NONE: + gval = 0; + break; + case WPA_CIPHER_WEP_40: + case WPA_CIPHER_WEP_104: + gval = WEP_ENABLED; + break; + case WPA_CIPHER_TKIP: + gval = TKIP_ENABLED; + break; + case WPA_CIPHER_AES_CCM: + gval = AES_ENABLED; + break; + default: + err = -EINVAL; + WL_ERR("Invalid multi cast cipher info\n"); + goto exit; + } + + offset++; + /* walk thru unicast cipher list and pick up what we recognize */ + count = data[offset] + (data[offset + 1] << 8); + offset += WPA_IE_SUITE_COUNT_LEN; + /* Check for unicast suite(s) */ + if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { + err = -EINVAL; + WL_ERR("no unicast cipher suite\n"); + goto exit; + } + for (i = 0; i < count; i++) { + if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + err = -EINVAL; + WL_ERR("ivalid OUI\n"); + goto exit; + } + offset += TLV_OUI_LEN; + switch (data[offset]) { + case WPA_CIPHER_NONE: + break; + case WPA_CIPHER_WEP_40: + case WPA_CIPHER_WEP_104: + pval |= WEP_ENABLED; + break; + case WPA_CIPHER_TKIP: + pval |= TKIP_ENABLED; + break; + case WPA_CIPHER_AES_CCM: + pval |= AES_ENABLED; + break; + default: + WL_ERR("Ivalid unicast security info\n"); + } + offset++; + } + /* walk thru auth management suite list and pick up what we recognize */ + count = data[offset] + (data[offset + 1] << 8); + offset += WPA_IE_SUITE_COUNT_LEN; + /* Check for auth key management suite(s) */ + if (offset + (WPA_IE_MIN_OUI_LEN * count) > len) { + err = -EINVAL; + WL_ERR("no auth key mgmt suite\n"); + goto exit; + } + for (i = 0; i < count; i++) { + if (!brcmf_valid_wpa_oui(&data[offset], is_rsn_ie)) { + err = -EINVAL; + WL_ERR("ivalid OUI\n"); + goto exit; + } + offset += TLV_OUI_LEN; + switch (data[offset]) { + case RSN_AKM_NONE: + WL_TRACE("RSN_AKM_NONE\n"); + wpa_auth |= WPA_AUTH_NONE; + break; + case RSN_AKM_UNSPECIFIED: + WL_TRACE("RSN_AKM_UNSPECIFIED\n"); + is_rsn_ie ? (wpa_auth |= WPA2_AUTH_UNSPECIFIED) : + (wpa_auth |= WPA_AUTH_UNSPECIFIED); + break; + case RSN_AKM_PSK: + WL_TRACE("RSN_AKM_PSK\n"); + is_rsn_ie ? (wpa_auth |= WPA2_AUTH_PSK) : + (wpa_auth |= WPA_AUTH_PSK); + break; + default: + WL_ERR("Ivalid key mgmt info\n"); + } + offset++; + } + + if (is_rsn_ie) { + wme_bss_disable = 1; + if ((offset + RSN_CAP_LEN) <= len) { + rsn_cap = data[offset] + (data[offset + 1] << 8); + if (rsn_cap & RSN_CAP_PTK_REPLAY_CNTR_MASK) + wme_bss_disable = 0; + } + /* set wme_bss_disable to sync RSN Capabilities */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "wme_bss_disable", + wme_bss_disable, bssidx); + if (err < 0) { + WL_ERR("wme_bss_disable error %d\n", err); + goto exit; + } + } + /* FOR WPS , set SES_OW_ENABLED */ + wsec = (pval | gval | SES_OW_ENABLED); + + /* set auth */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "auth", auth, bssidx); + if (err < 0) { + WL_ERR("auth error %d\n", err); + goto exit; + } + /* set wsec */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "wsec", wsec, bssidx); + if (err < 0) { + WL_ERR("wsec error %d\n", err); + goto exit; + } + /* set upper-layer auth */ + err = brcmf_dev_intvar_set_bsscfg(ndev, "wpa_auth", wpa_auth, bssidx); + if (err < 0) { + WL_ERR("wpa_auth error %d\n", err); + goto exit; + } + +exit: + return err; +} + +static s32 +brcmf_parse_vndr_ies(u8 *vndr_ie_buf, u32 vndr_ie_len, + struct parsed_vndr_ies *vndr_ies) +{ + s32 err = 0; + struct brcmf_vs_tlv *vndrie; + struct brcmf_tlv *ie; + struct parsed_vndr_ie_info *parsed_info; + s32 remaining_len; + + remaining_len = (s32)vndr_ie_len; + memset(vndr_ies, 0, sizeof(*vndr_ies)); + + ie = (struct brcmf_tlv *)vndr_ie_buf; + while (ie) { + if (ie->id != WLAN_EID_VENDOR_SPECIFIC) + goto next; + vndrie = (struct brcmf_vs_tlv *)ie; + /* len should be bigger than OUI length + one */ + if (vndrie->len < (VS_IE_FIXED_HDR_LEN - TLV_HDR_LEN + 1)) { + WL_ERR("invalid vndr ie. length is too small %d\n", + vndrie->len); + goto next; + } + /* if wpa or wme ie, do not add ie */ + if (!memcmp(vndrie->oui, (u8 *)WPA_OUI, TLV_OUI_LEN) && + ((vndrie->oui_type == WPA_OUI_TYPE) || + (vndrie->oui_type == WME_OUI_TYPE))) { + WL_TRACE("Found WPA/WME oui. Do not add it\n"); + goto next; + } + + parsed_info = &vndr_ies->ie_info[vndr_ies->count]; + + /* save vndr ie information */ + parsed_info->ie_ptr = (char *)vndrie; + parsed_info->ie_len = vndrie->len + TLV_HDR_LEN; + memcpy(&parsed_info->vndrie, vndrie, sizeof(*vndrie)); + + vndr_ies->count++; + + WL_TRACE("** OUI %02x %02x %02x, type 0x%02x\n", + parsed_info->vndrie.oui[0], + parsed_info->vndrie.oui[1], + parsed_info->vndrie.oui[2], + parsed_info->vndrie.oui_type); + + if (vndr_ies->count >= MAX_VNDR_IE_NUMBER) + break; +next: + remaining_len -= ie->len; + if (remaining_len <= 2) + ie = NULL; + else + ie = (struct brcmf_tlv *)(((u8 *)ie) + ie->len); + } + return err; +} + +static u32 +brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) +{ + + __le32 iecount_le; + __le32 pktflag_le; + + strncpy(iebuf, add_del_cmd, VNDR_IE_CMD_LEN - 1); + iebuf[VNDR_IE_CMD_LEN - 1] = '\0'; + + iecount_le = cpu_to_le32(1); + memcpy(&iebuf[VNDR_IE_COUNT_OFFSET], &iecount_le, sizeof(iecount_le)); + + pktflag_le = cpu_to_le32(pktflag); + memcpy(&iebuf[VNDR_IE_PKTFLAG_OFFSET], &pktflag_le, sizeof(pktflag_le)); + + memcpy(&iebuf[VNDR_IE_VSIE_OFFSET], ie_ptr, ie_len); + + return ie_len + VNDR_IE_HDR_SIZE; +} + +s32 +brcmf_set_management_ie(struct brcmf_cfg80211_priv *cfg_priv, + struct net_device *ndev, s32 bssidx, s32 pktflag, + u8 *vndr_ie_buf, u32 vndr_ie_len) +{ + s32 err = 0; + u8 *iovar_ie_buf; + u8 *curr_ie_buf; + u8 *mgmt_ie_buf = NULL; + u32 mgmt_ie_buf_len = 0; + u32 *mgmt_ie_len = 0; + u32 del_add_ie_buf_len = 0; + u32 total_ie_buf_len = 0; + u32 parsed_ie_buf_len = 0; + struct parsed_vndr_ies old_vndr_ies; + struct parsed_vndr_ies new_vndr_ies; + struct parsed_vndr_ie_info *vndrie_info; + s32 i; + u8 *ptr; + u32 remained_buf_len; + + WL_TRACE("bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag); + iovar_ie_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); + if (!iovar_ie_buf) + return -ENOMEM; + curr_ie_buf = iovar_ie_buf; + if (test_bit(WL_STATUS_AP_CREATING, &cfg_priv->status) || + test_bit(WL_STATUS_AP_CREATED, &cfg_priv->status)) { + switch (pktflag) { + case VNDR_IE_PRBRSP_FLAG: + mgmt_ie_buf = cfg_priv->ap_info->probe_res_ie; + mgmt_ie_len = &cfg_priv->ap_info->probe_res_ie_len; + mgmt_ie_buf_len = + sizeof(cfg_priv->ap_info->probe_res_ie); + break; + case VNDR_IE_BEACON_FLAG: + mgmt_ie_buf = cfg_priv->ap_info->beacon_ie; + mgmt_ie_len = &cfg_priv->ap_info->beacon_ie_len; + mgmt_ie_buf_len = sizeof(cfg_priv->ap_info->beacon_ie); + break; + default: + err = -EPERM; + WL_ERR("not suitable type\n"); + goto exit; + } + bssidx = 0; + } else { + err = -EPERM; + WL_ERR("not suitable type\n"); + goto exit; + } + + if (vndr_ie_len > mgmt_ie_buf_len) { + err = -ENOMEM; + WL_ERR("extra IE size too big\n"); + goto exit; + } + + /* parse and save new vndr_ie in curr_ie_buff before comparing it */ + if (vndr_ie_buf && vndr_ie_len && curr_ie_buf) { + ptr = curr_ie_buf; + brcmf_parse_vndr_ies(vndr_ie_buf, vndr_ie_len, &new_vndr_ies); + for (i = 0; i < new_vndr_ies.count; i++) { + vndrie_info = &new_vndr_ies.ie_info[i]; + memcpy(ptr + parsed_ie_buf_len, vndrie_info->ie_ptr, + vndrie_info->ie_len); + parsed_ie_buf_len += vndrie_info->ie_len; + } + } + + if (mgmt_ie_buf != NULL) { + if (parsed_ie_buf_len && (parsed_ie_buf_len == *mgmt_ie_len) && + (memcmp(mgmt_ie_buf, curr_ie_buf, + parsed_ie_buf_len) == 0)) { + WL_TRACE("Previous mgmt IE is equals to current IE"); + goto exit; + } + + /* parse old vndr_ie */ + brcmf_parse_vndr_ies(mgmt_ie_buf, *mgmt_ie_len, &old_vndr_ies); + + /* make a command to delete old ie */ + for (i = 0; i < old_vndr_ies.count; i++) { + vndrie_info = &old_vndr_ies.ie_info[i]; + + WL_TRACE("DEL ID : %d, Len: %d , OUI:%02x:%02x:%02x\n", + vndrie_info->vndrie.id, + vndrie_info->vndrie.len, + vndrie_info->vndrie.oui[0], + vndrie_info->vndrie.oui[1], + vndrie_info->vndrie.oui[2]); + + del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag, + vndrie_info->ie_ptr, + vndrie_info->ie_len, + "del"); + curr_ie_buf += del_add_ie_buf_len; + total_ie_buf_len += del_add_ie_buf_len; + } + } + + *mgmt_ie_len = 0; + /* Add if there is any extra IE */ + if (mgmt_ie_buf && parsed_ie_buf_len) { + ptr = mgmt_ie_buf; + + remained_buf_len = mgmt_ie_buf_len; + + /* make a command to add new ie */ + for (i = 0; i < new_vndr_ies.count; i++) { + vndrie_info = &new_vndr_ies.ie_info[i]; + + WL_TRACE("ADDED ID : %d, Len: %d, OUI:%02x:%02x:%02x\n", + vndrie_info->vndrie.id, + vndrie_info->vndrie.len, + vndrie_info->vndrie.oui[0], + vndrie_info->vndrie.oui[1], + vndrie_info->vndrie.oui[2]); + + del_add_ie_buf_len = brcmf_vndr_ie(curr_ie_buf, pktflag, + vndrie_info->ie_ptr, + vndrie_info->ie_len, + "add"); + /* verify remained buf size before copy data */ + remained_buf_len -= vndrie_info->ie_len; + if (remained_buf_len < 0) { + WL_ERR("no space in mgmt_ie_buf: len left %d", + remained_buf_len); + break; + } + + /* save the parsed IE in wl struct */ + memcpy(ptr + (*mgmt_ie_len), vndrie_info->ie_ptr, + vndrie_info->ie_len); + *mgmt_ie_len += vndrie_info->ie_len; + + curr_ie_buf += del_add_ie_buf_len; + total_ie_buf_len += del_add_ie_buf_len; + } + } + if (total_ie_buf_len) { + err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie", + iovar_ie_buf, + total_ie_buf_len, + cfg_priv->extra_buf, + WL_EXTRA_BUF_MAX, bssidx); + if (err) + WL_ERR("vndr ie set error : %d\n", err); + } + +exit: + kfree(iovar_ie_buf); + return err; +} + +static s32 +brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, + struct cfg80211_ap_settings *settings) +{ + s32 ie_offset; + struct brcmf_tlv *ssid_ie; + struct brcmf_ssid_le ssid_le; + s32 ioctl_value; + s32 err = -EPERM; + struct brcmf_tlv *rsn_ie; + struct brcmf_vs_tlv *wpa_ie; + struct brcmf_join_params join_params; + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + s32 bssidx = 0; + + WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", + settings->channel_type, settings->beacon_interval, + settings->dtim_period); + WL_TRACE("ssid=%s(%d), auth_type=%d, inactivity_timeout=%d\n", + settings->ssid, settings->ssid_len, settings->auth_type, + settings->inactivity_timeout); + + if (!test_bit(WL_STATUS_AP_CREATING, &cfg_priv->status)) { + WL_ERR("Not in AP creation mode\n"); + return -EPERM; + } + + memset(&ssid_le, 0, sizeof(ssid_le)); + if (settings->ssid == NULL || settings->ssid_len == 0) { + ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN; + ssid_ie = brcmf_parse_tlvs( + (u8 *)&settings->beacon.head[ie_offset], + settings->beacon.head_len - ie_offset, + WLAN_EID_SSID); + if (!ssid_ie) + return -EINVAL; + + memcpy(ssid_le.SSID, ssid_ie->data, ssid_ie->len); + ssid_le.SSID_len = cpu_to_le32(ssid_ie->len); + WL_TRACE("SSID is (%s) in Head\n", ssid_le.SSID); + } else { + memcpy(ssid_le.SSID, settings->ssid, settings->ssid_len); + ssid_le.SSID_len = cpu_to_le32((u32)settings->ssid_len); + } + + brcmf_set_mpc(ndev, 0); + ioctl_value = 1; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_DOWN, &ioctl_value); + if (err < 0) { + WL_ERR("BRCMF_C_DOWN error %d\n", err); + goto exit; + } + ioctl_value = 1; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_INFRA, &ioctl_value); + if (err < 0) { + WL_ERR("SET INFRA error %d\n", err); + goto exit; + } + ioctl_value = 1; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); + if (err < 0) { + WL_ERR("setting AP mode failed %d\n", err); + goto exit; + } + + /* find the RSN_IE */ + rsn_ie = brcmf_parse_tlvs((u8 *)settings->beacon.tail, + settings->beacon.tail_len, WLAN_EID_RSN); + + /* find the WPA_IE */ + wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail, + settings->beacon.tail_len); + + kfree(cfg_priv->ap_info->rsn_ie); + cfg_priv->ap_info->rsn_ie = NULL; + kfree(cfg_priv->ap_info->wpa_ie); + cfg_priv->ap_info->wpa_ie = NULL; + + if ((wpa_ie != NULL || rsn_ie != NULL)) { + WL_TRACE("WPA(2) IE is found\n"); + if (wpa_ie != NULL) { + /* WPA IE */ + err = brcmf_configure_wpaie(ndev, wpa_ie, false, + bssidx); + if (err < 0) + goto exit; + cfg_priv->ap_info->wpa_ie = kmemdup(wpa_ie, + wpa_ie->len + + TLV_HDR_LEN, + GFP_KERNEL); + } else { + /* RSN IE */ + err = brcmf_configure_wpaie(ndev, + (struct brcmf_vs_tlv *)rsn_ie, true, bssidx); + if (err < 0) + goto exit; + cfg_priv->ap_info->rsn_ie = kmemdup(rsn_ie, + rsn_ie->len + + TLV_HDR_LEN, + GFP_KERNEL); + } + cfg_priv->ap_info->security_mode = true; + } else { + WL_TRACE("No WPA(2) IEs found\n"); + brcmf_configure_opensecurity(ndev, bssidx); + cfg_priv->ap_info->security_mode = false; + } + /* Set Beacon IEs to FW */ + err = brcmf_set_management_ie(cfg_priv, ndev, bssidx, + VNDR_IE_BEACON_FLAG, + (u8 *)settings->beacon.tail, + settings->beacon.tail_len); + if (err) + WL_ERR("Set Beacon IE Failed\n"); + else + WL_TRACE("Applied Vndr IEs for Beacon\n"); + + /* Set Probe Response IEs to FW */ + err = brcmf_set_management_ie(cfg_priv, ndev, bssidx, + VNDR_IE_PRBRSP_FLAG, + (u8 *)settings->beacon.proberesp_ies, + settings->beacon.proberesp_ies_len); + if (err) + WL_ERR("Set Probe Resp IE Failed\n"); + else + WL_TRACE("Applied Vndr IEs for Probe Resp\n"); + + if (settings->beacon_interval) { + ioctl_value = settings->beacon_interval; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_BCNPRD, + &ioctl_value); + if (err < 0) { + WL_ERR("Beacon Interval Set Error, %d\n", err); + goto exit; + } + } + if (settings->dtim_period) { + ioctl_value = settings->dtim_period; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_DTIMPRD, + &ioctl_value); + if (err < 0) { + WL_ERR("DTIM Interval Set Error, %d\n", err); + goto exit; + } + } + ioctl_value = 1; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); + if (err < 0) { + WL_ERR("BRCMF_C_UP error (%d)\n", err); + goto exit; + } + + memset(&join_params, 0, sizeof(join_params)); + /* join parameters starts with ssid */ + memcpy(&join_params.ssid_le, &ssid_le, sizeof(ssid_le)); + /* create softap */ + err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params, + sizeof(join_params)); + if (err < 0) { + WL_ERR("SET SSID error (%d)\n", err); + goto exit; + } + clear_bit(WL_STATUS_AP_CREATING, &cfg_priv->status); + set_bit(WL_STATUS_AP_CREATED, &cfg_priv->status); + +exit: + if (err) + brcmf_set_mpc(ndev, 1); + return err; +} + +static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) +{ + struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + s32 ioctl_value; + s32 err = -EPERM; + + WL_TRACE("Enter\n"); + + if (cfg_priv->conf->mode == WL_MODE_AP) { + /* Due to most likely deauths outstanding we sleep */ + /* first to make sure they get processed by fw. */ + msleep(400); + ioctl_value = 0; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_AP, &ioctl_value); + if (err < 0) { + WL_ERR("setting AP mode failed %d\n", err); + goto exit; + } + ioctl_value = 0; + err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_UP, &ioctl_value); + if (err < 0) { + WL_ERR("BRCMF_C_UP error %d\n", err); + goto exit; + } + brcmf_set_mpc(ndev, 1); + clear_bit(WL_STATUS_AP_CREATING, &cfg_priv->status); + clear_bit(WL_STATUS_AP_CREATED, &cfg_priv->status); + } +exit: + return err; +} + +static int +brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, + u8 *mac) +{ + struct brcmf_scb_val_le scbval; + s32 err; + + if (!mac) + return -EFAULT; + + WL_TRACE("Enter %pM\n", mac); + + if (!check_sys_up(wiphy)) + return -EIO; + + memcpy(&scbval.ea, mac, ETH_ALEN); + scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); + err = brcmf_exec_dcmd(ndev, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, + &scbval, sizeof(scbval)); + if (err) + WL_ERR("SCB_DEAUTHENTICATE_FOR_REASON failed %d\n", err); + + WL_TRACE("Exit\n"); + return err; +} + static struct cfg80211_ops wl_cfg80211_ops = { .change_virtual_intf = brcmf_cfg80211_change_iface, .scan = brcmf_cfg80211_scan, @@ -3609,6 +4416,9 @@ static struct cfg80211_ops wl_cfg80211_ops = { .set_pmksa = brcmf_cfg80211_set_pmksa, .del_pmksa = brcmf_cfg80211_del_pmksa, .flush_pmksa = brcmf_cfg80211_flush_pmksa, + .start_ap = brcmf_cfg80211_start_ap, + .stop_ap = brcmf_cfg80211_stop_ap, + .del_station = brcmf_cfg80211_del_station, #ifndef CONFIG_BRCMISCAN /* scheduled scan need e-scan, which is mutual exclusive with i-scan */ .sched_scan_start = brcmf_cfg80211_sched_scan_start, @@ -3665,8 +4475,9 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) set_wiphy_dev(wdev->wiphy, ndev); wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX; wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; - wdev->wiphy->interface_modes = - BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC); + wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; /* Set * it as 11a by default. @@ -3914,6 +4725,45 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, return err; } +static s32 +brcmf_notify_connect_status_ap(struct brcmf_cfg80211_priv *cfg_priv, + struct net_device *ndev, + const struct brcmf_event_msg *e, void *data) +{ + s32 err = 0; + u32 event = be32_to_cpu(e->event_type); + u32 reason = be32_to_cpu(e->reason); + u32 len = be32_to_cpu(e->datalen); + static int generation; + + struct station_info sinfo; + + WL_CONN("event %d, reason %d\n", event, reason); + memset(&sinfo, 0, sizeof(sinfo)); + + sinfo.filled = 0; + if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) && + reason == BRCMF_E_STATUS_SUCCESS) { + sinfo.filled = STATION_INFO_ASSOC_REQ_IES; + if (!data) { + WL_ERR("No IEs present in ASSOC/REASSOC_IND"); + return -EINVAL; + } + sinfo.assoc_req_ies = data; + sinfo.assoc_req_ies_len = len; + generation++; + sinfo.generation = generation; + cfg80211_new_sta(ndev, e->addr, &sinfo, GFP_ATOMIC); + } else if ((event == BRCMF_E_DISASSOC_IND) || + (event == BRCMF_E_DEAUTH_IND) || + (event == BRCMF_E_DEAUTH)) { + generation++; + sinfo.generation = generation; + cfg80211_del_sta(ndev, e->addr, GFP_ATOMIC); + } + return err; +} + static s32 brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, @@ -3921,7 +4771,9 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, { s32 err = 0; - if (brcmf_is_linkup(cfg_priv, e)) { + if (cfg_priv->conf->mode == WL_MODE_AP) { + err = brcmf_notify_connect_status_ap(cfg_priv, ndev, e, data); + } else if (brcmf_is_linkup(cfg_priv, e)) { WL_CONN("Linkup\n"); if (brcmf_is_ibssmode(cfg_priv)) { brcmf_update_prof(cfg_priv, NULL, (void *)e->addr, @@ -4082,6 +4934,11 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) memset(el, 0, sizeof(*el)); el->handler[BRCMF_E_SCAN_COMPLETE] = brcmf_notify_scan_status; el->handler[BRCMF_E_LINK] = brcmf_notify_connect_status; + el->handler[BRCMF_E_DEAUTH_IND] = brcmf_notify_connect_status; + el->handler[BRCMF_E_DEAUTH] = brcmf_notify_connect_status; + el->handler[BRCMF_E_DISASSOC_IND] = brcmf_notify_connect_status; + el->handler[BRCMF_E_ASSOC_IND] = brcmf_notify_connect_status; + el->handler[BRCMF_E_REASSOC_IND] = brcmf_notify_connect_status; el->handler[BRCMF_E_ROAM] = brcmf_notify_roaming_status; el->handler[BRCMF_E_MIC_ERROR] = brcmf_notify_mic_status; el->handler[BRCMF_E_SET_SSID] = brcmf_notify_connect_status; @@ -4110,6 +4967,12 @@ static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) cfg_priv->iscan = NULL; kfree(cfg_priv->pmk_list); cfg_priv->pmk_list = NULL; + if (cfg_priv->ap_info) { + kfree(cfg_priv->ap_info->wpa_ie); + kfree(cfg_priv->ap_info->rsn_ie); + kfree(cfg_priv->ap_info); + cfg_priv->ap_info = NULL; + } } static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) @@ -4388,6 +5251,9 @@ static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) case NL80211_IFTYPE_STATION: infra = 1; break; + case NL80211_IFTYPE_AP: + infra = 1; + break; default: err = -EINVAL; WL_ERR("invalid type (%d)\n", iftype); diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 97f36d329456..374680072c16 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -125,6 +125,7 @@ do { \ #define WL_ESCAN_ACTION_ABORT 3 #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ +#define IE_MAX_LEN 512 /* dongle status */ enum wl_status { @@ -132,7 +133,9 @@ enum wl_status { WL_STATUS_SCANNING, WL_STATUS_SCAN_ABORTING, WL_STATUS_CONNECTING, - WL_STATUS_CONNECTED + WL_STATUS_CONNECTED, + WL_STATUS_AP_CREATING, + WL_STATUS_AP_CREATED }; /* wi-fi mode */ @@ -285,6 +288,17 @@ struct escan_info { struct net_device *ndev; }; +/* Structure to hold WPS, WPA IEs for a AP */ +struct ap_info { + u8 probe_res_ie[IE_MAX_LEN]; + u8 beacon_ie[IE_MAX_LEN]; + u32 probe_res_ie_len; + u32 beacon_ie_len; + u8 *wpa_ie; + u8 *rsn_ie; + bool security_mode; +}; + /** * struct brcmf_pno_param_le - PNO scan configuration parameters * @@ -407,6 +421,7 @@ struct brcmf_pno_scanresults_le { * @escan_timeout: Timer for catch scan timeout. * @escan_timeout_work: scan timeout worker. * @escan_ioctl_buf: dongle command buffer for escan commands. + * @ap_info: host ap information. * @ci: used to link this structure to netdev private data. */ struct brcmf_cfg80211_priv { @@ -448,6 +463,7 @@ struct brcmf_cfg80211_priv { struct timer_list escan_timeout; struct work_struct escan_timeout_work; u8 *escan_ioctl_buf; + struct ap_info *ap_info; }; static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) From 27a68fe391231b26e1143d67ac368053b1bf5a37 Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 27 Sep 2012 14:17:55 +0200 Subject: [PATCH 67/73] brcmfmac: rename structure brcmf_cfg80211_priv Renamed structure to brcmf_cfg80211_info as it is not really a private structure since it is exposed in header file. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- drivers/net/wireless/brcm80211/brcmfmac/dhd.h | 2 +- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 1183 ++++++++--------- .../wireless/brcm80211/brcmfmac/wl_cfg80211.h | 36 +- 3 files changed, 610 insertions(+), 611 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h index eed695a97323..17e7ae73e008 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h @@ -614,7 +614,7 @@ struct brcmf_pub { /* Linkage ponters */ struct brcmf_bus *bus_if; struct brcmf_proto *prot; - struct brcmf_cfg80211_priv *config; + struct brcmf_cfg80211_info *config; struct device *dev; /* fullmac dongle device pointer */ /* Internal brcmf items */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 0ecd0dfa6557..a0125d57c6c1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -97,10 +97,10 @@ static u32 brcmf_dbg_level = WL_DBG_ERR; static bool check_sys_up(struct wiphy *wiphy) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + if (!test_bit(WL_STATUS_READY, &cfg->status)) { WL_INFO("device is not ready : status (%d)\n", - (int)cfg_priv->status); + (int)cfg->status); return false; } return true; @@ -457,7 +457,7 @@ static void convert_key_from_CPU(struct brcmf_wsec_key *key, } static int -send_key_to_dongle(struct brcmf_cfg80211_priv *cfg_priv, s32 bssidx, +send_key_to_dongle(struct brcmf_cfg80211_info *cfg, s32 bssidx, struct net_device *ndev, struct brcmf_wsec_key *key) { int err; @@ -467,7 +467,7 @@ send_key_to_dongle(struct brcmf_cfg80211_priv *cfg_priv, s32 bssidx, err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, sizeof(key_le), - cfg_priv->extra_buf, + cfg->extra_buf, WL_EXTRA_BUF_MAX, bssidx); if (err) @@ -480,7 +480,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, enum nl80211_iftype type, u32 *flags, struct vif_params *params) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 infra = 0; s32 ap = 0; s32 err = 0; @@ -494,15 +494,15 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, type); return -EOPNOTSUPP; case NL80211_IFTYPE_ADHOC: - cfg_priv->conf->mode = WL_MODE_IBSS; + cfg->conf->mode = WL_MODE_IBSS; infra = 0; break; case NL80211_IFTYPE_STATION: - cfg_priv->conf->mode = WL_MODE_BSS; + cfg->conf->mode = WL_MODE_BSS; infra = 1; break; case NL80211_IFTYPE_AP: - cfg_priv->conf->mode = WL_MODE_AP; + cfg->conf->mode = WL_MODE_AP; ap = 1; break; default: @@ -511,11 +511,11 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, } if (ap) { - set_bit(WL_STATUS_AP_CREATING, &cfg_priv->status); - if (!cfg_priv->ap_info) - cfg_priv->ap_info = kzalloc(sizeof(*cfg_priv->ap_info), - GFP_KERNEL); - if (!cfg_priv->ap_info) { + set_bit(WL_STATUS_AP_CREATING, &cfg->status); + if (!cfg->ap_info) + cfg->ap_info = kzalloc(sizeof(*cfg->ap_info), + GFP_KERNEL); + if (!cfg->ap_info) { err = -ENOMEM; goto done; } @@ -528,7 +528,7 @@ brcmf_cfg80211_change_iface(struct wiphy *wiphy, struct net_device *ndev, goto done; } WL_INFO("IF Type = %s\n", - (cfg_priv->conf->mode == WL_MODE_IBSS) ? + (cfg->conf->mode == WL_MODE_IBSS) ? "Adhoc" : "Infra"); } ndev->ieee80211_ptr->iftype = type; @@ -620,7 +620,7 @@ brcmf_dev_intvar_get_bsscfg(struct net_device *ndev, s8 *name, s32 *val, * should return the ndev matching bssidx. */ static s32 -brcmf_find_bssidx(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev) +brcmf_find_bssidx(struct brcmf_cfg80211_info *cfg, struct net_device *ndev) { return 0; } @@ -628,9 +628,9 @@ brcmf_find_bssidx(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev) static void brcmf_set_mpc(struct net_device *ndev, int mpc) { s32 err = 0; - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - if (test_bit(WL_STATUS_READY, &cfg_priv->status)) { + if (test_bit(WL_STATUS_READY, &cfg->status)) { err = brcmf_dev_intvar_set(ndev, "mpc", mpc); if (err) { WL_ERR("fail to set mpc\n"); @@ -714,10 +714,10 @@ brcmf_run_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan, return err; } -static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_do_iscan(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); + struct net_device *ndev = cfg_to_ndev(cfg); struct brcmf_ssid ssid; __le32 passive_scan; s32 err = 0; @@ -727,19 +727,19 @@ static s32 brcmf_do_iscan(struct brcmf_cfg80211_priv *cfg_priv) iscan->state = WL_ISCAN_STATE_SCANING; - passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); - err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_SET_PASSIVE_SCAN, + passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); + err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { WL_ERR("error (%d)\n", err); return err; } brcmf_set_mpc(ndev, 0); - cfg_priv->iscan_kickstart = true; + cfg->iscan_kickstart = true; err = brcmf_run_iscan(iscan, &ssid, BRCMF_SCAN_ACTION_START); if (err) { brcmf_set_mpc(ndev, 1); - cfg_priv->iscan_kickstart = false; + cfg->iscan_kickstart = false; return err; } mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); @@ -752,27 +752,27 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct cfg80211_ssid *ssids; - struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; + struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; __le32 passive_scan; bool iscan_req; bool spec_scan; s32 err = 0; u32 SSID_len; - if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { - WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); + if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { + WL_ERR("Scanning already : status (%lu)\n", cfg->status); return -EAGAIN; } - if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { + if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { WL_ERR("Scanning being aborted : status (%lu)\n", - cfg_priv->status); + cfg->status); return -EAGAIN; } - if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { + if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { WL_ERR("Connecting : status (%lu)\n", - cfg_priv->status); + cfg->status); return -EAGAIN; } @@ -781,7 +781,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, if (request) { /* scan bss */ ssids = request->ssids; - if (cfg_priv->iscan_on && (!ssids || !ssids->ssid_len)) + if (cfg->iscan_on && (!ssids || !ssids->ssid_len)) iscan_req = true; } else { /* scan in ibss */ @@ -789,10 +789,10 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, ssids = this_ssid; } - cfg_priv->scan_request = request; - set_bit(WL_STATUS_SCANNING, &cfg_priv->status); + cfg->scan_request = request; + set_bit(WL_STATUS_SCANNING, &cfg->status); if (iscan_req) { - err = brcmf_do_iscan(cfg_priv); + err = brcmf_do_iscan(cfg); if (!err) return err; else @@ -811,7 +811,7 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, WL_SCAN("Broadcast scan\n"); } - passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); + passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { @@ -836,8 +836,8 @@ brcmf_cfg80211_iscan(struct wiphy *wiphy, struct net_device *ndev, return 0; scan_out: - clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); - cfg_priv->scan_request = NULL; + clear_bit(WL_STATUS_SCANNING, &cfg->status); + cfg->scan_request = NULL; return err; } @@ -942,7 +942,7 @@ static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le, } static s32 -brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, bool aborted, bool fw_abort) { @@ -954,11 +954,11 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, /* clear scan request, because the FW abort can cause a second call */ /* to this functon and might cause a double cfg80211_scan_done */ - scan_request = cfg_priv->scan_request; - cfg_priv->scan_request = NULL; + scan_request = cfg->scan_request; + cfg->scan_request = NULL; - if (timer_pending(&cfg_priv->escan_timeout)) - del_timer_sync(&cfg_priv->escan_timeout); + if (timer_pending(&cfg->escan_timeout)) + del_timer_sync(&cfg->escan_timeout); if (fw_abort) { /* Do a scan abort to stop the driver's scan engine */ @@ -984,11 +984,11 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, * e-scan can be initiated by scheduled scan * which takes precedence. */ - if (cfg_priv->sched_escan) { + if (cfg->sched_escan) { WL_SCAN("scheduled scan completed\n"); - cfg_priv->sched_escan = false; + cfg->sched_escan = false; if (!aborted) - cfg80211_sched_scan_results(cfg_to_wiphy(cfg_priv)); + cfg80211_sched_scan_results(cfg_to_wiphy(cfg)); brcmf_set_mpc(ndev, 1); } else if (scan_request) { WL_SCAN("ESCAN Completed scan: %s\n", @@ -996,7 +996,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, cfg80211_scan_done(scan_request, aborted); brcmf_set_mpc(ndev, 1); } - if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { WL_ERR("Scan complete while device not scanning\n"); return -EPERM; } @@ -1005,7 +1005,7 @@ brcmf_notify_escan_complete(struct brcmf_cfg80211_priv *cfg_priv, } static s32 -brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, +brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, struct cfg80211_scan_request *request, u16 action) { s32 params_size = BRCMF_SCAN_PARAMS_FIXED_SIZE + @@ -1035,7 +1035,7 @@ brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, params->sync_id = cpu_to_le16(0x1234); err = brcmf_dev_iovar_setbuf(ndev, "escan", params, params_size, - cfg_priv->escan_ioctl_buf, BRCMF_DCMD_MEDLEN); + cfg->escan_ioctl_buf, BRCMF_DCMD_MEDLEN); if (err) { if (err == -EBUSY) WL_INFO("system busy : escan canceled\n"); @@ -1049,7 +1049,7 @@ brcmf_run_escan(struct brcmf_cfg80211_priv *cfg_priv, struct net_device *ndev, } static s32 -brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy, +brcmf_do_escan(struct brcmf_cfg80211_info *cfg, struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request) { s32 err; @@ -1057,10 +1057,10 @@ brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy, struct brcmf_scan_results *results; WL_SCAN("Enter\n"); - cfg_priv->escan_info.ndev = ndev; - cfg_priv->escan_info.wiphy = wiphy; - cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; - passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); + cfg->escan_info.ndev = ndev; + cfg->escan_info.wiphy = wiphy; + cfg->escan_info.escan_state = WL_ESCAN_STATE_SCANNING; + passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { @@ -1068,12 +1068,12 @@ brcmf_do_escan(struct brcmf_cfg80211_priv *cfg_priv, struct wiphy *wiphy, return err; } brcmf_set_mpc(ndev, 0); - results = (struct brcmf_scan_results *)cfg_priv->escan_info.escan_buf; + results = (struct brcmf_scan_results *)cfg->escan_info.escan_buf; results->version = 0; results->count = 0; results->buflen = WL_ESCAN_RESULTS_FIXED_SIZE; - err = brcmf_run_escan(cfg_priv, ndev, request, WL_ESCAN_ACTION_START); + err = brcmf_run_escan(cfg, ndev, request, WL_ESCAN_ACTION_START); if (err) brcmf_set_mpc(ndev, 1); return err; @@ -1084,9 +1084,9 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_scan_request *request, struct cfg80211_ssid *this_ssid) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct cfg80211_ssid *ssids; - struct brcmf_cfg80211_scan_req *sr = cfg_priv->scan_req_int; + struct brcmf_cfg80211_scan_req *sr = cfg->scan_req_int; __le32 passive_scan; bool escan_req; bool spec_scan; @@ -1095,23 +1095,23 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, WL_SCAN("START ESCAN\n"); - if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { - WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); + if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { + WL_ERR("Scanning already : status (%lu)\n", cfg->status); return -EAGAIN; } - if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status)) { + if (test_bit(WL_STATUS_SCAN_ABORTING, &cfg->status)) { WL_ERR("Scanning being aborted : status (%lu)\n", - cfg_priv->status); + cfg->status); return -EAGAIN; } - if (test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { + if (test_bit(WL_STATUS_CONNECTING, &cfg->status)) { WL_ERR("Connecting : status (%lu)\n", - cfg_priv->status); + cfg->status); return -EAGAIN; } /* Arm scan timeout timer */ - mod_timer(&cfg_priv->escan_timeout, jiffies + + mod_timer(&cfg->escan_timeout, jiffies + WL_ESCAN_TIMER_INTERVAL_MS * HZ / 1000); escan_req = false; @@ -1125,10 +1125,10 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, ssids = this_ssid; } - cfg_priv->scan_request = request; - set_bit(WL_STATUS_SCANNING, &cfg_priv->status); + cfg->scan_request = request; + set_bit(WL_STATUS_SCANNING, &cfg->status); if (escan_req) { - err = brcmf_do_escan(cfg_priv, wiphy, ndev, request); + err = brcmf_do_escan(cfg, wiphy, ndev, request); if (!err) return err; else @@ -1147,7 +1147,7 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, } else WL_SCAN("Broadcast scan\n"); - passive_scan = cfg_priv->active_scan ? 0 : cpu_to_le32(1); + passive_scan = cfg->active_scan ? 0 : cpu_to_le32(1); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_PASSIVE_SCAN, &passive_scan, sizeof(passive_scan)); if (err) { @@ -1172,10 +1172,10 @@ brcmf_cfg80211_escan(struct wiphy *wiphy, struct net_device *ndev, return 0; scan_out: - clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); - if (timer_pending(&cfg_priv->escan_timeout)) - del_timer_sync(&cfg_priv->escan_timeout); - cfg_priv->scan_request = NULL; + clear_bit(WL_STATUS_SCANNING, &cfg->status); + if (timer_pending(&cfg->escan_timeout)) + del_timer_sync(&cfg->escan_timeout); + cfg->scan_request = NULL; return err; } @@ -1184,7 +1184,7 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request) { struct net_device *ndev = request->wdev->netdev; - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); s32 err = 0; WL_TRACE("Enter\n"); @@ -1192,9 +1192,9 @@ brcmf_cfg80211_scan(struct wiphy *wiphy, if (!check_sys_up(wiphy)) return -EIO; - if (cfg_priv->iscan_on) + if (cfg->iscan_on) err = brcmf_cfg80211_iscan(wiphy, ndev, request, NULL); - else if (cfg_priv->escan_on) + else if (cfg->escan_on) err = brcmf_cfg80211_escan(wiphy, ndev, request, NULL); if (err) @@ -1241,8 +1241,8 @@ static s32 brcmf_set_retry(struct net_device *ndev, u32 retry, bool l) static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg); s32 err = 0; WL_TRACE("Enter\n"); @@ -1250,30 +1250,30 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return -EIO; if (changed & WIPHY_PARAM_RTS_THRESHOLD && - (cfg_priv->conf->rts_threshold != wiphy->rts_threshold)) { - cfg_priv->conf->rts_threshold = wiphy->rts_threshold; - err = brcmf_set_rts(ndev, cfg_priv->conf->rts_threshold); + (cfg->conf->rts_threshold != wiphy->rts_threshold)) { + cfg->conf->rts_threshold = wiphy->rts_threshold; + err = brcmf_set_rts(ndev, cfg->conf->rts_threshold); if (!err) goto done; } if (changed & WIPHY_PARAM_FRAG_THRESHOLD && - (cfg_priv->conf->frag_threshold != wiphy->frag_threshold)) { - cfg_priv->conf->frag_threshold = wiphy->frag_threshold; - err = brcmf_set_frag(ndev, cfg_priv->conf->frag_threshold); + (cfg->conf->frag_threshold != wiphy->frag_threshold)) { + cfg->conf->frag_threshold = wiphy->frag_threshold; + err = brcmf_set_frag(ndev, cfg->conf->frag_threshold); if (!err) goto done; } if (changed & WIPHY_PARAM_RETRY_LONG - && (cfg_priv->conf->retry_long != wiphy->retry_long)) { - cfg_priv->conf->retry_long = wiphy->retry_long; - err = brcmf_set_retry(ndev, cfg_priv->conf->retry_long, true); + && (cfg->conf->retry_long != wiphy->retry_long)) { + cfg->conf->retry_long = wiphy->retry_long; + err = brcmf_set_retry(ndev, cfg->conf->retry_long, true); if (!err) goto done; } if (changed & WIPHY_PARAM_RETRY_SHORT - && (cfg_priv->conf->retry_short != wiphy->retry_short)) { - cfg_priv->conf->retry_short = wiphy->retry_short; - err = brcmf_set_retry(ndev, cfg_priv->conf->retry_short, false); + && (cfg->conf->retry_short != wiphy->retry_short)) { + cfg->conf->retry_short = wiphy->retry_short; + err = brcmf_set_retry(ndev, cfg->conf->retry_short, false); if (!err) goto done; } @@ -1283,22 +1283,22 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } -static void *brcmf_read_prof(struct brcmf_cfg80211_priv *cfg_priv, s32 item) +static void *brcmf_read_prof(struct brcmf_cfg80211_info *cfg, s32 item) { switch (item) { case WL_PROF_SEC: - return &cfg_priv->profile->sec; + return &cfg->profile->sec; case WL_PROF_BSSID: - return &cfg_priv->profile->bssid; + return &cfg->profile->bssid; case WL_PROF_SSID: - return &cfg_priv->profile->ssid; + return &cfg->profile->ssid; } WL_ERR("invalid item (%d)\n", item); return NULL; } static s32 -brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_update_prof(struct brcmf_cfg80211_info *cfg, const struct brcmf_event_msg *e, void *data, s32 item) { s32 err = 0; @@ -1307,27 +1307,27 @@ brcmf_update_prof(struct brcmf_cfg80211_priv *cfg_priv, switch (item) { case WL_PROF_SSID: ssid = (struct brcmf_ssid *) data; - memset(cfg_priv->profile->ssid.SSID, 0, - sizeof(cfg_priv->profile->ssid.SSID)); - memcpy(cfg_priv->profile->ssid.SSID, + memset(cfg->profile->ssid.SSID, 0, + sizeof(cfg->profile->ssid.SSID)); + memcpy(cfg->profile->ssid.SSID, ssid->SSID, ssid->SSID_len); - cfg_priv->profile->ssid.SSID_len = ssid->SSID_len; + cfg->profile->ssid.SSID_len = ssid->SSID_len; break; case WL_PROF_BSSID: if (data) - memcpy(cfg_priv->profile->bssid, data, ETH_ALEN); + memcpy(cfg->profile->bssid, data, ETH_ALEN); else - memset(cfg_priv->profile->bssid, 0, ETH_ALEN); + memset(cfg->profile->bssid, 0, ETH_ALEN); break; case WL_PROF_SEC: - memcpy(&cfg_priv->profile->sec, data, - sizeof(cfg_priv->profile->sec)); + memcpy(&cfg->profile->sec, data, + sizeof(cfg->profile->sec)); break; case WL_PROF_BEACONINT: - cfg_priv->profile->beacon_interval = *(u16 *)data; + cfg->profile->beacon_interval = *(u16 *)data; break; case WL_PROF_DTIMPERIOD: - cfg_priv->profile->dtim_period = *(u8 *)data; + cfg->profile->dtim_period = *(u8 *)data; break; default: WL_ERR("unsupported item (%d)\n", item); @@ -1370,20 +1370,20 @@ static void brcmf_ch_to_chanspec(int ch, struct brcmf_join_params *join_params, } } -static void brcmf_link_down(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_link_down(struct brcmf_cfg80211_info *cfg) { struct net_device *ndev = NULL; s32 err = 0; WL_TRACE("Enter\n"); - if (cfg_priv->link_up) { - ndev = cfg_to_ndev(cfg_priv); + if (cfg->link_up) { + ndev = cfg_to_ndev(cfg); WL_INFO("Call WLC_DISASSOC to stop excess roaming\n "); err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, NULL, 0); if (err) WL_ERR("WLC_DISASSOC failed (%d)\n", err); - cfg_priv->link_up = false; + cfg->link_up = false; } WL_TRACE("Exit\n"); } @@ -1392,7 +1392,7 @@ static s32 brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_join_params join_params; size_t join_params_size = 0; s32 err = 0; @@ -1411,7 +1411,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, return -EOPNOTSUPP; } - set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + set_bit(WL_STATUS_CONNECTING, &cfg->status); if (params->bssid) WL_CONN("BSSID: %pM\n", params->bssid); @@ -1479,7 +1479,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); join_params_size = sizeof(join_params.ssid_le); - brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); + brcmf_update_prof(cfg, NULL, &ssid, WL_PROF_SSID); /* BSSID */ if (params->bssid) { @@ -1490,24 +1490,24 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); } - brcmf_update_prof(cfg_priv, NULL, + brcmf_update_prof(cfg, NULL, &join_params.params_le.bssid, WL_PROF_BSSID); /* Channel */ if (params->channel) { u32 target_channel; - cfg_priv->channel = + cfg->channel = ieee80211_frequency_to_channel( params->channel->center_freq); if (params->channel_fixed) { /* adding chanspec */ - brcmf_ch_to_chanspec(cfg_priv->channel, + brcmf_ch_to_chanspec(cfg->channel, &join_params, &join_params_size); } /* set channel for starter */ - target_channel = cfg_priv->channel; + target_channel = cfg->channel; err = brcmf_exec_dcmd_u32(ndev, BRCM_SET_CHANNEL, &target_channel); if (err) { @@ -1515,9 +1515,9 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, goto done; } } else - cfg_priv->channel = 0; + cfg->channel = 0; - cfg_priv->ibss_starter = false; + cfg->ibss_starter = false; err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, @@ -1529,7 +1529,7 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, done: if (err) - clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + clear_bit(WL_STATUS_CONNECTING, &cfg->status); WL_TRACE("Exit\n"); return err; } @@ -1537,14 +1537,14 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, static s32 brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 err = 0; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) return -EIO; - brcmf_link_down(cfg_priv); + brcmf_link_down(cfg); WL_TRACE("Exit\n"); @@ -1554,7 +1554,7 @@ brcmf_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *ndev) static s32 brcmf_set_wpa_version(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1571,7 +1571,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, WL_ERR("set wpa_auth failed (%d)\n", err); return err; } - sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); + sec = brcmf_read_prof(cfg, WL_PROF_SEC); sec->wpa_versions = sme->crypto.wpa_versions; return err; } @@ -1579,7 +1579,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, static s32 brcmf_set_auth_type(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1610,7 +1610,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, WL_ERR("set auth failed (%d)\n", err); return err; } - sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); + sec = brcmf_read_prof(cfg, WL_PROF_SEC); sec->auth_type = sme->auth_type; return err; } @@ -1619,7 +1619,7 @@ static s32 brcmf_set_set_cipher(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 pval = 0; s32 gval = 0; @@ -1675,7 +1675,7 @@ brcmf_set_set_cipher(struct net_device *ndev, return err; } - sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); + sec = brcmf_read_prof(cfg, WL_PROF_SEC); sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; sec->cipher_group = sme->crypto.cipher_group; @@ -1685,7 +1685,7 @@ brcmf_set_set_cipher(struct net_device *ndev, static s32 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1731,7 +1731,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) return err; } } - sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); + sec = brcmf_read_prof(cfg, WL_PROF_SEC); sec->wpa_auth = sme->crypto.akm_suites[0]; return err; @@ -1741,7 +1741,7 @@ static s32 brcmf_set_sharedkey(struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); struct brcmf_cfg80211_security *sec; struct brcmf_wsec_key key; s32 val; @@ -1753,7 +1753,7 @@ brcmf_set_sharedkey(struct net_device *ndev, if (sme->key_len == 0) return 0; - sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); + sec = brcmf_read_prof(cfg, WL_PROF_SEC); WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, sec->cipher_pairwise); @@ -1789,8 +1789,8 @@ brcmf_set_sharedkey(struct net_device *ndev, WL_CONN("key length (%d) key index (%d) algo (%d)\n", key.len, key.index, key.algo); WL_CONN("key \"%s\"\n", key.data); - bssidx = brcmf_find_bssidx(cfg_priv, ndev); - err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); + bssidx = brcmf_find_bssidx(cfg, ndev); + err = send_key_to_dongle(cfg, bssidx, ndev, &key); if (err) return err; @@ -1808,7 +1808,7 @@ static s32 brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct ieee80211_channel *chan = sme->channel; struct brcmf_join_params join_params; size_t join_params_size; @@ -1825,15 +1825,15 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, return -EOPNOTSUPP; } - set_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + set_bit(WL_STATUS_CONNECTING, &cfg->status); if (chan) { - cfg_priv->channel = + cfg->channel = ieee80211_frequency_to_channel(chan->center_freq); WL_CONN("channel (%d), center_req (%d)\n", - cfg_priv->channel, chan->center_freq); + cfg->channel, chan->center_freq); } else - cfg_priv->channel = 0; + cfg->channel = 0; WL_INFO("ie (%p), ie_len (%zd)\n", sme->ie, sme->ie_len); @@ -1874,7 +1874,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); - brcmf_update_prof(cfg_priv, NULL, &ssid, WL_PROF_SSID); + brcmf_update_prof(cfg, NULL, &ssid, WL_PROF_SSID); memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); @@ -1882,7 +1882,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("ssid \"%s\", len (%d)\n", ssid.SSID, ssid.SSID_len); - brcmf_ch_to_chanspec(cfg_priv->channel, + brcmf_ch_to_chanspec(cfg->channel, &join_params, &join_params_size); err = brcmf_exec_dcmd(ndev, BRCMF_C_SET_SSID, &join_params, join_params_size); @@ -1891,7 +1891,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, done: if (err) - clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + clear_bit(WL_STATUS_CONNECTING, &cfg->status); WL_TRACE("Exit\n"); return err; } @@ -1900,7 +1900,7 @@ static s32 brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scbval; s32 err = 0; @@ -1908,16 +1908,16 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, if (!check_sys_up(wiphy)) return -EIO; - clear_bit(WL_STATUS_CONNECTED, &cfg_priv->status); + clear_bit(WL_STATUS_CONNECTED, &cfg->status); - memcpy(&scbval.ea, brcmf_read_prof(cfg_priv, WL_PROF_BSSID), ETH_ALEN); + memcpy(&scbval.ea, brcmf_read_prof(cfg, WL_PROF_BSSID), ETH_ALEN); scbval.val = cpu_to_le32(reason_code); err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, sizeof(struct brcmf_scb_val_le)); if (err) WL_ERR("error (%d)\n", err); - cfg_priv->link_up = false; + cfg->link_up = false; WL_TRACE("Exit\n"); return err; @@ -1928,8 +1928,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type, s32 mbm) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg); u16 txpwrmw; s32 err = 0; s32 disable = 0; @@ -1965,7 +1965,7 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, (s32) (brcmf_mw_to_qdbm(txpwrmw))); if (err) WL_ERR("qtxpower error (%d)\n", err); - cfg_priv->conf->tx_power = dbm; + cfg->conf->tx_power = dbm; done: WL_TRACE("Exit\n"); @@ -1974,8 +1974,8 @@ brcmf_cfg80211_set_tx_power(struct wiphy *wiphy, static s32 brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg); s32 txpwrdbm; u8 result; s32 err = 0; @@ -2002,7 +2002,7 @@ static s32 brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool unicast, bool multicast) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); u32 index; u32 wsec; s32 err = 0; @@ -2013,7 +2013,7 @@ brcmf_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *ndev, if (!check_sys_up(wiphy)) return -EIO; - bssidx = brcmf_find_bssidx(cfg_priv, ndev); + bssidx = brcmf_find_bssidx(cfg, ndev); err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); if (err) { WL_ERR("WLC_GET_WSEC error (%d)\n", err); @@ -2037,7 +2037,7 @@ static s32 brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, const u8 *mac_addr, struct key_params *params) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; struct brcmf_wsec_key_le key_le; s32 err = 0; @@ -2050,11 +2050,11 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, if (!is_multicast_ether_addr(mac_addr)) memcpy((char *)&key.ea, (void *)mac_addr, ETH_ALEN); key.len = (u32) params->key_len; - bssidx = brcmf_find_bssidx(cfg_priv, ndev); + bssidx = brcmf_find_bssidx(cfg, ndev); /* check for key index change */ if (key.len == 0) { /* key delete */ - err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); + err = send_key_to_dongle(cfg, bssidx, ndev, &key); if (err) WL_ERR("key delete error (%d)\n", err); } else { @@ -2114,7 +2114,7 @@ brcmf_add_keyext(struct wiphy *wiphy, struct net_device *ndev, brcmf_netdev_wait_pend8021x(ndev); err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "wsec_key", &key_le, sizeof(key_le), - cfg_priv->extra_buf, + cfg->extra_buf, WL_EXTRA_BUF_MAX, bssidx); if (err) WL_ERR("wsec_key error (%d)\n", err); @@ -2127,7 +2127,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr, struct key_params *params) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; s32 val; s32 wsec; @@ -2169,7 +2169,7 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("WLAN_CIPHER_SUITE_WEP104\n"); break; case WLAN_CIPHER_SUITE_TKIP: - if (cfg_priv->conf->mode != WL_MODE_AP) { + if (cfg->conf->mode != WL_MODE_AP) { WL_CONN("Swapping key\n"); memcpy(keybuf, &key.data[24], sizeof(keybuf)); memcpy(&key.data[24], &key.data[16], sizeof(keybuf)); @@ -2195,8 +2195,8 @@ brcmf_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev, goto done; } - bssidx = brcmf_find_bssidx(cfg_priv, ndev); - err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); + bssidx = brcmf_find_bssidx(cfg, ndev); + err = send_key_to_dongle(cfg, bssidx, ndev, &key); if (err) goto done; @@ -2221,7 +2221,7 @@ static s32 brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, u8 key_idx, bool pairwise, const u8 *mac_addr) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_wsec_key key; s32 err = 0; s32 bssidx; @@ -2239,8 +2239,8 @@ brcmf_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("key index (%d)\n", key_idx); /* Set the new key/index */ - bssidx = brcmf_find_bssidx(cfg_priv, ndev); - err = send_key_to_dongle(cfg_priv, bssidx, ndev, &key); + bssidx = brcmf_find_bssidx(cfg, ndev); + err = send_key_to_dongle(cfg, bssidx, ndev, &key); if (err) { if (err == -EINVAL) { if (key.index >= DOT11_MAX_DEFAULT_KEYS) @@ -2261,7 +2261,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, void (*callback) (void *cookie, struct key_params * params)) { struct key_params params; - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_cfg80211_security *sec; s32 wsec; s32 err = 0; @@ -2274,7 +2274,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, memset(¶ms, 0, sizeof(params)); - bssidx = brcmf_find_bssidx(cfg_priv, ndev); + bssidx = brcmf_find_bssidx(cfg, ndev); err = brcmf_dev_intvar_get_bsscfg(ndev, "wsec", &wsec, bssidx); if (err) { WL_ERR("WLC_GET_WSEC error (%d)\n", err); @@ -2284,7 +2284,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, } switch (wsec & ~SES_OW_ENABLED) { case WEP_ENABLED: - sec = brcmf_read_prof(cfg_priv, WL_PROF_SEC); + sec = brcmf_read_prof(cfg, WL_PROF_SEC); if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { params.cipher = WLAN_CIPHER_SUITE_WEP40; WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); @@ -2326,27 +2326,27 @@ static s32 brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_scb_val_le scb_val; int rssi; s32 rate; s32 err = 0; - u8 *bssid = brcmf_read_prof(cfg_priv, WL_PROF_BSSID); + u8 *bssid = brcmf_read_prof(cfg, WL_PROF_BSSID); struct brcmf_sta_info_le *sta_info_le; WL_TRACE("Enter, MAC %pM\n", mac); if (!check_sys_up(wiphy)) return -EIO; - if (cfg_priv->conf->mode == WL_MODE_AP) { + if (cfg->conf->mode == WL_MODE_AP) { err = brcmf_dev_iovar_getbuf(ndev, "sta_info", mac, ETH_ALEN, - cfg_priv->dcmd_buf, + cfg->dcmd_buf, WL_DCMD_LEN_MAX); if (err < 0) { WL_ERR("GET STA INFO failed, %d\n", err); goto done; } - sta_info_le = (struct brcmf_sta_info_le *)cfg_priv->dcmd_buf; + sta_info_le = (struct brcmf_sta_info_le *)cfg->dcmd_buf; sinfo->filled = STATION_INFO_INACTIVE_TIME; sinfo->inactive_time = le32_to_cpu(sta_info_le->idle) * 1000; @@ -2356,7 +2356,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, } WL_TRACE("STA idle time : %d ms, connected time :%d sec\n", sinfo->inactive_time, sinfo->connected_time); - } else if (cfg_priv->conf->mode == WL_MODE_BSS) { + } else if (cfg->conf->mode == WL_MODE_BSS) { if (memcmp(mac, bssid, ETH_ALEN)) { WL_ERR("Wrong Mac address cfg_mac-%pM wl_bssid-%pM\n", mac, bssid); @@ -2374,7 +2374,7 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, WL_CONN("Rate %d Mbps\n", rate / 2); } - if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) { + if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) { memset(&scb_val, 0, sizeof(scb_val)); err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val, sizeof(scb_val)); @@ -2401,7 +2401,7 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, { s32 pm; s32 err = 0; - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); WL_TRACE("Enter\n"); @@ -2409,14 +2409,13 @@ brcmf_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *ndev, * Powersave enable/disable request is coming from the * cfg80211 even before the interface is up. In that * scenario, driver will be storing the power save - * preference in cfg_priv struct to apply this to + * preference in cfg struct to apply this to * FW later while initializing the dongle */ - cfg_priv->pwr_save = enabled; - if (!test_bit(WL_STATUS_READY, &cfg_priv->status)) { + cfg->pwr_save = enabled; + if (!test_bit(WL_STATUS_READY, &cfg->status)) { - WL_INFO("Device is not ready," - "storing the value in cfg_priv struct\n"); + WL_INFO("Device is not ready, storing the value in cfg_info struct\n"); goto done; } @@ -2494,10 +2493,10 @@ brcmf_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *ndev, return err; } -static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_priv *cfg_priv, +static s32 brcmf_inform_single_bss(struct brcmf_cfg80211_info *cfg, struct brcmf_bss_info_le *bi) { - struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct ieee80211_channel *notify_channel; struct cfg80211_bss *bss; struct ieee80211_supported_band *band; @@ -2561,14 +2560,14 @@ next_bss_le(struct brcmf_scan_results *list, struct brcmf_bss_info_le *bss) le32_to_cpu(bss->length)); } -static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_inform_bss(struct brcmf_cfg80211_info *cfg) { struct brcmf_scan_results *bss_list; struct brcmf_bss_info_le *bi = NULL; /* must be initialized */ s32 err = 0; int i; - bss_list = cfg_priv->bss_list; + bss_list = cfg->bss_list; if (bss_list->version != BRCMF_BSS_INFO_VERSION) { WL_ERR("Version %d != WL_BSS_INFO_VERSION\n", bss_list->version); @@ -2577,17 +2576,17 @@ static s32 brcmf_inform_bss(struct brcmf_cfg80211_priv *cfg_priv) WL_SCAN("scanned AP count (%d)\n", bss_list->count); for (i = 0; i < bss_list->count && i < WL_AP_MAX; i++) { bi = next_bss_le(bss_list, bi); - err = brcmf_inform_single_bss(cfg_priv, bi); + err = brcmf_inform_single_bss(cfg, bi); if (err) break; } return err; } -static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, +static s32 wl_inform_ibss(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const u8 *bssid) { - struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct ieee80211_channel *notify_channel; struct brcmf_bss_info_le *bi = NULL; struct ieee80211_supported_band *band; @@ -2662,9 +2661,9 @@ static s32 wl_inform_ibss(struct brcmf_cfg80211_priv *cfg_priv, return err; } -static bool brcmf_is_ibssmode(struct brcmf_cfg80211_priv *cfg_priv) +static bool brcmf_is_ibssmode(struct brcmf_cfg80211_info *cfg) { - return cfg_priv->conf->mode == WL_MODE_IBSS; + return cfg->conf->mode == WL_MODE_IBSS; } /* @@ -2734,7 +2733,7 @@ brcmf_find_wpaie(u8 *parse, u32 len) return NULL; } -static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) { struct brcmf_bss_info_le *bi; struct brcmf_ssid *ssid; @@ -2746,21 +2745,21 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) s32 err = 0; WL_TRACE("Enter\n"); - if (brcmf_is_ibssmode(cfg_priv)) + if (brcmf_is_ibssmode(cfg)) return err; - ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg_priv, WL_PROF_SSID); + ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg, WL_PROF_SSID); - *(__le32 *)cfg_priv->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); - err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCMF_C_GET_BSS_INFO, - cfg_priv->extra_buf, WL_EXTRA_BUF_MAX); + *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); + err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO, + cfg->extra_buf, WL_EXTRA_BUF_MAX); if (err) { WL_ERR("Could not get bss info %d\n", err); goto update_bss_info_out; } - bi = (struct brcmf_bss_info_le *)(cfg_priv->extra_buf + 4); - err = brcmf_inform_single_bss(cfg_priv, bi); + bi = (struct brcmf_bss_info_le *)(cfg->extra_buf + 4); + err = brcmf_inform_single_bss(cfg, bi); if (err) goto update_bss_info_out; @@ -2778,7 +2777,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) * so we speficially query dtim information to dongle. */ u32 var; - err = brcmf_dev_intvar_get(cfg_to_ndev(cfg_priv), + err = brcmf_dev_intvar_get(cfg_to_ndev(cfg), "dtim_assoc", &var); if (err) { WL_ERR("wl dtim_assoc failed (%d)\n", err); @@ -2787,22 +2786,22 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_priv *cfg_priv) dtim_period = (u8)var; } - brcmf_update_prof(cfg_priv, NULL, &beacon_interval, WL_PROF_BEACONINT); - brcmf_update_prof(cfg_priv, NULL, &dtim_period, WL_PROF_DTIMPERIOD); + brcmf_update_prof(cfg, NULL, &beacon_interval, WL_PROF_BEACONINT); + brcmf_update_prof(cfg, NULL, &dtim_period, WL_PROF_DTIMPERIOD); update_bss_info_out: WL_TRACE("Exit"); return err; } -static void brcmf_abort_scanning(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); - struct escan_info *escan = &cfg_priv->escan_info; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); + struct escan_info *escan = &cfg->escan_info; struct brcmf_ssid ssid; - set_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); - if (cfg_priv->iscan_on) { + set_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); + if (cfg->iscan_on) { iscan->state = WL_ISCAN_STATE_IDLE; if (iscan->timer_on) { @@ -2816,39 +2815,39 @@ static void brcmf_abort_scanning(struct brcmf_cfg80211_priv *cfg_priv) memset(&ssid, 0, sizeof(ssid)); brcmf_run_iscan(iscan, &ssid, WL_SCAN_ACTION_ABORT); - if (cfg_priv->scan_request) { + if (cfg->scan_request) { /* Indidate scan abort to cfg80211 layer */ WL_INFO("Terminating scan in progress\n"); - cfg80211_scan_done(cfg_priv->scan_request, true); - cfg_priv->scan_request = NULL; + cfg80211_scan_done(cfg->scan_request, true); + cfg->scan_request = NULL; } } - if (cfg_priv->escan_on && cfg_priv->scan_request) { + if (cfg->escan_on && cfg->scan_request) { escan->escan_state = WL_ESCAN_STATE_IDLE; - brcmf_notify_escan_complete(cfg_priv, escan->ndev, true, true); + brcmf_notify_escan_complete(cfg, escan->ndev, true, true); } - clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); - clear_bit(WL_STATUS_SCAN_ABORTING, &cfg_priv->status); + clear_bit(WL_STATUS_SCANNING, &cfg->status); + clear_bit(WL_STATUS_SCAN_ABORTING, &cfg->status); } static void brcmf_notify_iscan_complete(struct brcmf_cfg80211_iscan_ctrl *iscan, bool aborted) { - struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); + struct net_device *ndev = cfg_to_ndev(cfg); - if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { WL_ERR("Scan complete while device not scanning\n"); return; } - if (cfg_priv->scan_request) { + if (cfg->scan_request) { WL_SCAN("ISCAN Completed scan: %s\n", aborted ? "Aborted" : "Done"); - cfg80211_scan_done(cfg_priv->scan_request, aborted); + cfg80211_scan_done(cfg->scan_request, aborted); brcmf_set_mpc(ndev, 1); - cfg_priv->scan_request = NULL; + cfg->scan_request = NULL; } - cfg_priv->iscan_kickstart = false; + cfg->iscan_kickstart = false; } static s32 brcmf_wakeup_iscan(struct brcmf_cfg80211_iscan_ctrl *iscan) @@ -2901,21 +2900,21 @@ brcmf_get_iscan_results(struct brcmf_cfg80211_iscan_ctrl *iscan, u32 *status, return err; } -static s32 brcmf_iscan_done(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_iscan_done(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; s32 err = 0; iscan->state = WL_ISCAN_STATE_IDLE; - brcmf_inform_bss(cfg_priv); + brcmf_inform_bss(cfg); brcmf_notify_iscan_complete(iscan, false); return err; } -static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_iscan_pending(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; s32 err = 0; /* Reschedule the timer */ @@ -2925,12 +2924,12 @@ static s32 brcmf_iscan_pending(struct brcmf_cfg80211_priv *cfg_priv) return err; } -static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; s32 err = 0; - brcmf_inform_bss(cfg_priv); + brcmf_inform_bss(cfg); brcmf_run_iscan(iscan, NULL, BRCMF_SCAN_ACTION_CONTINUE); /* Reschedule the timer */ mod_timer(&iscan->timer, jiffies + iscan->timer_ms * HZ / 1000); @@ -2939,9 +2938,9 @@ static s32 brcmf_iscan_inprogress(struct brcmf_cfg80211_priv *cfg_priv) return err; } -static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_iscan_aborted(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_priv->iscan; + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg->iscan; s32 err = 0; iscan->state = WL_ISCAN_STATE_IDLE; @@ -2955,7 +2954,7 @@ static void brcmf_cfg80211_iscan_handler(struct work_struct *work) struct brcmf_cfg80211_iscan_ctrl *iscan = container_of(work, struct brcmf_cfg80211_iscan_ctrl, work); - struct brcmf_cfg80211_priv *cfg_priv = iscan_to_cfg(iscan); + struct brcmf_cfg80211_info *cfg = iscan_to_cfg(iscan); struct brcmf_cfg80211_iscan_eloop *el = &iscan->el; u32 status = BRCMF_SCAN_RESULTS_PARTIAL; @@ -2964,12 +2963,12 @@ static void brcmf_cfg80211_iscan_handler(struct work_struct *work) iscan->timer_on = 0; } - if (brcmf_get_iscan_results(iscan, &status, &cfg_priv->bss_list)) { + if (brcmf_get_iscan_results(iscan, &status, &cfg->bss_list)) { status = BRCMF_SCAN_RESULTS_ABORTED; WL_ERR("Abort iscan\n"); } - el->handler[status](cfg_priv); + el->handler[status](cfg); } static void brcmf_iscan_timer(unsigned long data) @@ -2984,11 +2983,11 @@ static void brcmf_iscan_timer(unsigned long data) } } -static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_invoke_iscan(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); - if (cfg_priv->iscan_on) { + if (cfg->iscan_on) { iscan->state = WL_ISCAN_STATE_IDLE; INIT_WORK(&iscan->work, brcmf_cfg80211_iscan_handler); } @@ -3006,21 +3005,21 @@ static void brcmf_init_iscan_eloop(struct brcmf_cfg80211_iscan_eloop *el) el->handler[BRCMF_SCAN_RESULTS_NO_MEM] = brcmf_iscan_aborted; } -static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_init_iscan(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg_priv); + struct brcmf_cfg80211_iscan_ctrl *iscan = cfg_to_iscan(cfg); int err = 0; - if (cfg_priv->iscan_on) { - iscan->ndev = cfg_to_ndev(cfg_priv); + if (cfg->iscan_on) { + iscan->ndev = cfg_to_ndev(cfg); brcmf_init_iscan_eloop(&iscan->el); iscan->timer_ms = WL_ISCAN_TIMER_INTERVAL_MS; init_timer(&iscan->timer); iscan->timer.data = (unsigned long) iscan; iscan->timer.function = brcmf_iscan_timer; - err = brcmf_invoke_iscan(cfg_priv); + err = brcmf_invoke_iscan(cfg); if (!err) - iscan->data = cfg_priv; + iscan->data = cfg; } return err; @@ -3028,23 +3027,23 @@ static s32 brcmf_init_iscan(struct brcmf_cfg80211_priv *cfg_priv) static void brcmf_cfg80211_escan_timeout_worker(struct work_struct *work) { - struct brcmf_cfg80211_priv *cfg_priv = - container_of(work, struct brcmf_cfg80211_priv, + struct brcmf_cfg80211_info *cfg = + container_of(work, struct brcmf_cfg80211_info, escan_timeout_work); - brcmf_notify_escan_complete(cfg_priv, - cfg_priv->escan_info.ndev, true, true); + brcmf_notify_escan_complete(cfg, + cfg->escan_info.ndev, true, true); } static void brcmf_escan_timeout(unsigned long data) { - struct brcmf_cfg80211_priv *cfg_priv = - (struct brcmf_cfg80211_priv *)data; + struct brcmf_cfg80211_info *cfg = + (struct brcmf_cfg80211_info *)data; - if (cfg_priv->scan_request) { + if (cfg->scan_request) { WL_ERR("timer expired\n"); - if (cfg_priv->escan_on) - schedule_work(&cfg_priv->escan_timeout_work); + if (cfg->escan_on) + schedule_work(&cfg->escan_timeout_work); } } @@ -3081,7 +3080,7 @@ brcmf_compare_update_same_bss(struct brcmf_bss_info_le *bss, } static s32 -brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -3097,11 +3096,11 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, status = be32_to_cpu(e->status); - if (!ndev || !cfg_priv->escan_on || - !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + if (!ndev || !cfg->escan_on || + !test_bit(WL_STATUS_SCANNING, &cfg->status)) { WL_ERR("scan not ready ndev %p wl->escan_on %d drv_status %x\n", - ndev, cfg_priv->escan_on, - !test_bit(WL_STATUS_SCANNING, &cfg_priv->status)); + ndev, cfg->escan_on, + !test_bit(WL_STATUS_SCANNING, &cfg->status)); return -EPERM; } @@ -3112,7 +3111,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, WL_ERR("Invalid escan result (NULL pointer)\n"); goto exit; } - if (!cfg_priv->scan_request) { + if (!cfg->scan_request) { WL_SCAN("result without cfg80211 request\n"); goto exit; } @@ -3132,7 +3131,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, goto exit; } - if (!(cfg_to_wiphy(cfg_priv)->interface_modes & + if (!(cfg_to_wiphy(cfg)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { if (le16_to_cpu(bss_info_le->capability) & WLAN_CAPABILITY_IBSS) { @@ -3142,7 +3141,7 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, } list = (struct brcmf_scan_results *) - cfg_priv->escan_info.escan_buf; + cfg->escan_info.escan_buf; if (bi_length > WL_ESCAN_BUF_SIZE - list->buflen) { WL_ERR("Buffer is too small: ignoring\n"); goto exit; @@ -3155,19 +3154,19 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, if (brcmf_compare_update_same_bss(bss, bss_info_le)) goto exit; } - memcpy(&(cfg_priv->escan_info.escan_buf[list->buflen]), + memcpy(&(cfg->escan_info.escan_buf[list->buflen]), bss_info_le, bi_length); list->version = le32_to_cpu(bss_info_le->version); list->buflen += bi_length; list->count++; } else { - cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE; - if (cfg_priv->scan_request) { - cfg_priv->bss_list = (struct brcmf_scan_results *) - cfg_priv->escan_info.escan_buf; - brcmf_inform_bss(cfg_priv); + cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; + if (cfg->scan_request) { + cfg->bss_list = (struct brcmf_scan_results *) + cfg->escan_info.escan_buf; + brcmf_inform_bss(cfg); aborted = status != BRCMF_E_STATUS_SUCCESS; - brcmf_notify_escan_complete(cfg_priv, ndev, aborted, + brcmf_notify_escan_complete(cfg, ndev, aborted, false); } else WL_ERR("Unexpected scan result 0x%x\n", status); @@ -3176,18 +3175,18 @@ brcmf_cfg80211_escan_handler(struct brcmf_cfg80211_priv *cfg_priv, return err; } -static void brcmf_init_escan(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_init_escan(struct brcmf_cfg80211_info *cfg) { - if (cfg_priv->escan_on) { - cfg_priv->el.handler[BRCMF_E_ESCAN_RESULT] = + if (cfg->escan_on) { + cfg->el.handler[BRCMF_E_ESCAN_RESULT] = brcmf_cfg80211_escan_handler; - cfg_priv->escan_info.escan_state = WL_ESCAN_STATE_IDLE; + cfg->escan_info.escan_state = WL_ESCAN_STATE_IDLE; /* Init scan_timeout timer */ - init_timer(&cfg_priv->escan_timeout); - cfg_priv->escan_timeout.data = (unsigned long) cfg_priv; - cfg_priv->escan_timeout.function = brcmf_escan_timeout; - INIT_WORK(&cfg_priv->escan_timeout_work, + init_timer(&cfg->escan_timeout); + cfg->escan_timeout.data = (unsigned long) cfg; + cfg->escan_timeout.function = brcmf_escan_timeout; + INIT_WORK(&cfg->escan_timeout_work, brcmf_cfg80211_escan_timeout_worker); } } @@ -3204,7 +3203,7 @@ static __always_inline void brcmf_delay(u32 ms) static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); /* * Check for WL_STATUS_READY before any function call which @@ -3213,7 +3212,7 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) */ WL_TRACE("Enter\n"); - if (test_bit(WL_STATUS_READY, &cfg_priv->status)) + if (test_bit(WL_STATUS_READY, &cfg->status)) brcmf_invoke_iscan(wiphy_to_cfg(wiphy)); WL_TRACE("Exit\n"); @@ -3223,8 +3222,8 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg_to_ndev(cfg); WL_TRACE("Enter\n"); @@ -3238,12 +3237,12 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, * While going to suspend if associated with AP disassociate * from AP to save power while system is in suspended state */ - if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || - test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && - test_bit(WL_STATUS_READY, &cfg_priv->status)) { + if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || + test_bit(WL_STATUS_CONNECTING, &cfg->status)) && + test_bit(WL_STATUS_READY, &cfg->status)) { WL_INFO("Disassociating from AP" " while entering suspend state\n"); - brcmf_link_down(cfg_priv); + brcmf_link_down(cfg); /* * Make sure WPA_Supplicant receives all the event @@ -3253,13 +3252,13 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, brcmf_delay(500); } - if (test_bit(WL_STATUS_READY, &cfg_priv->status)) - brcmf_abort_scanning(cfg_priv); + if (test_bit(WL_STATUS_READY, &cfg->status)) + brcmf_abort_scanning(cfg); else - clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); + clear_bit(WL_STATUS_SCANNING, &cfg->status); /* Turn off watchdog timer */ - if (test_bit(WL_STATUS_READY, &cfg_priv->status)) + if (test_bit(WL_STATUS_READY, &cfg->status)) brcmf_set_mpc(ndev, 1); WL_TRACE("Exit\n"); @@ -3270,14 +3269,14 @@ static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy, static __used s32 brcmf_dev_bufvar_set(struct net_device *ndev, s8 *name, s8 *buf, s32 len) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); u32 buflen; - buflen = brcmf_c_mkiovar(name, buf, len, cfg_priv->dcmd_buf, + buflen = brcmf_c_mkiovar(name, buf, len, cfg->dcmd_buf, WL_DCMD_LEN_MAX); BUG_ON(!buflen); - return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg_priv->dcmd_buf, + return brcmf_exec_dcmd(ndev, BRCMF_C_SET_VAR, cfg->dcmd_buf, buflen); } @@ -3285,20 +3284,20 @@ static s32 brcmf_dev_bufvar_get(struct net_device *ndev, s8 *name, s8 *buf, s32 buf_len) { - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); u32 len; s32 err = 0; - len = brcmf_c_mkiovar(name, NULL, 0, cfg_priv->dcmd_buf, + len = brcmf_c_mkiovar(name, NULL, 0, cfg->dcmd_buf, WL_DCMD_LEN_MAX); BUG_ON(!len); - err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg_priv->dcmd_buf, + err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_VAR, cfg->dcmd_buf, WL_DCMD_LEN_MAX); if (err) { WL_ERR("error (%d)\n", err); return err; } - memcpy(buf, cfg_priv->dcmd_buf, buf_len); + memcpy(buf, cfg->dcmd_buf, buf_len); return err; } @@ -3331,8 +3330,8 @@ static s32 brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct pmkid_list *pmkids = &cfg_priv->pmk_list->pmkids; + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct pmkid_list *pmkids = &cfg->pmk_list->pmkids; s32 err = 0; int i; int pmkid_len; @@ -3360,7 +3359,7 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev, for (i = 0; i < WLAN_PMKID_LEN; i++) WL_CONN("%02x\n", pmkids->pmkid[pmkid_len].PMKID[i]); - err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); + err = brcmf_update_pmklist(ndev, cfg->pmk_list, err); WL_TRACE("Exit\n"); return err; @@ -3370,7 +3369,7 @@ static s32 brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_pmksa *pmksa) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct pmkid_list pmkid; s32 err = 0; int i, pmkid_len; @@ -3387,30 +3386,30 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, for (i = 0; i < WLAN_PMKID_LEN; i++) WL_CONN("%02x\n", pmkid.pmkid[0].PMKID[i]); - pmkid_len = le32_to_cpu(cfg_priv->pmk_list->pmkids.npmkid); + pmkid_len = le32_to_cpu(cfg->pmk_list->pmkids.npmkid); for (i = 0; i < pmkid_len; i++) if (!memcmp - (pmksa->bssid, &cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, + (pmksa->bssid, &cfg->pmk_list->pmkids.pmkid[i].BSSID, ETH_ALEN)) break; if ((pmkid_len > 0) && (i < pmkid_len)) { - memset(&cfg_priv->pmk_list->pmkids.pmkid[i], 0, + memset(&cfg->pmk_list->pmkids.pmkid[i], 0, sizeof(struct pmkid)); for (; i < (pmkid_len - 1); i++) { - memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].BSSID, - &cfg_priv->pmk_list->pmkids.pmkid[i + 1].BSSID, + memcpy(&cfg->pmk_list->pmkids.pmkid[i].BSSID, + &cfg->pmk_list->pmkids.pmkid[i + 1].BSSID, ETH_ALEN); - memcpy(&cfg_priv->pmk_list->pmkids.pmkid[i].PMKID, - &cfg_priv->pmk_list->pmkids.pmkid[i + 1].PMKID, + memcpy(&cfg->pmk_list->pmkids.pmkid[i].PMKID, + &cfg->pmk_list->pmkids.pmkid[i + 1].PMKID, WLAN_PMKID_LEN); } - cfg_priv->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); + cfg->pmk_list->pmkids.npmkid = cpu_to_le32(pmkid_len - 1); } else err = -EINVAL; - err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); + err = brcmf_update_pmklist(ndev, cfg->pmk_list, err); WL_TRACE("Exit\n"); return err; @@ -3420,15 +3419,15 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev, static s32 brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 err = 0; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) return -EIO; - memset(cfg_priv->pmk_list, 0, sizeof(*cfg_priv->pmk_list)); - err = brcmf_update_pmklist(ndev, cfg_priv->pmk_list, err); + memset(cfg->pmk_list, 0, sizeof(*cfg->pmk_list)); + err = brcmf_update_pmklist(ndev, cfg->pmk_list, err); WL_TRACE("Exit\n"); return err; @@ -3444,7 +3443,7 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev) * cfg80211_scan_request one out of the received PNO event. */ static s32 -brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_sched_scan_results(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -3452,7 +3451,7 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv, struct cfg80211_scan_request *request = NULL; struct cfg80211_ssid *ssid = NULL; struct ieee80211_channel *channel = NULL; - struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); + struct wiphy *wiphy = cfg_to_wiphy(cfg); int err = 0; int channel_req = 0; int band = 0; @@ -3524,19 +3523,19 @@ brcmf_notify_sched_scan_results(struct brcmf_cfg80211_priv *cfg_priv, if (request->n_ssids) request->ssids = &ssid[0]; - if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { /* Abort any on-going scan */ - brcmf_abort_scanning(cfg_priv); + brcmf_abort_scanning(cfg); } - set_bit(WL_STATUS_SCANNING, &cfg_priv->status); - err = brcmf_do_escan(cfg_priv, wiphy, ndev, request); + set_bit(WL_STATUS_SCANNING, &cfg->status); + err = brcmf_do_escan(cfg, wiphy, ndev, request); if (err) { - clear_bit(WL_STATUS_SCANNING, &cfg_priv->status); + clear_bit(WL_STATUS_SCANNING, &cfg->status); goto out_err; } - cfg_priv->sched_escan = true; - cfg_priv->scan_request = request; + cfg->sched_escan = true; + cfg->scan_request = request; } else { WL_ERR("FALSE PNO Event. (pfn_count == 0)\n"); goto out_err; @@ -3601,15 +3600,15 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, struct cfg80211_sched_scan_request *request) { char iovbuf[128]; - struct brcmf_cfg80211_priv *cfg_priv = wiphy_priv(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy); struct brcmf_pno_net_param_le pfn; int i; int ret = 0; WL_SCAN("Enter n_match_sets:%d n_ssids:%d\n", request->n_match_sets, request->n_ssids); - if (test_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { - WL_ERR("Scanning already : status (%lu)\n", cfg_priv->status); + if (test_bit(WL_STATUS_SCANNING, &cfg->status)) { + WL_ERR("Scanning already : status (%lu)\n", cfg->status); return -EAGAIN; } @@ -3688,12 +3687,12 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy, static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *ndev) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); WL_SCAN("enter\n"); brcmf_dev_pno_clean(ndev); - if (cfg_priv->sched_escan) - brcmf_notify_escan_complete(cfg_priv, ndev, true, true); + if (cfg->sched_escan) + brcmf_notify_escan_complete(cfg, ndev, true, true); return 0; } #endif /* CONFIG_BRCMISCAN */ @@ -3701,8 +3700,8 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy, #ifdef CONFIG_NL80211_TESTMODE static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); - struct net_device *ndev = cfg_priv->wdev->netdev; + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = cfg->wdev->netdev; struct brcmf_dcmd *dcmd = data; struct sk_buff *reply; int ret; @@ -4010,7 +4009,7 @@ brcmf_vndr_ie(u8 *iebuf, s32 pktflag, u8 *ie_ptr, u32 ie_len, s8 *add_del_cmd) } s32 -brcmf_set_management_ie(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_set_management_ie(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, s32 bssidx, s32 pktflag, u8 *vndr_ie_buf, u32 vndr_ie_len) { @@ -4035,19 +4034,19 @@ brcmf_set_management_ie(struct brcmf_cfg80211_priv *cfg_priv, if (!iovar_ie_buf) return -ENOMEM; curr_ie_buf = iovar_ie_buf; - if (test_bit(WL_STATUS_AP_CREATING, &cfg_priv->status) || - test_bit(WL_STATUS_AP_CREATED, &cfg_priv->status)) { + if (test_bit(WL_STATUS_AP_CREATING, &cfg->status) || + test_bit(WL_STATUS_AP_CREATED, &cfg->status)) { switch (pktflag) { case VNDR_IE_PRBRSP_FLAG: - mgmt_ie_buf = cfg_priv->ap_info->probe_res_ie; - mgmt_ie_len = &cfg_priv->ap_info->probe_res_ie_len; + mgmt_ie_buf = cfg->ap_info->probe_res_ie; + mgmt_ie_len = &cfg->ap_info->probe_res_ie_len; mgmt_ie_buf_len = - sizeof(cfg_priv->ap_info->probe_res_ie); + sizeof(cfg->ap_info->probe_res_ie); break; case VNDR_IE_BEACON_FLAG: - mgmt_ie_buf = cfg_priv->ap_info->beacon_ie; - mgmt_ie_len = &cfg_priv->ap_info->beacon_ie_len; - mgmt_ie_buf_len = sizeof(cfg_priv->ap_info->beacon_ie); + mgmt_ie_buf = cfg->ap_info->beacon_ie; + mgmt_ie_len = &cfg->ap_info->beacon_ie_len; + mgmt_ie_buf_len = sizeof(cfg->ap_info->beacon_ie); break; default: err = -EPERM; @@ -4153,7 +4152,7 @@ brcmf_set_management_ie(struct brcmf_cfg80211_priv *cfg_priv, err = brcmf_dev_iovar_setbuf_bsscfg(ndev, "vndr_ie", iovar_ie_buf, total_ie_buf_len, - cfg_priv->extra_buf, + cfg->extra_buf, WL_EXTRA_BUF_MAX, bssidx); if (err) WL_ERR("vndr ie set error : %d\n", err); @@ -4176,7 +4175,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, struct brcmf_tlv *rsn_ie; struct brcmf_vs_tlv *wpa_ie; struct brcmf_join_params join_params; - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 bssidx = 0; WL_TRACE("channel_type=%d, beacon_interval=%d, dtim_period=%d,\n", @@ -4186,7 +4185,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, settings->ssid, settings->ssid_len, settings->auth_type, settings->inactivity_timeout); - if (!test_bit(WL_STATUS_AP_CREATING, &cfg_priv->status)) { + if (!test_bit(WL_STATUS_AP_CREATING, &cfg->status)) { WL_ERR("Not in AP creation mode\n"); return -EPERM; } @@ -4237,10 +4236,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, wpa_ie = brcmf_find_wpaie((u8 *)settings->beacon.tail, settings->beacon.tail_len); - kfree(cfg_priv->ap_info->rsn_ie); - cfg_priv->ap_info->rsn_ie = NULL; - kfree(cfg_priv->ap_info->wpa_ie); - cfg_priv->ap_info->wpa_ie = NULL; + kfree(cfg->ap_info->rsn_ie); + cfg->ap_info->rsn_ie = NULL; + kfree(cfg->ap_info->wpa_ie); + cfg->ap_info->wpa_ie = NULL; if ((wpa_ie != NULL || rsn_ie != NULL)) { WL_TRACE("WPA(2) IE is found\n"); @@ -4250,7 +4249,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, bssidx); if (err < 0) goto exit; - cfg_priv->ap_info->wpa_ie = kmemdup(wpa_ie, + cfg->ap_info->wpa_ie = kmemdup(wpa_ie, wpa_ie->len + TLV_HDR_LEN, GFP_KERNEL); @@ -4260,19 +4259,19 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, (struct brcmf_vs_tlv *)rsn_ie, true, bssidx); if (err < 0) goto exit; - cfg_priv->ap_info->rsn_ie = kmemdup(rsn_ie, + cfg->ap_info->rsn_ie = kmemdup(rsn_ie, rsn_ie->len + TLV_HDR_LEN, GFP_KERNEL); } - cfg_priv->ap_info->security_mode = true; + cfg->ap_info->security_mode = true; } else { WL_TRACE("No WPA(2) IEs found\n"); brcmf_configure_opensecurity(ndev, bssidx); - cfg_priv->ap_info->security_mode = false; + cfg->ap_info->security_mode = false; } /* Set Beacon IEs to FW */ - err = brcmf_set_management_ie(cfg_priv, ndev, bssidx, + err = brcmf_set_management_ie(cfg, ndev, bssidx, VNDR_IE_BEACON_FLAG, (u8 *)settings->beacon.tail, settings->beacon.tail_len); @@ -4282,7 +4281,7 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, WL_TRACE("Applied Vndr IEs for Beacon\n"); /* Set Probe Response IEs to FW */ - err = brcmf_set_management_ie(cfg_priv, ndev, bssidx, + err = brcmf_set_management_ie(cfg, ndev, bssidx, VNDR_IE_PRBRSP_FLAG, (u8 *)settings->beacon.proberesp_ies, settings->beacon.proberesp_ies_len); @@ -4326,8 +4325,8 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, WL_ERR("SET SSID error (%d)\n", err); goto exit; } - clear_bit(WL_STATUS_AP_CREATING, &cfg_priv->status); - set_bit(WL_STATUS_AP_CREATED, &cfg_priv->status); + clear_bit(WL_STATUS_AP_CREATING, &cfg->status); + set_bit(WL_STATUS_AP_CREATED, &cfg->status); exit: if (err) @@ -4337,13 +4336,13 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev, static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) { - struct brcmf_cfg80211_priv *cfg_priv = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); s32 ioctl_value; s32 err = -EPERM; WL_TRACE("Enter\n"); - if (cfg_priv->conf->mode == WL_MODE_AP) { + if (cfg->conf->mode == WL_MODE_AP) { /* Due to most likely deauths outstanding we sleep */ /* first to make sure they get processed by fw. */ msleep(400); @@ -4360,8 +4359,8 @@ static int brcmf_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *ndev) goto exit; } brcmf_set_mpc(ndev, 1); - clear_bit(WL_STATUS_AP_CREATING, &cfg_priv->status); - clear_bit(WL_STATUS_AP_CREATED, &cfg_priv->status); + clear_bit(WL_STATUS_AP_CREATING, &cfg->status); + clear_bit(WL_STATUS_AP_CREATED, &cfg->status); } exit: return err; @@ -4466,7 +4465,7 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) return ERR_PTR(-ENOMEM); wdev->wiphy = wiphy_new(&wl_cfg80211_ops, - sizeof(struct brcmf_cfg80211_priv)); + sizeof(struct brcmf_cfg80211_info)); if (!wdev->wiphy) { WL_ERR("Could not allocate wiphy device\n"); err = -ENOMEM; @@ -4510,9 +4509,9 @@ static struct wireless_dev *brcmf_alloc_wdev(struct device *ndev) return ERR_PTR(err); } -static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_free_wdev(struct brcmf_cfg80211_info *cfg) { - struct wireless_dev *wdev = cfg_priv->wdev; + struct wireless_dev *wdev = cfg->wdev; if (!wdev) { WL_ERR("wdev is invalid\n"); @@ -4521,10 +4520,10 @@ static void brcmf_free_wdev(struct brcmf_cfg80211_priv *cfg_priv) wiphy_unregister(wdev->wiphy); wiphy_free(wdev->wiphy); kfree(wdev); - cfg_priv->wdev = NULL; + cfg->wdev = NULL; } -static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv, +static bool brcmf_is_linkup(struct brcmf_cfg80211_info *cfg, const struct brcmf_event_msg *e) { u32 event = be32_to_cpu(e->event_type); @@ -4532,14 +4531,14 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_priv *cfg_priv, if (event == BRCMF_E_SET_SSID && status == BRCMF_E_STATUS_SUCCESS) { WL_CONN("Processing set ssid\n"); - cfg_priv->link_up = true; + cfg->link_up = true; return true; } return false; } -static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv, +static bool brcmf_is_linkdown(struct brcmf_cfg80211_info *cfg, const struct brcmf_event_msg *e) { u32 event = be32_to_cpu(e->event_type); @@ -4552,7 +4551,7 @@ static bool brcmf_is_linkdown(struct brcmf_cfg80211_priv *cfg_priv, return false; } -static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv, +static bool brcmf_is_nonetwork(struct brcmf_cfg80211_info *cfg, const struct brcmf_event_msg *e) { u32 event = be32_to_cpu(e->event_type); @@ -4573,9 +4572,9 @@ static bool brcmf_is_nonetwork(struct brcmf_cfg80211_priv *cfg_priv, return false; } -static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_info *cfg) { - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); kfree(conn_info->req_ie); conn_info->req_ie = NULL; @@ -4585,30 +4584,30 @@ static void brcmf_clear_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) conn_info->resp_ie_len = 0; } -static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_info *cfg) { - struct net_device *ndev = cfg_to_ndev(cfg_priv); + struct net_device *ndev = cfg_to_ndev(cfg); struct brcmf_cfg80211_assoc_ielen_le *assoc_info; - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); u32 req_len; u32 resp_len; s32 err = 0; - brcmf_clear_assoc_ies(cfg_priv); + brcmf_clear_assoc_ies(cfg); - err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg_priv->extra_buf, + err = brcmf_dev_bufvar_get(ndev, "assoc_info", cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { WL_ERR("could not get assoc info (%d)\n", err); return err; } assoc_info = - (struct brcmf_cfg80211_assoc_ielen_le *)cfg_priv->extra_buf; + (struct brcmf_cfg80211_assoc_ielen_le *)cfg->extra_buf; req_len = le32_to_cpu(assoc_info->req_len); resp_len = le32_to_cpu(assoc_info->resp_len); if (req_len) { err = brcmf_dev_bufvar_get(ndev, "assoc_req_ies", - cfg_priv->extra_buf, + cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { WL_ERR("could not get assoc req (%d)\n", err); @@ -4616,7 +4615,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) } conn_info->req_ie_len = req_len; conn_info->req_ie = - kmemdup(cfg_priv->extra_buf, conn_info->req_ie_len, + kmemdup(cfg->extra_buf, conn_info->req_ie_len, GFP_KERNEL); } else { conn_info->req_ie_len = 0; @@ -4624,7 +4623,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) } if (resp_len) { err = brcmf_dev_bufvar_get(ndev, "assoc_resp_ies", - cfg_priv->extra_buf, + cfg->extra_buf, WL_ASSOC_INFO_MAX); if (err) { WL_ERR("could not get assoc resp (%d)\n", err); @@ -4632,7 +4631,7 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) } conn_info->resp_ie_len = resp_len; conn_info->resp_ie = - kmemdup(cfg_priv->extra_buf, conn_info->resp_ie_len, + kmemdup(cfg->extra_buf, conn_info->resp_ie_len, GFP_KERNEL); } else { conn_info->resp_ie_len = 0; @@ -4645,12 +4644,12 @@ static s32 brcmf_get_assoc_ies(struct brcmf_cfg80211_priv *cfg_priv) } static s32 -brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e) { - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); - struct wiphy *wiphy = cfg_to_wiphy(cfg_priv); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); + struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_channel_info_le channel_le; struct ieee80211_channel *notify_channel; struct ieee80211_supported_band *band; @@ -4660,9 +4659,9 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, WL_TRACE("Enter\n"); - brcmf_get_assoc_ies(cfg_priv); - brcmf_update_prof(cfg_priv, NULL, &e->addr, WL_PROF_BSSID); - brcmf_update_bss_info(cfg_priv); + brcmf_get_assoc_ies(cfg); + brcmf_update_prof(cfg, NULL, &e->addr, WL_PROF_BSSID); + brcmf_update_bss_info(cfg); brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, sizeof(channel_le)); @@ -4679,35 +4678,35 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_priv *cfg_priv, notify_channel = ieee80211_get_channel(wiphy, freq); cfg80211_roamed(ndev, notify_channel, - (u8 *)brcmf_read_prof(cfg_priv, WL_PROF_BSSID), + (u8 *)brcmf_read_prof(cfg, WL_PROF_BSSID), conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); WL_CONN("Report roaming result\n"); - set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); + set_bit(WL_STATUS_CONNECTED, &cfg->status); WL_TRACE("Exit\n"); return err; } static s32 -brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, bool completed) { - struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg_priv); + struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); s32 err = 0; WL_TRACE("Enter\n"); - if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) { + if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) { if (completed) { - brcmf_get_assoc_ies(cfg_priv); - brcmf_update_prof(cfg_priv, NULL, &e->addr, + brcmf_get_assoc_ies(cfg); + brcmf_update_prof(cfg, NULL, &e->addr, WL_PROF_BSSID); - brcmf_update_bss_info(cfg_priv); + brcmf_update_bss_info(cfg); } cfg80211_connect_result(ndev, - (u8 *)brcmf_read_prof(cfg_priv, + (u8 *)brcmf_read_prof(cfg, WL_PROF_BSSID), conn_info->req_ie, conn_info->req_ie_len, @@ -4717,7 +4716,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, WLAN_STATUS_AUTH_TIMEOUT, GFP_KERNEL); if (completed) - set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); + set_bit(WL_STATUS_CONNECTED, &cfg->status); WL_CONN("Report connect result - connection %s\n", completed ? "succeeded" : "failed"); } @@ -4726,7 +4725,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_priv *cfg_priv, } static s32 -brcmf_notify_connect_status_ap(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_connect_status_ap(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4765,54 +4764,54 @@ brcmf_notify_connect_status_ap(struct brcmf_cfg80211_priv *cfg_priv, } static s32 -brcmf_notify_connect_status(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { s32 err = 0; - if (cfg_priv->conf->mode == WL_MODE_AP) { - err = brcmf_notify_connect_status_ap(cfg_priv, ndev, e, data); - } else if (brcmf_is_linkup(cfg_priv, e)) { + if (cfg->conf->mode == WL_MODE_AP) { + err = brcmf_notify_connect_status_ap(cfg, ndev, e, data); + } else if (brcmf_is_linkup(cfg, e)) { WL_CONN("Linkup\n"); - if (brcmf_is_ibssmode(cfg_priv)) { - brcmf_update_prof(cfg_priv, NULL, (void *)e->addr, + if (brcmf_is_ibssmode(cfg)) { + brcmf_update_prof(cfg, NULL, (void *)e->addr, WL_PROF_BSSID); - wl_inform_ibss(cfg_priv, ndev, e->addr); + wl_inform_ibss(cfg, ndev, e->addr); cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); - clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); - set_bit(WL_STATUS_CONNECTED, &cfg_priv->status); + clear_bit(WL_STATUS_CONNECTING, &cfg->status); + set_bit(WL_STATUS_CONNECTED, &cfg->status); } else - brcmf_bss_connect_done(cfg_priv, ndev, e, true); - } else if (brcmf_is_linkdown(cfg_priv, e)) { + brcmf_bss_connect_done(cfg, ndev, e, true); + } else if (brcmf_is_linkdown(cfg, e)) { WL_CONN("Linkdown\n"); - if (brcmf_is_ibssmode(cfg_priv)) { - clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + if (brcmf_is_ibssmode(cfg)) { + clear_bit(WL_STATUS_CONNECTING, &cfg->status); if (test_and_clear_bit(WL_STATUS_CONNECTED, - &cfg_priv->status)) - brcmf_link_down(cfg_priv); + &cfg->status)) + brcmf_link_down(cfg); } else { - brcmf_bss_connect_done(cfg_priv, ndev, e, false); + brcmf_bss_connect_done(cfg, ndev, e, false); if (test_and_clear_bit(WL_STATUS_CONNECTED, - &cfg_priv->status)) { + &cfg->status)) { cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); - brcmf_link_down(cfg_priv); + brcmf_link_down(cfg); } } - brcmf_init_prof(cfg_priv->profile); - } else if (brcmf_is_nonetwork(cfg_priv, e)) { - if (brcmf_is_ibssmode(cfg_priv)) - clear_bit(WL_STATUS_CONNECTING, &cfg_priv->status); + brcmf_init_prof(cfg->profile); + } else if (brcmf_is_nonetwork(cfg, e)) { + if (brcmf_is_ibssmode(cfg)) + clear_bit(WL_STATUS_CONNECTING, &cfg->status); else - brcmf_bss_connect_done(cfg_priv, ndev, e, false); + brcmf_bss_connect_done(cfg, ndev, e, false); } return err; } static s32 -brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_roaming_status(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4821,17 +4820,17 @@ brcmf_notify_roaming_status(struct brcmf_cfg80211_priv *cfg_priv, u32 status = be32_to_cpu(e->status); if (event == BRCMF_E_ROAM && status == BRCMF_E_STATUS_SUCCESS) { - if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) - brcmf_bss_roaming_done(cfg_priv, ndev, e); + if (test_bit(WL_STATUS_CONNECTED, &cfg->status)) + brcmf_bss_roaming_done(cfg, ndev, e); else - brcmf_bss_connect_done(cfg_priv, ndev, e, true); + brcmf_bss_connect_done(cfg, ndev, e, true); } return err; } static s32 -brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_mic_status(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4850,7 +4849,7 @@ brcmf_notify_mic_status(struct brcmf_cfg80211_priv *cfg_priv, } static s32 -brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, +brcmf_notify_scan_status(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { @@ -4863,12 +4862,12 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, WL_TRACE("Enter\n"); - if (cfg_priv->iscan_on && cfg_priv->iscan_kickstart) { + if (cfg->iscan_on && cfg->iscan_kickstart) { WL_TRACE("Exit\n"); - return brcmf_wakeup_iscan(cfg_to_iscan(cfg_priv)); + return brcmf_wakeup_iscan(cfg_to_iscan(cfg)); } - if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg_priv->status)) { + if (!test_and_clear_bit(WL_STATUS_SCANNING, &cfg->status)) { WL_ERR("Scan complete while device not scanning\n"); scan_abort = true; err = -EINVAL; @@ -4885,33 +4884,33 @@ brcmf_notify_scan_status(struct brcmf_cfg80211_priv *cfg_priv, scan_channel = le32_to_cpu(channel_inform_le.scan_channel); if (scan_channel) WL_CONN("channel_inform.scan_channel (%d)\n", scan_channel); - cfg_priv->bss_list = cfg_priv->scan_results; - bss_list_le = (struct brcmf_scan_results_le *) cfg_priv->bss_list; + cfg->bss_list = cfg->scan_results; + bss_list_le = (struct brcmf_scan_results_le *) cfg->bss_list; - memset(cfg_priv->scan_results, 0, len); + memset(cfg->scan_results, 0, len); bss_list_le->buflen = cpu_to_le32(len); err = brcmf_exec_dcmd(ndev, BRCMF_C_SCAN_RESULTS, - cfg_priv->scan_results, len); + cfg->scan_results, len); if (err) { WL_ERR("%s Scan_results error (%d)\n", ndev->name, err); err = -EINVAL; scan_abort = true; goto scan_done_out; } - cfg_priv->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); - cfg_priv->scan_results->version = le32_to_cpu(bss_list_le->version); - cfg_priv->scan_results->count = le32_to_cpu(bss_list_le->count); + cfg->scan_results->buflen = le32_to_cpu(bss_list_le->buflen); + cfg->scan_results->version = le32_to_cpu(bss_list_le->version); + cfg->scan_results->count = le32_to_cpu(bss_list_le->count); - err = brcmf_inform_bss(cfg_priv); + err = brcmf_inform_bss(cfg); if (err) scan_abort = true; scan_done_out: - if (cfg_priv->scan_request) { + if (cfg->scan_request) { WL_SCAN("calling cfg80211_scan_done\n"); - cfg80211_scan_done(cfg_priv->scan_request, scan_abort); + cfg80211_scan_done(cfg->scan_request, scan_abort); brcmf_set_mpc(ndev, 1); - cfg_priv->scan_request = NULL; + cfg->scan_request = NULL; } WL_TRACE("Exit\n"); @@ -4945,74 +4944,74 @@ static void brcmf_init_eloop_handler(struct brcmf_cfg80211_event_loop *el) el->handler[BRCMF_E_PFN_NET_FOUND] = brcmf_notify_sched_scan_results; } -static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_deinit_priv_mem(struct brcmf_cfg80211_info *cfg) { - kfree(cfg_priv->scan_results); - cfg_priv->scan_results = NULL; - kfree(cfg_priv->bss_info); - cfg_priv->bss_info = NULL; - kfree(cfg_priv->conf); - cfg_priv->conf = NULL; - kfree(cfg_priv->profile); - cfg_priv->profile = NULL; - kfree(cfg_priv->scan_req_int); - cfg_priv->scan_req_int = NULL; - kfree(cfg_priv->escan_ioctl_buf); - cfg_priv->escan_ioctl_buf = NULL; - kfree(cfg_priv->dcmd_buf); - cfg_priv->dcmd_buf = NULL; - kfree(cfg_priv->extra_buf); - cfg_priv->extra_buf = NULL; - kfree(cfg_priv->iscan); - cfg_priv->iscan = NULL; - kfree(cfg_priv->pmk_list); - cfg_priv->pmk_list = NULL; - if (cfg_priv->ap_info) { - kfree(cfg_priv->ap_info->wpa_ie); - kfree(cfg_priv->ap_info->rsn_ie); - kfree(cfg_priv->ap_info); - cfg_priv->ap_info = NULL; + kfree(cfg->scan_results); + cfg->scan_results = NULL; + kfree(cfg->bss_info); + cfg->bss_info = NULL; + kfree(cfg->conf); + cfg->conf = NULL; + kfree(cfg->profile); + cfg->profile = NULL; + kfree(cfg->scan_req_int); + cfg->scan_req_int = NULL; + kfree(cfg->escan_ioctl_buf); + cfg->escan_ioctl_buf = NULL; + kfree(cfg->dcmd_buf); + cfg->dcmd_buf = NULL; + kfree(cfg->extra_buf); + cfg->extra_buf = NULL; + kfree(cfg->iscan); + cfg->iscan = NULL; + kfree(cfg->pmk_list); + cfg->pmk_list = NULL; + if (cfg->ap_info) { + kfree(cfg->ap_info->wpa_ie); + kfree(cfg->ap_info->rsn_ie); + kfree(cfg->ap_info); + cfg->ap_info = NULL; } } -static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_info *cfg) { - cfg_priv->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); - if (!cfg_priv->scan_results) + cfg->scan_results = kzalloc(WL_SCAN_BUF_MAX, GFP_KERNEL); + if (!cfg->scan_results) goto init_priv_mem_out; - cfg_priv->conf = kzalloc(sizeof(*cfg_priv->conf), GFP_KERNEL); - if (!cfg_priv->conf) + cfg->conf = kzalloc(sizeof(*cfg->conf), GFP_KERNEL); + if (!cfg->conf) goto init_priv_mem_out; - cfg_priv->profile = kzalloc(sizeof(*cfg_priv->profile), GFP_KERNEL); - if (!cfg_priv->profile) + cfg->profile = kzalloc(sizeof(*cfg->profile), GFP_KERNEL); + if (!cfg->profile) goto init_priv_mem_out; - cfg_priv->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); - if (!cfg_priv->bss_info) + cfg->bss_info = kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (!cfg->bss_info) goto init_priv_mem_out; - cfg_priv->scan_req_int = kzalloc(sizeof(*cfg_priv->scan_req_int), + cfg->scan_req_int = kzalloc(sizeof(*cfg->scan_req_int), GFP_KERNEL); - if (!cfg_priv->scan_req_int) + if (!cfg->scan_req_int) goto init_priv_mem_out; - cfg_priv->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); - if (!cfg_priv->escan_ioctl_buf) + cfg->escan_ioctl_buf = kzalloc(BRCMF_DCMD_MEDLEN, GFP_KERNEL); + if (!cfg->escan_ioctl_buf) goto init_priv_mem_out; - cfg_priv->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); - if (!cfg_priv->dcmd_buf) + cfg->dcmd_buf = kzalloc(WL_DCMD_LEN_MAX, GFP_KERNEL); + if (!cfg->dcmd_buf) goto init_priv_mem_out; - cfg_priv->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); - if (!cfg_priv->extra_buf) + cfg->extra_buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); + if (!cfg->extra_buf) goto init_priv_mem_out; - cfg_priv->iscan = kzalloc(sizeof(*cfg_priv->iscan), GFP_KERNEL); - if (!cfg_priv->iscan) + cfg->iscan = kzalloc(sizeof(*cfg->iscan), GFP_KERNEL); + if (!cfg->iscan) goto init_priv_mem_out; - cfg_priv->pmk_list = kzalloc(sizeof(*cfg_priv->pmk_list), GFP_KERNEL); - if (!cfg_priv->pmk_list) + cfg->pmk_list = kzalloc(sizeof(*cfg->pmk_list), GFP_KERNEL); + if (!cfg->pmk_list) goto init_priv_mem_out; return 0; init_priv_mem_out: - brcmf_deinit_priv_mem(cfg_priv); + brcmf_deinit_priv_mem(cfg); return -ENOMEM; } @@ -5022,17 +5021,17 @@ static s32 brcmf_init_priv_mem(struct brcmf_cfg80211_priv *cfg_priv) */ static struct brcmf_cfg80211_event_q *brcmf_deq_event( - struct brcmf_cfg80211_priv *cfg_priv) + struct brcmf_cfg80211_info *cfg) { struct brcmf_cfg80211_event_q *e = NULL; - spin_lock_irq(&cfg_priv->evt_q_lock); - if (!list_empty(&cfg_priv->evt_q_list)) { - e = list_first_entry(&cfg_priv->evt_q_list, + spin_lock_irq(&cfg->evt_q_lock); + if (!list_empty(&cfg->evt_q_list)) { + e = list_first_entry(&cfg->evt_q_list, struct brcmf_cfg80211_event_q, evt_q_list); list_del(&e->evt_q_list); } - spin_unlock_irq(&cfg_priv->evt_q_lock); + spin_unlock_irq(&cfg->evt_q_lock); return e; } @@ -5044,7 +5043,7 @@ static struct brcmf_cfg80211_event_q *brcmf_deq_event( */ static s32 -brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, +brcmf_enq_event(struct brcmf_cfg80211_info *cfg, u32 event, const struct brcmf_event_msg *msg, void *data) { struct brcmf_cfg80211_event_q *e; @@ -5068,9 +5067,9 @@ brcmf_enq_event(struct brcmf_cfg80211_priv *cfg_priv, u32 event, if (data) memcpy(&e->edata, data, data_len); - spin_lock_irqsave(&cfg_priv->evt_q_lock, flags); - list_add_tail(&e->evt_q_list, &cfg_priv->evt_q_list); - spin_unlock_irqrestore(&cfg_priv->evt_q_lock, flags); + spin_lock_irqsave(&cfg->evt_q_lock, flags); + list_add_tail(&e->evt_q_list, &cfg->evt_q_list); + spin_unlock_irqrestore(&cfg->evt_q_lock, flags); return err; } @@ -5082,12 +5081,12 @@ static void brcmf_put_event(struct brcmf_cfg80211_event_q *e) static void brcmf_cfg80211_event_handler(struct work_struct *work) { - struct brcmf_cfg80211_priv *cfg_priv = - container_of(work, struct brcmf_cfg80211_priv, + struct brcmf_cfg80211_info *cfg = + container_of(work, struct brcmf_cfg80211_info, event_work); struct brcmf_cfg80211_event_q *e; - e = brcmf_deq_event(cfg_priv); + e = brcmf_deq_event(cfg); if (unlikely(!e)) { WL_ERR("event queue empty...\n"); return; @@ -5095,95 +5094,95 @@ static void brcmf_cfg80211_event_handler(struct work_struct *work) do { WL_INFO("event type (%d)\n", e->etype); - if (cfg_priv->el.handler[e->etype]) - cfg_priv->el.handler[e->etype](cfg_priv, - cfg_to_ndev(cfg_priv), + if (cfg->el.handler[e->etype]) + cfg->el.handler[e->etype](cfg, + cfg_to_ndev(cfg), &e->emsg, e->edata); else WL_INFO("Unknown Event (%d): ignoring\n", e->etype); brcmf_put_event(e); - } while ((e = brcmf_deq_event(cfg_priv))); + } while ((e = brcmf_deq_event(cfg))); } -static void brcmf_init_eq(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_init_eq(struct brcmf_cfg80211_info *cfg) { - spin_lock_init(&cfg_priv->evt_q_lock); - INIT_LIST_HEAD(&cfg_priv->evt_q_list); + spin_lock_init(&cfg->evt_q_lock); + INIT_LIST_HEAD(&cfg->evt_q_list); } -static void brcmf_flush_eq(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_flush_eq(struct brcmf_cfg80211_info *cfg) { struct brcmf_cfg80211_event_q *e; - spin_lock_irq(&cfg_priv->evt_q_lock); - while (!list_empty(&cfg_priv->evt_q_list)) { - e = list_first_entry(&cfg_priv->evt_q_list, + spin_lock_irq(&cfg->evt_q_lock); + while (!list_empty(&cfg->evt_q_list)) { + e = list_first_entry(&cfg->evt_q_list, struct brcmf_cfg80211_event_q, evt_q_list); list_del(&e->evt_q_list); kfree(e); } - spin_unlock_irq(&cfg_priv->evt_q_lock); + spin_unlock_irq(&cfg->evt_q_lock); } -static s32 wl_init_priv(struct brcmf_cfg80211_priv *cfg_priv) +static s32 wl_init_priv(struct brcmf_cfg80211_info *cfg) { s32 err = 0; - cfg_priv->scan_request = NULL; - cfg_priv->pwr_save = true; + cfg->scan_request = NULL; + cfg->pwr_save = true; #ifdef CONFIG_BRCMISCAN - cfg_priv->iscan_on = true; /* iscan on & off switch. + cfg->iscan_on = true; /* iscan on & off switch. we enable iscan per default */ - cfg_priv->escan_on = false; /* escan on & off switch. + cfg->escan_on = false; /* escan on & off switch. we disable escan per default */ #else - cfg_priv->iscan_on = false; /* iscan on & off switch. + cfg->iscan_on = false; /* iscan on & off switch. we disable iscan per default */ - cfg_priv->escan_on = true; /* escan on & off switch. + cfg->escan_on = true; /* escan on & off switch. we enable escan per default */ #endif - cfg_priv->roam_on = true; /* roam on & off switch. + cfg->roam_on = true; /* roam on & off switch. we enable roam per default */ - cfg_priv->iscan_kickstart = false; - cfg_priv->active_scan = true; /* we do active scan for + cfg->iscan_kickstart = false; + cfg->active_scan = true; /* we do active scan for specific scan per default */ - cfg_priv->dongle_up = false; /* dongle is not up yet */ - brcmf_init_eq(cfg_priv); - err = brcmf_init_priv_mem(cfg_priv); + cfg->dongle_up = false; /* dongle is not up yet */ + brcmf_init_eq(cfg); + err = brcmf_init_priv_mem(cfg); if (err) return err; - INIT_WORK(&cfg_priv->event_work, brcmf_cfg80211_event_handler); - brcmf_init_eloop_handler(&cfg_priv->el); - mutex_init(&cfg_priv->usr_sync); - err = brcmf_init_iscan(cfg_priv); + INIT_WORK(&cfg->event_work, brcmf_cfg80211_event_handler); + brcmf_init_eloop_handler(&cfg->el); + mutex_init(&cfg->usr_sync); + err = brcmf_init_iscan(cfg); if (err) return err; - brcmf_init_escan(cfg_priv); - brcmf_init_conf(cfg_priv->conf); - brcmf_init_prof(cfg_priv->profile); - brcmf_link_down(cfg_priv); + brcmf_init_escan(cfg); + brcmf_init_conf(cfg->conf); + brcmf_init_prof(cfg->profile); + brcmf_link_down(cfg); return err; } -static void wl_deinit_priv(struct brcmf_cfg80211_priv *cfg_priv) +static void wl_deinit_priv(struct brcmf_cfg80211_info *cfg) { - cancel_work_sync(&cfg_priv->event_work); - cfg_priv->dongle_up = false; /* dongle down */ - brcmf_flush_eq(cfg_priv); - brcmf_link_down(cfg_priv); - brcmf_abort_scanning(cfg_priv); - brcmf_deinit_priv_mem(cfg_priv); + cancel_work_sync(&cfg->event_work); + cfg->dongle_up = false; /* dongle down */ + brcmf_flush_eq(cfg); + brcmf_link_down(cfg); + brcmf_abort_scanning(cfg); + brcmf_deinit_priv_mem(cfg); } -struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, +struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, struct device *busdev, struct brcmf_pub *drvr) { struct wireless_dev *wdev; - struct brcmf_cfg80211_priv *cfg_priv; + struct brcmf_cfg80211_info *cfg; s32 err = 0; if (!ndev) { @@ -5197,29 +5196,29 @@ struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, } wdev->iftype = brcmf_mode_to_nl80211_iftype(WL_MODE_BSS); - cfg_priv = wdev_to_cfg(wdev); - cfg_priv->wdev = wdev; - cfg_priv->pub = drvr; + cfg = wdev_to_cfg(wdev); + cfg->wdev = wdev; + cfg->pub = drvr; ndev->ieee80211_ptr = wdev; SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy)); wdev->netdev = ndev; - err = wl_init_priv(cfg_priv); + err = wl_init_priv(cfg); if (err) { WL_ERR("Failed to init iwm_priv (%d)\n", err); goto cfg80211_attach_out; } - return cfg_priv; + return cfg; cfg80211_attach_out: - brcmf_free_wdev(cfg_priv); + brcmf_free_wdev(cfg); return NULL; } -void brcmf_cfg80211_detach(struct brcmf_cfg80211_priv *cfg_priv) +void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg) { - wl_deinit_priv(cfg_priv); - brcmf_free_wdev(cfg_priv); + wl_deinit_priv(cfg); + brcmf_free_wdev(cfg); } void @@ -5227,10 +5226,10 @@ brcmf_cfg80211_event(struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { u32 event_type = be32_to_cpu(e->event_type); - struct brcmf_cfg80211_priv *cfg_priv = ndev_to_cfg(ndev); + struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); - if (!brcmf_enq_event(cfg_priv, event_type, e, data)) - schedule_work(&cfg_priv->event_work); + if (!brcmf_enq_event(cfg, event_type, e, data)) + schedule_work(&cfg->event_work); } static s32 brcmf_dongle_mode(struct net_device *ndev, s32 iftype) @@ -5426,14 +5425,14 @@ brcmf_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time, return err; } -static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) +static s32 wl_update_wiphybands(struct brcmf_cfg80211_info *cfg) { struct wiphy *wiphy; s32 phy_list; s8 phy; s32 err = 0; - err = brcmf_exec_dcmd(cfg_to_ndev(cfg_priv), BRCM_GET_PHYLIST, + err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCM_GET_PHYLIST, &phy_list, sizeof(phy_list)); if (err) { WL_ERR("error (%d)\n", err); @@ -5443,29 +5442,29 @@ static s32 wl_update_wiphybands(struct brcmf_cfg80211_priv *cfg_priv) phy = ((char *)&phy_list)[0]; WL_INFO("%c phy\n", phy); if (phy == 'n' || phy == 'a') { - wiphy = cfg_to_wiphy(cfg_priv); + wiphy = cfg_to_wiphy(cfg); wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_n; } return err; } -static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_dongle_probecap(struct brcmf_cfg80211_info *cfg) { - return wl_update_wiphybands(cfg_priv); + return wl_update_wiphybands(cfg); } -static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) +static s32 brcmf_config_dongle(struct brcmf_cfg80211_info *cfg) { struct net_device *ndev; struct wireless_dev *wdev; s32 power_mode; s32 err = 0; - if (cfg_priv->dongle_up) + if (cfg->dongle_up) return err; - ndev = cfg_to_ndev(cfg_priv); + ndev = cfg_to_ndev(cfg); wdev = ndev->ieee80211_ptr; brcmf_dongle_scantime(ndev, WL_SCAN_CHANNEL_TIME, @@ -5475,21 +5474,21 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) if (err) goto default_conf_out; - power_mode = cfg_priv->pwr_save ? PM_FAST : PM_OFF; + power_mode = cfg->pwr_save ? PM_FAST : PM_OFF; err = brcmf_exec_dcmd_u32(ndev, BRCMF_C_SET_PM, &power_mode); if (err) goto default_conf_out; WL_INFO("power save set to %s\n", (power_mode ? "enabled" : "disabled")); - err = brcmf_dongle_roam(ndev, (cfg_priv->roam_on ? 0 : 1), + err = brcmf_dongle_roam(ndev, (cfg->roam_on ? 0 : 1), WL_BEACON_TIMEOUT); if (err) goto default_conf_out; err = brcmf_dongle_mode(ndev, wdev->iftype); if (err && err != -EINPROGRESS) goto default_conf_out; - err = brcmf_dongle_probecap(cfg_priv); + err = brcmf_dongle_probecap(cfg); if (err) goto default_conf_out; @@ -5497,31 +5496,31 @@ static s32 brcmf_config_dongle(struct brcmf_cfg80211_priv *cfg_priv) default_conf_out: - cfg_priv->dongle_up = true; + cfg->dongle_up = true; return err; } -static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv) +static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_info *cfg) { char buf[10+IFNAMSIZ]; struct dentry *fd; s32 err = 0; - sprintf(buf, "netdev:%s", cfg_to_ndev(cfg_priv)->name); - cfg_priv->debugfsdir = debugfs_create_dir(buf, - cfg_to_wiphy(cfg_priv)->debugfsdir); + sprintf(buf, "netdev:%s", cfg_to_ndev(cfg)->name); + cfg->debugfsdir = debugfs_create_dir(buf, + cfg_to_wiphy(cfg)->debugfsdir); - fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg_priv->debugfsdir, - (u16 *)&cfg_priv->profile->beacon_interval); + fd = debugfs_create_u16("beacon_int", S_IRUGO, cfg->debugfsdir, + (u16 *)&cfg->profile->beacon_interval); if (!fd) { err = -ENOMEM; goto err_out; } - fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg_priv->debugfsdir, - (u8 *)&cfg_priv->profile->dtim_period); + fd = debugfs_create_u8("dtim_period", S_IRUGO, cfg->debugfsdir, + (u8 *)&cfg->profile->dtim_period); if (!fd) { err = -ENOMEM; goto err_out; @@ -5531,40 +5530,40 @@ static int brcmf_debugfs_add_netdev_params(struct brcmf_cfg80211_priv *cfg_priv) return err; } -static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_priv *cfg_priv) +static void brcmf_debugfs_remove_netdev(struct brcmf_cfg80211_info *cfg) { - debugfs_remove_recursive(cfg_priv->debugfsdir); - cfg_priv->debugfsdir = NULL; + debugfs_remove_recursive(cfg->debugfsdir); + cfg->debugfsdir = NULL; } -static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) +static s32 __brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) { s32 err = 0; - set_bit(WL_STATUS_READY, &cfg_priv->status); + set_bit(WL_STATUS_READY, &cfg->status); - brcmf_debugfs_add_netdev_params(cfg_priv); + brcmf_debugfs_add_netdev_params(cfg); - err = brcmf_config_dongle(cfg_priv); + err = brcmf_config_dongle(cfg); if (err) return err; - brcmf_invoke_iscan(cfg_priv); + brcmf_invoke_iscan(cfg); return err; } -static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) +static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) { /* * While going down, if associated with AP disassociate * from AP to save power */ - if ((test_bit(WL_STATUS_CONNECTED, &cfg_priv->status) || - test_bit(WL_STATUS_CONNECTING, &cfg_priv->status)) && - test_bit(WL_STATUS_READY, &cfg_priv->status)) { + if ((test_bit(WL_STATUS_CONNECTED, &cfg->status) || + test_bit(WL_STATUS_CONNECTING, &cfg->status)) && + test_bit(WL_STATUS_READY, &cfg->status)) { WL_INFO("Disassociating from AP"); - brcmf_link_down(cfg_priv); + brcmf_link_down(cfg); /* Make sure WPA_Supplicant receives all the event generated due to DISASSOC call to the fw to keep @@ -5573,32 +5572,32 @@ static s32 __brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) brcmf_delay(500); } - brcmf_abort_scanning(cfg_priv); - clear_bit(WL_STATUS_READY, &cfg_priv->status); + brcmf_abort_scanning(cfg); + clear_bit(WL_STATUS_READY, &cfg->status); - brcmf_debugfs_remove_netdev(cfg_priv); + brcmf_debugfs_remove_netdev(cfg); return 0; } -s32 brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv) +s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg) { s32 err = 0; - mutex_lock(&cfg_priv->usr_sync); - err = __brcmf_cfg80211_up(cfg_priv); - mutex_unlock(&cfg_priv->usr_sync); + mutex_lock(&cfg->usr_sync); + err = __brcmf_cfg80211_up(cfg); + mutex_unlock(&cfg->usr_sync); return err; } -s32 brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv) +s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg) { s32 err = 0; - mutex_lock(&cfg_priv->usr_sync); - err = __brcmf_cfg80211_down(cfg_priv); - mutex_unlock(&cfg_priv->usr_sync); + mutex_lock(&cfg->usr_sync); + err = __brcmf_cfg80211_down(cfg); + mutex_unlock(&cfg->usr_sync); return err; } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h index 374680072c16..71ced174748a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h @@ -176,11 +176,11 @@ struct brcmf_cfg80211_conf { }; /* forward declaration */ -struct brcmf_cfg80211_priv; +struct brcmf_cfg80211_info; /* cfg80211 main event loop */ struct brcmf_cfg80211_event_loop { - s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_priv *cfg_priv, + s32(*handler[BRCMF_E_LAST]) (struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data); @@ -238,7 +238,7 @@ struct brcmf_cfg80211_profile { /* dongle iscan event loop */ struct brcmf_cfg80211_iscan_eloop { s32 (*handler[WL_SCAN_ERSULTS_LAST]) - (struct brcmf_cfg80211_priv *cfg_priv); + (struct brcmf_cfg80211_info *cfg); }; /* dongle iscan controller */ @@ -381,7 +381,7 @@ struct brcmf_pno_scanresults_le { }; /** - * struct brcmf_cfg80211_priv - dongle private data of cfg80211 interface + * struct brcmf_cfg80211_info - dongle private data of cfg80211 interface * * @wdev: representing wl cfg80211 device. * @conf: dongle configuration. @@ -424,7 +424,7 @@ struct brcmf_pno_scanresults_le { * @ap_info: host ap information. * @ci: used to link this structure to netdev private data. */ -struct brcmf_cfg80211_priv { +struct brcmf_cfg80211_info { struct wireless_dev *wdev; struct brcmf_cfg80211_conf *conf; struct cfg80211_scan_request *scan_request; @@ -466,49 +466,49 @@ struct brcmf_cfg80211_priv { struct ap_info *ap_info; }; -static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_priv *w) +static inline struct wiphy *cfg_to_wiphy(struct brcmf_cfg80211_info *w) { return w->wdev->wiphy; } -static inline struct brcmf_cfg80211_priv *wiphy_to_cfg(struct wiphy *w) +static inline struct brcmf_cfg80211_info *wiphy_to_cfg(struct wiphy *w) { - return (struct brcmf_cfg80211_priv *)(wiphy_priv(w)); + return (struct brcmf_cfg80211_info *)(wiphy_priv(w)); } -static inline struct brcmf_cfg80211_priv *wdev_to_cfg(struct wireless_dev *wd) +static inline struct brcmf_cfg80211_info *wdev_to_cfg(struct wireless_dev *wd) { - return (struct brcmf_cfg80211_priv *)(wdev_priv(wd)); + return (struct brcmf_cfg80211_info *)(wdev_priv(wd)); } -static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_priv *cfg) +static inline struct net_device *cfg_to_ndev(struct brcmf_cfg80211_info *cfg) { return cfg->wdev->netdev; } -static inline struct brcmf_cfg80211_priv *ndev_to_cfg(struct net_device *ndev) +static inline struct brcmf_cfg80211_info *ndev_to_cfg(struct net_device *ndev) { return wdev_to_cfg(ndev->ieee80211_ptr); } -#define iscan_to_cfg(i) ((struct brcmf_cfg80211_priv *)(i->data)) +#define iscan_to_cfg(i) ((struct brcmf_cfg80211_info *)(i->data)) #define cfg_to_iscan(w) (w->iscan) static inline struct -brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_priv *cfg) +brcmf_cfg80211_connect_info *cfg_to_conn(struct brcmf_cfg80211_info *cfg) { return &cfg->conn_info; } -struct brcmf_cfg80211_priv *brcmf_cfg80211_attach(struct net_device *ndev, +struct brcmf_cfg80211_info *brcmf_cfg80211_attach(struct net_device *ndev, struct device *busdev, struct brcmf_pub *drvr); -void brcmf_cfg80211_detach(struct brcmf_cfg80211_priv *cfg_priv); +void brcmf_cfg80211_detach(struct brcmf_cfg80211_info *cfg); /* event handler from dongle */ void brcmf_cfg80211_event(struct net_device *ndev, const struct brcmf_event_msg *e, void *data); -s32 brcmf_cfg80211_up(struct brcmf_cfg80211_priv *cfg_priv); -s32 brcmf_cfg80211_down(struct brcmf_cfg80211_priv *cfg_priv); +s32 brcmf_cfg80211_up(struct brcmf_cfg80211_info *cfg); +s32 brcmf_cfg80211_down(struct brcmf_cfg80211_info *cfg); #endif /* _wl_cfg80211_h_ */ From 06bb123e5994351a158ce3daa4b19f9cc1486c9d Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 27 Sep 2012 14:17:56 +0200 Subject: [PATCH 68/73] brcmfmac: remove brcmf_read_prof() function The function brcmf_read_prof() provided access to fields with brcmf_cfg80211_profile structure using a field id, but the calling function can easily access that structure directly. This patch removes the function. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 49 +++++++++---------- 1 file changed, 22 insertions(+), 27 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index a0125d57c6c1..53c17f9e094f 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1283,20 +1283,6 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } -static void *brcmf_read_prof(struct brcmf_cfg80211_info *cfg, s32 item) -{ - switch (item) { - case WL_PROF_SEC: - return &cfg->profile->sec; - case WL_PROF_BSSID: - return &cfg->profile->bssid; - case WL_PROF_SSID: - return &cfg->profile->ssid; - } - WL_ERR("invalid item (%d)\n", item); - return NULL; -} - static s32 brcmf_update_prof(struct brcmf_cfg80211_info *cfg, const struct brcmf_event_msg *e, void *data, s32 item) @@ -1555,6 +1541,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1571,7 +1558,7 @@ static s32 brcmf_set_wpa_version(struct net_device *ndev, WL_ERR("set wpa_auth failed (%d)\n", err); return err; } - sec = brcmf_read_prof(cfg, WL_PROF_SEC); + sec = &profile->sec; sec->wpa_versions = sme->crypto.wpa_versions; return err; } @@ -1580,6 +1567,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1610,7 +1598,7 @@ static s32 brcmf_set_auth_type(struct net_device *ndev, WL_ERR("set auth failed (%d)\n", err); return err; } - sec = brcmf_read_prof(cfg, WL_PROF_SEC); + sec = &profile->sec; sec->auth_type = sme->auth_type; return err; } @@ -1620,6 +1608,7 @@ brcmf_set_set_cipher(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_security *sec; s32 pval = 0; s32 gval = 0; @@ -1675,7 +1664,7 @@ brcmf_set_set_cipher(struct net_device *ndev, return err; } - sec = brcmf_read_prof(cfg, WL_PROF_SEC); + sec = &profile->sec; sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0]; sec->cipher_group = sme->crypto.cipher_group; @@ -1686,6 +1675,7 @@ static s32 brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_security *sec; s32 val = 0; s32 err = 0; @@ -1731,7 +1721,7 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) return err; } } - sec = brcmf_read_prof(cfg, WL_PROF_SEC); + sec = &profile->sec; sec->wpa_auth = sme->crypto.akm_suites[0]; return err; @@ -1742,6 +1732,7 @@ brcmf_set_sharedkey(struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = ndev_to_cfg(ndev); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_security *sec; struct brcmf_wsec_key key; s32 val; @@ -1753,7 +1744,7 @@ brcmf_set_sharedkey(struct net_device *ndev, if (sme->key_len == 0) return 0; - sec = brcmf_read_prof(cfg, WL_PROF_SEC); + sec = &profile->sec; WL_CONN("wpa_versions 0x%x cipher_pairwise 0x%x\n", sec->wpa_versions, sec->cipher_pairwise); @@ -1901,6 +1892,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, u16 reason_code) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_scb_val_le scbval; s32 err = 0; @@ -1910,7 +1902,7 @@ brcmf_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *ndev, clear_bit(WL_STATUS_CONNECTED, &cfg->status); - memcpy(&scbval.ea, brcmf_read_prof(cfg, WL_PROF_BSSID), ETH_ALEN); + memcpy(&scbval.ea, &profile->bssid, ETH_ALEN); scbval.val = cpu_to_le32(reason_code); err = brcmf_exec_dcmd(ndev, BRCMF_C_DISASSOC, &scbval, sizeof(struct brcmf_scb_val_le)); @@ -2262,6 +2254,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, { struct key_params params; struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_security *sec; s32 wsec; s32 err = 0; @@ -2284,7 +2277,7 @@ brcmf_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev, } switch (wsec & ~SES_OW_ENABLED) { case WEP_ENABLED: - sec = brcmf_read_prof(cfg, WL_PROF_SEC); + sec = &profile->sec; if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) { params.cipher = WLAN_CIPHER_SUITE_WEP40; WL_CONN("WLAN_CIPHER_SUITE_WEP40\n"); @@ -2327,11 +2320,12 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev, u8 *mac, struct station_info *sinfo) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_scb_val_le scb_val; int rssi; s32 rate; s32 err = 0; - u8 *bssid = brcmf_read_prof(cfg, WL_PROF_BSSID); + u8 *bssid = profile->bssid; struct brcmf_sta_info_le *sta_info_le; WL_TRACE("Enter, MAC %pM\n", mac); @@ -2735,6 +2729,7 @@ brcmf_find_wpaie(u8 *parse, u32 len) static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) { + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_bss_info_le *bi; struct brcmf_ssid *ssid; struct brcmf_tlv *tim; @@ -2748,7 +2743,7 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) if (brcmf_is_ibssmode(cfg)) return err; - ssid = (struct brcmf_ssid *)brcmf_read_prof(cfg, WL_PROF_SSID); + ssid = &profile->ssid; *(__le32 *)cfg->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX); err = brcmf_exec_dcmd(cfg_to_ndev(cfg), BRCMF_C_GET_BSS_INFO, @@ -4648,6 +4643,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e) { + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); struct wiphy *wiphy = cfg_to_wiphy(cfg); struct brcmf_channel_info_le channel_le; @@ -4677,8 +4673,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, freq = ieee80211_channel_to_frequency(target_channel, band->band); notify_channel = ieee80211_get_channel(wiphy, freq); - cfg80211_roamed(ndev, notify_channel, - (u8 *)brcmf_read_prof(cfg, WL_PROF_BSSID), + cfg80211_roamed(ndev, notify_channel, (u8 *)profile->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL); WL_CONN("Report roaming result\n"); @@ -4693,6 +4688,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, bool completed) { + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_cfg80211_connect_info *conn_info = cfg_to_conn(cfg); s32 err = 0; @@ -4706,8 +4702,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, brcmf_update_bss_info(cfg); } cfg80211_connect_result(ndev, - (u8 *)brcmf_read_prof(cfg, - WL_PROF_BSSID), + (u8 *)profile->bssid, conn_info->req_ie, conn_info->req_ie_len, conn_info->resp_ie, From 6c8c4f7299b89ef369fd332e5f76c2fd23a62abe Mon Sep 17 00:00:00 2001 From: Arend van Spriel Date: Thu, 27 Sep 2012 14:17:57 +0200 Subject: [PATCH 69/73] brcmfmac: remove brcmf_update_prof() function The function brcmf_update_prof() only add complexity that is not needed. Reviewed-by: Hante Meuleman Reviewed-by: Pieter-Paul Giesberts Signed-off-by: Arend van Spriel Signed-off-by: John W. Linville --- .../wireless/brcm80211/brcmfmac/wl_cfg80211.c | 81 +++++-------------- 1 file changed, 19 insertions(+), 62 deletions(-) diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 53c17f9e094f..eca71b354736 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -1283,47 +1283,6 @@ static s32 brcmf_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) return err; } -static s32 -brcmf_update_prof(struct brcmf_cfg80211_info *cfg, - const struct brcmf_event_msg *e, void *data, s32 item) -{ - s32 err = 0; - struct brcmf_ssid *ssid; - - switch (item) { - case WL_PROF_SSID: - ssid = (struct brcmf_ssid *) data; - memset(cfg->profile->ssid.SSID, 0, - sizeof(cfg->profile->ssid.SSID)); - memcpy(cfg->profile->ssid.SSID, - ssid->SSID, ssid->SSID_len); - cfg->profile->ssid.SSID_len = ssid->SSID_len; - break; - case WL_PROF_BSSID: - if (data) - memcpy(cfg->profile->bssid, data, ETH_ALEN); - else - memset(cfg->profile->bssid, 0, ETH_ALEN); - break; - case WL_PROF_SEC: - memcpy(&cfg->profile->sec, data, - sizeof(cfg->profile->sec)); - break; - case WL_PROF_BEACONINT: - cfg->profile->beacon_interval = *(u16 *)data; - break; - case WL_PROF_DTIMPERIOD: - cfg->profile->dtim_period = *(u8 *)data; - break; - default: - WL_ERR("unsupported item (%d)\n", item); - err = -EOPNOTSUPP; - break; - } - - return err; -} - static void brcmf_init_prof(struct brcmf_cfg80211_profile *prof) { memset(prof, 0, sizeof(*prof)); @@ -1379,12 +1338,12 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_ibss_params *params) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct brcmf_join_params join_params; size_t join_params_size = 0; s32 err = 0; s32 wsec = 0; s32 bcnprd; - struct brcmf_ssid ssid; WL_TRACE("Enter\n"); if (!check_sys_up(wiphy)) @@ -1460,25 +1419,23 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev, memset(&join_params, 0, sizeof(struct brcmf_join_params)); /* SSID */ - ssid.SSID_len = min_t(u32, params->ssid_len, 32); - memcpy(ssid.SSID, params->ssid, ssid.SSID_len); - memcpy(join_params.ssid_le.SSID, params->ssid, ssid.SSID_len); - join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); + profile->ssid.SSID_len = min_t(u32, params->ssid_len, 32); + memcpy(profile->ssid.SSID, params->ssid, profile->ssid.SSID_len); + memcpy(join_params.ssid_le.SSID, params->ssid, profile->ssid.SSID_len); + join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); join_params_size = sizeof(join_params.ssid_le); - brcmf_update_prof(cfg, NULL, &ssid, WL_PROF_SSID); /* BSSID */ if (params->bssid) { memcpy(join_params.params_le.bssid, params->bssid, ETH_ALEN); join_params_size = sizeof(join_params.ssid_le) + BRCMF_ASSOC_PARAMS_FIXED_SIZE; + memcpy(profile->bssid, params->bssid, ETH_ALEN); } else { memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); + memset(profile->bssid, 0, ETH_ALEN); } - brcmf_update_prof(cfg, NULL, - &join_params.params_le.bssid, WL_PROF_BSSID); - /* Channel */ if (params->channel) { u32 target_channel; @@ -1800,6 +1757,7 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, struct cfg80211_connect_params *sme) { struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_profile *profile = cfg->profile; struct ieee80211_channel *chan = sme->channel; struct brcmf_join_params join_params; size_t join_params_size; @@ -1861,11 +1819,11 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, memset(&join_params, 0, sizeof(join_params)); join_params_size = sizeof(join_params.ssid_le); - ssid.SSID_len = min_t(u32, sizeof(ssid.SSID), (u32)sme->ssid_len); - memcpy(&join_params.ssid_le.SSID, sme->ssid, ssid.SSID_len); - memcpy(&ssid.SSID, sme->ssid, ssid.SSID_len); - join_params.ssid_le.SSID_len = cpu_to_le32(ssid.SSID_len); - brcmf_update_prof(cfg, NULL, &ssid, WL_PROF_SSID); + profile->ssid.SSID_len = min_t(u32, + sizeof(ssid.SSID), (u32)sme->ssid_len); + memcpy(&join_params.ssid_le.SSID, sme->ssid, profile->ssid.SSID_len); + memcpy(&profile->ssid.SSID, sme->ssid, profile->ssid.SSID_len); + join_params.ssid_le.SSID_len = cpu_to_le32(profile->ssid.SSID_len); memcpy(join_params.params_le.bssid, ether_bcast, ETH_ALEN); @@ -2781,8 +2739,8 @@ static s32 brcmf_update_bss_info(struct brcmf_cfg80211_info *cfg) dtim_period = (u8)var; } - brcmf_update_prof(cfg, NULL, &beacon_interval, WL_PROF_BEACONINT); - brcmf_update_prof(cfg, NULL, &dtim_period, WL_PROF_DTIMPERIOD); + profile->beacon_interval = beacon_interval; + profile->dtim_period = dtim_period; update_bss_info_out: WL_TRACE("Exit"); @@ -4656,7 +4614,7 @@ brcmf_bss_roaming_done(struct brcmf_cfg80211_info *cfg, WL_TRACE("Enter\n"); brcmf_get_assoc_ies(cfg); - brcmf_update_prof(cfg, NULL, &e->addr, WL_PROF_BSSID); + memcpy(profile->bssid, e->addr, ETH_ALEN); brcmf_update_bss_info(cfg); brcmf_exec_dcmd(ndev, BRCMF_C_GET_CHANNEL, &channel_le, @@ -4697,8 +4655,7 @@ brcmf_bss_connect_done(struct brcmf_cfg80211_info *cfg, if (test_and_clear_bit(WL_STATUS_CONNECTING, &cfg->status)) { if (completed) { brcmf_get_assoc_ies(cfg); - brcmf_update_prof(cfg, NULL, &e->addr, - WL_PROF_BSSID); + memcpy(profile->bssid, e->addr, ETH_ALEN); brcmf_update_bss_info(cfg); } cfg80211_connect_result(ndev, @@ -4763,6 +4720,7 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, struct net_device *ndev, const struct brcmf_event_msg *e, void *data) { + struct brcmf_cfg80211_profile *profile = cfg->profile; s32 err = 0; if (cfg->conf->mode == WL_MODE_AP) { @@ -4770,8 +4728,7 @@ brcmf_notify_connect_status(struct brcmf_cfg80211_info *cfg, } else if (brcmf_is_linkup(cfg, e)) { WL_CONN("Linkup\n"); if (brcmf_is_ibssmode(cfg)) { - brcmf_update_prof(cfg, NULL, (void *)e->addr, - WL_PROF_BSSID); + memcpy(profile->bssid, e->addr, ETH_ALEN); wl_inform_ibss(cfg, ndev, e->addr); cfg80211_ibss_joined(ndev, e->addr, GFP_KERNEL); clear_bit(WL_STATUS_CONNECTING, &cfg->status); From ff9bd2d8d95aedb661714536cb919281540f9772 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Thu, 27 Sep 2012 16:41:02 +0200 Subject: [PATCH 70/73] ath9k_hw: Handle AR_INTR_SYNC_HOST1_(FATAL|PERR) on AR9003 Interrupts with the sync_cause AR_INTR_SYNC_HOST1_FATAL and AR_INTR_SYNC_HOST1_PERR have to be handled using a chip reset. Otherwise a interrupt storm with unhandled interrupts will cause a hang or crash of the machine. Signed-off-by: Sven Eckelmann Signed-off-by: Simon Wunderlich Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/ar9003_mac.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c index d5b2e0ecc21c..301bf72c53bf 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c @@ -182,6 +182,7 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) struct ath9k_hw_capabilities *pCap = &ah->caps; struct ath_common *common = ath9k_hw_common(ah); u32 sync_cause = 0, async_cause, async_mask = AR_INTR_MAC_IRQ; + bool fatal_int; if (ath9k_hw_mci_is_enabled(ah)) async_mask |= AR_INTR_ASYNC_MASK_MCI; @@ -310,6 +311,22 @@ static bool ar9003_hw_get_isr(struct ath_hw *ah, enum ath9k_int *masked) if (sync_cause) { ath9k_debug_sync_cause(common, sync_cause); + fatal_int = + (sync_cause & + (AR_INTR_SYNC_HOST1_FATAL | AR_INTR_SYNC_HOST1_PERR)) + ? true : false; + + if (fatal_int) { + if (sync_cause & AR_INTR_SYNC_HOST1_FATAL) { + ath_dbg(common, ANY, + "received PCI FATAL interrupt\n"); + } + if (sync_cause & AR_INTR_SYNC_HOST1_PERR) { + ath_dbg(common, ANY, + "received PCI PERR interrupt\n"); + } + *masked |= ATH9K_INT_FATAL; + } if (sync_cause & AR_INTR_SYNC_RADM_CPL_TIMEOUT) { REG_WRITE(ah, AR_RC, AR_RC_HOSTIF); From 2db96c3d0a1f716fc90451cc2ed13842471f4658 Mon Sep 17 00:00:00 2001 From: Avinash Patil Date: Thu, 27 Sep 2012 19:00:10 -0700 Subject: [PATCH 71/73] mwifiex: enhance RX reordering to avoid packet drop during host sleep Once hostsleep is activated, this patch takes care of not dropping packets in RX reorder table. Signed-off-by: Avinash Patil Signed-off-by: Bing Zhao Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/11n_rxreorder.c | 49 ++++++++++++++++---- drivers/net/wireless/mwifiex/11n_rxreorder.h | 5 ++ drivers/net/wireless/mwifiex/cmdevt.c | 2 + drivers/net/wireless/mwifiex/main.h | 1 + 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 24e2582b467c..9402b93b9a36 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c @@ -302,6 +302,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, new_node->start_win = last_seq + 1; new_node->win_size = win_size; + new_node->flags = 0; new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, GFP_KERNEL); @@ -457,13 +458,20 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, * If seq_num is less then starting win then ignore and drop the * packet */ - if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) {/* Wrap */ - if (seq_num >= ((start_win + TWOPOW11) & - (MAX_TID_VALUE - 1)) && (seq_num < start_win)) + if (tbl->flags & RXREOR_FORCE_NO_DROP) { + dev_dbg(priv->adapter->dev, + "RXREOR_FORCE_NO_DROP when HS is activated\n"); + tbl->flags &= ~RXREOR_FORCE_NO_DROP; + } else { + if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { + if (seq_num >= ((start_win + TWOPOW11) & + (MAX_TID_VALUE - 1)) && + seq_num < start_win) + return -1; + } else if ((seq_num < start_win) || + (seq_num > (start_win + TWOPOW11))) { return -1; - } else if ((seq_num < start_win) || - (seq_num > (start_win + TWOPOW11))) { - return -1; + } } /* @@ -474,8 +482,7 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); if (((end_win < start_win) && - (seq_num < (TWOPOW11 - (MAX_TID_VALUE - start_win))) && - (seq_num > end_win)) || + (seq_num < start_win) && (seq_num > end_win)) || ((end_win > start_win) && ((seq_num > end_win) || (seq_num < start_win)))) { end_win = seq_num; @@ -637,3 +644,29 @@ void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); mwifiex_reset_11n_rx_seq_num(priv); } + +/* + * This function updates all rx_reorder_tbl's flags. + */ +void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags) +{ + struct mwifiex_private *priv; + struct mwifiex_rx_reorder_tbl *tbl; + unsigned long lock_flags; + int i; + + for (i = 0; i < adapter->priv_num; i++) { + priv = adapter->priv[i]; + if (!priv) + continue; + if (list_empty(&priv->rx_reorder_tbl_ptr)) + continue; + + spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags); + list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) + tbl->flags = flags; + spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags); + } + + return; +} diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 72848591691a..4064041ac852 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h @@ -41,6 +41,10 @@ #define BA_SETUP_MAX_PACKET_THRESHOLD 16 #define BA_SETUP_PACKET_OFFSET 16 +enum mwifiex_rxreor_flags { + RXREOR_FORCE_NO_DROP = 1<<0, +}; + static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) { memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq)); @@ -73,5 +77,6 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct struct mwifiex_rx_reorder_tbl * mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta); void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta); +void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags); #endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c index 225c1a4feeba..8d465107f52b 100644 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ b/drivers/net/wireless/mwifiex/cmdevt.c @@ -1088,6 +1088,8 @@ mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) if (activated) { if (priv->adapter->is_hs_configured) { priv->adapter->hs_activated = true; + mwifiex_update_rxreor_flags(priv->adapter, + RXREOR_FORCE_NO_DROP); dev_dbg(priv->adapter->dev, "event: hs_activated\n"); priv->adapter->hs_activate_wait_q_woken = true; wake_up_interruptible( diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index 956312f45e60..bfb3fa69805c 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h @@ -535,6 +535,7 @@ struct mwifiex_rx_reorder_tbl { int win_size; void **rx_reorder_ptr; struct reorder_tmr_cnxt timer_context; + u8 flags; }; struct mwifiex_bss_prio_node { From 5570a914f28f58de6839a4d532e98eb8167bd57d Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 28 Sep 2012 12:59:43 +0800 Subject: [PATCH 72/73] mwifiex: convert to use le16_add_cpu() Convert cpu_to_le16(le16_to_cpu(E1) + E2) to use le16_add_cpu(). dpatch engine is used to auto generate this patch. (https://github.com/weiyj/dpatch) Signed-off-by: Wei Yongjun Signed-off-by: John W. Linville --- drivers/net/wireless/mwifiex/scan.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index 9e077e5fc64a..e36a75988f87 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c @@ -614,9 +614,8 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv, /* Increment the TLV header length by the size appended */ - chan_tlv_out->header.len = - cpu_to_le16(le16_to_cpu(chan_tlv_out->header.len) + - (sizeof(chan_tlv_out->chan_scan_param))); + le16_add_cpu(&chan_tlv_out->header.len, + sizeof(chan_tlv_out->chan_scan_param)); /* * The tlv buffer length is set to the number of bytes From 5160b46f3e53c41c4c6b9e7cdbe0401d3afbfb63 Mon Sep 17 00:00:00 2001 From: Sujith Manoharan Date: Fri, 28 Sep 2012 11:13:51 +0530 Subject: [PATCH 73/73] ath9k: Fix BTCOEX weight initialization The WLAN/BT weights have to set correctly before BTCOEX is initialized. Currently, this is not done for all chips in the AR9003 family. This patch fixes this issue by setting the weights in the init path. While at it, rename ar9462_wlan_weights to mci_wlan_weights since it is common to both AR9462 and AR9565. Signed-off-by: Sujith Manoharan Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ath9k/btcoex.c | 61 ++++++++++--------- drivers/net/wireless/ath/ath9k/btcoex.h | 3 +- drivers/net/wireless/ath/ath9k/gpio.c | 5 +- drivers/net/wireless/ath/ath9k/htc_drv_gpio.c | 2 +- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/ath/ath9k/btcoex.c b/drivers/net/wireless/ath/ath9k/btcoex.c index 4ef610e63fcb..419e9a3f2fed 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.c +++ b/drivers/net/wireless/ath/ath9k/btcoex.c @@ -43,8 +43,8 @@ static const u32 ar9003_wlan_weights[ATH_BTCOEX_STOMP_MAX] { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, /* STOMP_NONE */ }; -static const u32 ar9462_wlan_weights[ATH_BTCOEX_STOMP_MAX] - [AR9300_NUM_WLAN_WEIGHTS] = { +static const u32 mci_wlan_weights[ATH_BTCOEX_STOMP_MAX] + [AR9300_NUM_WLAN_WEIGHTS] = { { 0x01017d01, 0x41414101, 0x41414101, 0x41414141 }, /* STOMP_ALL */ { 0x01017d01, 0x3b3b3b01, 0x3b3b3b01, 0x3b3b3b3b }, /* STOMP_LOW */ { 0x01017d01, 0x01010101, 0x01010101, 0x01010101 }, /* STOMP_NONE */ @@ -208,14 +208,37 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah) AR_GPIO_OUTPUT_MUX_AS_TX_FRAME); } +/* + * For AR9002, bt_weight/wlan_weight are used. + * For AR9003 and above, stomp_type is used. + */ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, u32 bt_weight, - u32 wlan_weight) + u32 wlan_weight, + enum ath_stomp_type stomp_type) { struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw; - btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) | - SM(wlan_weight, AR_BTCOEX_WL_WGHT); + if (AR_SREV_9300_20_OR_LATER(ah)) { + const u32 *weight = ar9003_wlan_weights[stomp_type]; + int i; + + if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { + if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && + btcoex_hw->mci.stomp_ftp) + stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; + weight = mci_wlan_weights[stomp_type]; + } + + for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { + btcoex_hw->bt_weight[i] = AR9300_BT_WGHT; + btcoex_hw->wlan_weight[i] = weight[i]; + } + } else { + btcoex_hw->bt_coex_weights = + SM(bt_weight, AR_BTCOEX_BT_WGHT) | + SM(wlan_weight, AR_BTCOEX_WL_WGHT); + } } EXPORT_SYMBOL(ath9k_hw_btcoex_set_weight); @@ -332,26 +355,6 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah) } EXPORT_SYMBOL(ath9k_hw_btcoex_disable); -static void ar9003_btcoex_bt_stomp(struct ath_hw *ah, - enum ath_stomp_type stomp_type) -{ - struct ath_btcoex_hw *btcoex = &ah->btcoex_hw; - const u32 *weight = ar9003_wlan_weights[stomp_type]; - int i; - - if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) { - if ((stomp_type == ATH_BTCOEX_STOMP_LOW) && - btcoex->mci.stomp_ftp) - stomp_type = ATH_BTCOEX_STOMP_LOW_FTP; - weight = ar9462_wlan_weights[stomp_type]; - } - - for (i = 0; i < AR9300_NUM_WLAN_WEIGHTS; i++) { - btcoex->bt_weight[i] = AR9300_BT_WGHT; - btcoex->wlan_weight[i] = weight[i]; - } -} - /* * Configures appropriate weight based on stomp type. */ @@ -359,22 +362,22 @@ void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, enum ath_stomp_type stomp_type) { if (AR_SREV_9300_20_OR_LATER(ah)) { - ar9003_btcoex_bt_stomp(ah, stomp_type); + ath9k_hw_btcoex_set_weight(ah, 0, 0, stomp_type); return; } switch (stomp_type) { case ATH_BTCOEX_STOMP_ALL: ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_ALL_WLAN_WGHT); + AR_STOMP_ALL_WLAN_WGHT, 0); break; case ATH_BTCOEX_STOMP_LOW: ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); + AR_STOMP_LOW_WLAN_WGHT, 0); break; case ATH_BTCOEX_STOMP_NONE: ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_NONE_WLAN_WGHT); + AR_STOMP_NONE_WLAN_WGHT, 0); break; default: ath_dbg(ath9k_hw_common(ah), BTCOEX, "Invalid Stomptype\n"); diff --git a/drivers/net/wireless/ath/ath9k/btcoex.h b/drivers/net/wireless/ath/ath9k/btcoex.h index 20092f98658f..385197ad79b0 100644 --- a/drivers/net/wireless/ath/ath9k/btcoex.h +++ b/drivers/net/wireless/ath/ath9k/btcoex.h @@ -107,7 +107,8 @@ void ath9k_hw_btcoex_init_mci(struct ath_hw *ah); void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum); void ath9k_hw_btcoex_set_weight(struct ath_hw *ah, u32 bt_weight, - u32 wlan_weight); + u32 wlan_weight, + enum ath_stomp_type stomp_type); void ath9k_hw_btcoex_disable(struct ath_hw *ah); void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah, enum ath_stomp_type stomp_type); diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 5faa4f777122..d9ed141a053e 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -395,7 +395,10 @@ void ath9k_start_btcoex(struct ath_softc *sc) !ah->btcoex_hw.enabled) { if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); + AR_STOMP_LOW_WLAN_WGHT, 0); + else + ath9k_hw_btcoex_set_weight(ah, 0, 0, + ATH_BTCOEX_STOMP_NONE); ath9k_hw_btcoex_enable(ah); if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c index 8fd64a6f0eb9..0eacfc13c915 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c @@ -161,7 +161,7 @@ void ath9k_htc_start_btcoex(struct ath9k_htc_priv *priv) if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) { ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, - AR_STOMP_LOW_WLAN_WGHT); + AR_STOMP_LOW_WLAN_WGHT, 0); ath9k_hw_btcoex_enable(ah); ath_htc_resume_btcoex_work(priv); }