All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3
@ 2011-08-14 10:16 Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 01/40] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy" Eliad Peller
                   ` (40 more replies)
  0 siblings, 41 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:16 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

The new wl12xx fw (ver 7.3.0.0.75) had some major api changes.
The main change was the addition of multi-role concept, which
will later allow using multiple vifs concurrently.

Consequently, this design change caused api changes for most
of the api commands, as a new role_id had to be added.

This patchset migrates the fw to use the new fw api (a new
fw filename is used, as there is no backward compatability
with older firmwares).

Additional patchsets will follow, with further bugfixes
and new features (e.g. p2p support).

v2: apply Luca's comments, rebase.

Arik Nemtsov (17):
  wl12xx: Revert "wl12xx: schedule TX packets according to FW
    occupancy"
  wl12xx: Use a single fw for both STA and AP roles
  wl12xx: use 1 spare block in all cases
  wl12xx: handle dummy packet event also in ap mode
  wl12xx: fix session counter
  wl12xx: use dynamic hlids for AP-mode
  wl12xx: re-enable block ack session support
  wl12xx: AP-mode - set STA HT capabilities when adding a STA
  wl12xx: AP-mode - configure STA HT rates on join
  wl12xx: AP-mode - configure HT rate support to the FW
  wl12xx: track freed packets in FW by AC
  wl12xx: schedule TX packets according to FW packet occupancy
  wl12xx: handle wrap-around overflow in released Tx blocks FW counter
  wl12xx: enable AP advanced functionality
  wl12xx: set the AP-started flag only after setting keys
  wl12xx: AP-mode - prevent Tx to stale/invalid stations
  wl12xx: fix tx_queue_count spurious increment

Eliad Peller (23):
  wl12xx: temporarily disable advanced ap functions
  wl12xx: remove rx filtering stuff
  wl12xx: update fw status struct
  wl12xx: update acx commands
  wl12xx: update commands & events
  wl12xx: enable/disable role on interface add/remove
  wl12xx: add device role commands
  wl12xx: update scan cmd api
  wl12xx: update rx/tx
  wl12xx: change max/default template size
  wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap
  wl12xx: add set_rate_mgmt_params acx
  wl12xx: add system_hlid
  wl12xx: add ROC/CROC commands
  wl12xx: replace dummy_join with ROC/CROC commands
  wl12xx: update BT coex configuration params
  wl12xx: call wl12xx_cmd_set_peer_state() in AP mode
  wl12xx: don't remove key if hlid was already deleted
  wl12xx: add wl12xx_cmd_role_start_ibss()
  wl12xx: support IBSS vif type
  wl12xx: use ap_bcast_hlid for recorded keys
  wl12xx: don't remove key if hlid was already deleted
  wl12xx: don't wait for disconnection event

 drivers/net/wireless/wl12xx/acx.c          |  322 ++++------
 drivers/net/wireless/wl12xx/acx.h          |  394 ++++--------
 drivers/net/wireless/wl12xx/boot.c         |   30 +-
 drivers/net/wireless/wl12xx/cmd.c          |  793 +++++++++++++++++------
 drivers/net/wireless/wl12xx/cmd.h          |  329 ++++++-----
 drivers/net/wireless/wl12xx/conf.h         |  352 ++++------
 drivers/net/wireless/wl12xx/debugfs.c      |   17 +-
 drivers/net/wireless/wl12xx/event.c        |    6 +-
 drivers/net/wireless/wl12xx/event.h        |   80 +--
 drivers/net/wireless/wl12xx/init.c         |   91 +--
 drivers/net/wireless/wl12xx/io.h           |    1 -
 drivers/net/wireless/wl12xx/main.c         |  951 +++++++++++++++++-----------
 drivers/net/wireless/wl12xx/ps.c           |    4 +-
 drivers/net/wireless/wl12xx/reg.h          |   75 ---
 drivers/net/wireless/wl12xx/rx.c           |   23 +-
 drivers/net/wireless/wl12xx/rx.h           |   10 +-
 drivers/net/wireless/wl12xx/scan.c         |   38 +-
 drivers/net/wireless/wl12xx/scan.h         |   25 +-
 drivers/net/wireless/wl12xx/sdio.c         |    4 +-
 drivers/net/wireless/wl12xx/spi.c          |    2 -
 drivers/net/wireless/wl12xx/tx.c           |  136 +++--
 drivers/net/wireless/wl12xx/tx.h           |   16 +-
 drivers/net/wireless/wl12xx/wl12xx.h       |  153 +++---
 drivers/net/wireless/wl12xx/wl12xx_80211.h |   25 -
 24 files changed, 2034 insertions(+), 1843 deletions(-)

-- 
1.7.6.401.g6a319


^ permalink raw reply	[flat|nested] 42+ messages in thread

* [PATCH v2 01/40] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy"
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 02/40] wl12xx: Use a single fw for both STA and AP roles Eliad Peller
                   ` (39 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

This does not make sense in fw >= 6/7.3.0.0.75 (wl127x/wl128x) -
we don't use Tx blocks to measure FW occupancy anymore.

This reverts commit 9e374a37b6fa2310b71d3c5657cd0c1e693120c6.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/debugfs.c |    5 +--
 drivers/net/wireless/wl12xx/main.c    |   30 ++++-----------
 drivers/net/wireless/wl12xx/tx.c      |   68 +++++++++++----------------------
 drivers/net/wireless/wl12xx/wl12xx.h  |    2 +-
 4 files changed, 33 insertions(+), 72 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 37934b5..3b5f240 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -336,16 +336,13 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 #define DRIVER_STATE_PRINT_INT(x)  DRIVER_STATE_PRINT(x, "%d")
 #define DRIVER_STATE_PRINT_STR(x)  DRIVER_STATE_PRINT(x, "%s")
 #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
 #define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")
 
 	DRIVER_STATE_PRINT_INT(tx_blocks_available);
-	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[0]);
-	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[1]);
-	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[2]);
-	DRIVER_STATE_PRINT_INT(tx_allocated_blocks[3]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
 	DRIVER_STATE_PRINT_INT(tx_frames_cnt);
 	DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 98258fe..f91875e 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -821,30 +821,19 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
 
 		wl1271_irq_ps_regulate_link(wl, hlid,
 					    wl->links[hlid].allocated_blks);
 	}
 }
 
-static u32 wl1271_tx_allocated_blocks(struct wl1271 *wl)
-{
-	int i;
-	u32 total_alloc_blocks = 0;
-
-	for (i = 0; i < NUM_TX_QUEUES; i++)
-		total_alloc_blocks += wl->tx_allocated_blocks[i];
-
-	return total_alloc_blocks;
-}
-
 static void wl1271_fw_status(struct wl1271 *wl,
 			     struct wl1271_fw_full_status *full_status)
 {
 	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
 	u32 old_tx_blk_count = wl->tx_blocks_available;
-	u32 freed_blocks = 0, ac_freed_blocks;
+	u32 freed_blocks = 0;
 	int i;
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
 				sizeof(struct wl1271_fw_ap_status), false);
 	} else {
@@ -858,29 +847,27 @@ static void wl1271_fw_status(struct wl1271 *wl,
 		     status->fw_rx_counter,
 		     status->drv_rx_counter,
 		     status->tx_results_counter);
 
 	/* update number of available TX blocks */
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
-		ac_freed_blocks = le32_to_cpu(status->tx_released_blks[i]) -
-				  wl->tx_blocks_freed[i];
-		freed_blocks += ac_freed_blocks;
-
-		wl->tx_allocated_blocks[i] -= ac_freed_blocks;
+		freed_blocks += le32_to_cpu(status->tx_released_blks[i]) -
+				wl->tx_blocks_freed[i];
 
 		wl->tx_blocks_freed[i] =
 			le32_to_cpu(status->tx_released_blks[i]);
 	}
 
+	wl->tx_allocated_blocks -= freed_blocks;
+
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		/* Update num of allocated TX blocks per link and ps status */
 		wl1271_irq_update_links_status(wl, &full_status->ap);
 		wl->tx_blocks_available += freed_blocks;
 	} else {
-		int avail = full_status->sta.tx_total -
-			    wl1271_tx_allocated_blocks(wl);
+		int avail = full_status->sta.tx_total - wl->tx_allocated_blocks;
 
 		/*
 		 * The FW might change the total number of TX memblocks before
 		 * we get a notification about blocks being released. Thus, the
 		 * available blocks calculation might yield a temporary result
 		 * which is lower than the actual available blocks. Keeping in
@@ -2010,12 +1997,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	wl->band = IEEE80211_BAND_2GHZ;
 
 	wl->rx_counter = 0;
 	wl->psm_entry_retry = 0;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
 	wl->tx_blocks_available = 0;
+	wl->tx_allocated_blocks = 0;
 	wl->tx_results_count = 0;
 	wl->tx_packets_count = 0;
 	wl->time_offset = 0;
 	wl->session_counter = 0;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
 	wl->vif = NULL;
@@ -2030,16 +2018,14 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	 * this is performed after the cancel_work calls and the associated
 	 * mutex_lock, so that wl1271_op_add_interface does not accidentally
 	 * get executed before all these vars have been reset.
 	 */
 	wl->flags = 0;
 
-	for (i = 0; i < NUM_TX_QUEUES; i++) {
+	for (i = 0; i < NUM_TX_QUEUES; i++)
 		wl->tx_blocks_freed[i] = 0;
-		wl->tx_allocated_blocks[i] = 0;
-	}
 
 	wl1271_debugfs_reset(wl);
 
 	kfree(wl->fw_status);
 	wl->fw_status = NULL;
 	kfree(wl->tx_res_if);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 48fde96..0696aed 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -165,13 +165,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 				u32 buf_offset, u8 hlid)
 {
 	struct wl1271_tx_hw_descr *desc;
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
 	u32 len;
 	u32 total_blocks;
-	int id, ret = -EBUSY, ac;
+	int id, ret = -EBUSY;
 	u32 spare_blocks;
 
 	if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
 		spare_blocks = 2;
 	else
 		spare_blocks = 1;
@@ -203,15 +203,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 			desc->wl127x_mem.total_mem_blocks = total_blocks;
 		}
 
 		desc->id = id;
 
 		wl->tx_blocks_available -= total_blocks;
-
-		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
-		wl->tx_allocated_blocks[ac] += total_blocks;
+		wl->tx_allocated_blocks += total_blocks;
 
 		if (wl->bss_type == BSS_TYPE_AP_BSS)
 			wl->links[hlid].allocated_blks += total_blocks;
 
 		ret = 0;
 
@@ -456,47 +454,27 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
 			clear_bit(i, &wl->stopped_queues_map);
 			spin_unlock_irqrestore(&wl->wl_lock, flags);
 		}
 	}
 }
 
-static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
-						struct sk_buff_head *queues)
-{
-	int i, q = -1;
-	u32 min_blks = 0xffffffff;
-
-	/*
-	 * Find a non-empty ac where:
-	 * 1. There are packets to transmit
-	 * 2. The FW has the least allocated blocks
-	 */
-	for (i = 0; i < NUM_TX_QUEUES; i++)
-		if (!skb_queue_empty(&queues[i]) &&
-		    (wl->tx_allocated_blocks[i] < min_blks)) {
-			q = i;
-			min_blks = wl->tx_allocated_blocks[q];
-		}
-
-	if (q == -1)
-		return NULL;
-
-	return &queues[q];
-}
-
 static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
-	struct sk_buff_head *queue;
 
-	queue = wl1271_select_queue(wl, wl->tx_queue);
-	if (!queue)
+	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
+	if (skb)
 		goto out;
-
-	skb = skb_dequeue(queue);
+	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
+	if (skb)
+		goto out;
+	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
+	if (skb)
+		goto out;
+	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);
 
 out:
 	if (skb) {
 		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		spin_lock_irqsave(&wl->wl_lock, flags);
 		wl->tx_queue_count[q]--;
@@ -508,35 +486,35 @@ out:
 
 static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
 	int i, h, start_hlid;
-	struct sk_buff_head *queue;
 
 	/* start from the link after the last one */
 	start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
 
 	/* dequeue according to AC, round robin on each link */
 	for (i = 0; i < AP_MAX_LINKS; i++) {
 		h = (start_hlid + i) % AP_MAX_LINKS;
 
-		/* only consider connected stations */
-		if (h >= WL1271_AP_STA_HLID_START &&
-		    !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
-			continue;
-
-		queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
-		if (!queue)
-			continue;
-
-		skb = skb_dequeue(queue);
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
 		if (skb)
-			break;
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+		if (skb)
+			goto out;
 	}
 
+out:
 	if (skb) {
 		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		wl->last_tx_hlid = h;
 		spin_lock_irqsave(&wl->wl_lock, flags);
 		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 0bc2935..5b00a84 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -421,13 +421,13 @@ struct wl1271 {
 
 	struct wl1271_acx_mem_map *target_mem_map;
 
 	/* Accounting for allocated / available TX blocks on HW */
 	u32 tx_blocks_freed[NUM_TX_QUEUES];
 	u32 tx_blocks_available;
-	u32 tx_allocated_blocks[NUM_TX_QUEUES];
+	u32 tx_allocated_blocks;
 	u32 tx_results_count;
 
 	/* Transmitted TX packets counter for chipset interface */
 	u32 tx_packets_count;
 
 	/* Time-offset between host and chipset clocks */
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 02/40] wl12xx: Use a single fw for both STA and AP roles
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 01/40] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy" Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 03/40] wl12xx: use 1 spare block in all cases Eliad Peller
                   ` (38 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Firmware >= 6/7.3.0.0.75 (wl127x/wl128x) supports both
STA and AP roles.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: s/WL1271/WL127X

 drivers/net/wireless/wl12xx/main.c   |   31 +++++--------------------------
 drivers/net/wireless/wl12xx/sdio.c   |    4 +---
 drivers/net/wireless/wl12xx/spi.c    |    2 --
 drivers/net/wireless/wl12xx/wl12xx.h |    7 ++-----
 4 files changed, 8 insertions(+), 36 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index f91875e..7b29573 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1040,31 +1040,16 @@ EXPORT_SYMBOL_GPL(wl1271_irq);
 static int wl1271_fetch_firmware(struct wl1271 *wl)
 {
 	const struct firmware *fw;
 	const char *fw_name;
 	int ret;
 
-	switch (wl->bss_type) {
-	case BSS_TYPE_AP_BSS:
-		if (wl->chip.id == CHIP_ID_1283_PG20)
-			fw_name = WL128X_AP_FW_NAME;
-		else
-			fw_name = WL127X_AP_FW_NAME;
-		break;
-	case BSS_TYPE_IBSS:
-	case BSS_TYPE_STA_BSS:
-		if (wl->chip.id == CHIP_ID_1283_PG20)
-			fw_name = WL128X_FW_NAME;
-		else
-			fw_name	= WL1271_FW_NAME;
-		break;
-	default:
-		wl1271_error("no compatible firmware for bss_type %d",
-			     wl->bss_type);
-		return -EINVAL;
-	}
+	if (wl->chip.id == CHIP_ID_1283_PG20)
+		fw_name = WL128X_FW_NAME;
+	else
+		fw_name	= WL127X_FW_NAME;
 
 	wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name);
 
 	ret = request_firmware(&fw, fw_name, wl1271_wl_to_dev(wl));
 
 	if (ret < 0) {
@@ -1087,13 +1072,12 @@ static int wl1271_fetch_firmware(struct wl1271 *wl)
 		wl1271_error("could not allocate memory for the firmware");
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	memcpy(wl->fw, fw->data, wl->fw_len);
-	wl->fw_bss_type = wl->bss_type;
 	ret = 0;
 
 out:
 	release_firmware(fw);
 
 	return ret;
@@ -1358,14 +1342,13 @@ static int wl1271_chip_wakeup(struct wl1271 *wl)
 	default:
 		wl1271_warning("unsupported chip id: 0x%x", wl->chip.id);
 		ret = -ENODEV;
 		goto out;
 	}
 
-	/* Make sure the firmware type matches the BSS type */
-	if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) {
+	if (wl->fw == NULL) {
 		ret = wl1271_fetch_firmware(wl);
 		if (ret < 0)
 			goto out;
 	}
 
 	/* No NVS from netlink, try to get it from the filesystem */
@@ -1793,15 +1776,12 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
 	 * initializing the firmware. The MAC address cannot be changed
 	 * after boot, and without the proper MAC address, the firmware
 	 * will not function properly.
 	 *
 	 * The MAC address is first known when the corresponding interface
 	 * is added. That is where we will initialize the hardware.
-	 *
-	 * In addition, we currently have different firmwares for AP and managed
-	 * operation. We will know which to boot according to interface type.
 	 */
 
 	return 0;
 }
 
 static void wl1271_op_stop(struct ieee80211_hw *hw)
@@ -4390,13 +4370,12 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->vif = NULL;
 	wl->flags = 0;
 	wl->sg_enabled = true;
 	wl->hw_pg_ver = -1;
 	wl->bss_type = MAX_BSS_TYPE;
 	wl->set_bss_type = MAX_BSS_TYPE;
-	wl->fw_bss_type = MAX_BSS_TYPE;
 	wl->last_tx_hlid = 0;
 	wl->ap_ps_map = 0;
 	wl->ap_fw_ps_map = 0;
 	wl->quirks = 0;
 	wl->platform_quirks = 0;
 	wl->sched_scanning = false;
diff --git a/drivers/net/wireless/wl12xx/sdio.c b/drivers/net/wireless/wl12xx/sdio.c
index 5cf18c2..ac2e566 100644
--- a/drivers/net/wireless/wl12xx/sdio.c
+++ b/drivers/net/wireless/wl12xx/sdio.c
@@ -409,10 +409,8 @@ static void __exit wl1271_exit(void)
 module_init(wl1271_init);
 module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
-MODULE_FIRMWARE(WL1271_FW_NAME);
+MODULE_FIRMWARE(WL127X_FW_NAME);
 MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL127X_AP_FW_NAME);
-MODULE_FIRMWARE(WL128X_AP_FW_NAME);
diff --git a/drivers/net/wireless/wl12xx/spi.c b/drivers/net/wireless/wl12xx/spi.c
index e0b3736..7314795 100644
--- a/drivers/net/wireless/wl12xx/spi.c
+++ b/drivers/net/wireless/wl12xx/spi.c
@@ -485,9 +485,7 @@ module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 MODULE_FIRMWARE(WL1271_FW_NAME);
 MODULE_FIRMWARE(WL128X_FW_NAME);
-MODULE_FIRMWARE(WL127X_AP_FW_NAME);
-MODULE_FIRMWARE(WL128X_AP_FW_NAME);
 MODULE_ALIAS("spi:wl1271");
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 5b00a84..dc0013e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -127,16 +127,14 @@ extern u32 wl12xx_debug_level;
 				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
 				  CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
 				  CFG_RX_ASSOC_EN)
 
 
 
-#define WL1271_FW_NAME "ti-connectivity/wl1271-fw-2.bin"
-#define WL128X_FW_NAME "ti-connectivity/wl128x-fw.bin"
-#define WL127X_AP_FW_NAME "ti-connectivity/wl1271-fw-ap.bin"
-#define WL128X_AP_FW_NAME "ti-connectivity/wl128x-fw-ap.bin"
+#define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
+#define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
 
 /*
  * wl127x and wl128x are using the same NVS file name. However, the
  * ini parameters between them are different.  The driver validates
  * the correct NVS size in wl1271_boot_upload_nvs().
  */
@@ -402,13 +400,12 @@ struct wl1271 {
 
 	int cmd_box_addr;
 	int event_box_addr;
 
 	u8 *fw;
 	size_t fw_len;
-	u8 fw_bss_type;
 	void *nvs;
 	size_t nvs_len;
 
 	s8 hw_pg_ver;
 
 	u8 bssid[ETH_ALEN];
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 03/40] wl12xx: use 1 spare block in all cases
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 01/40] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy" Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 02/40] wl12xx: Use a single fw for both STA and AP roles Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 04/40] wl12xx: temporarily disable advanced ap functions Eliad Peller
                   ` (37 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Remove support for firmwares that require 2 spare blocks for packet TX
(and delete the WL12XX_QUIRK_USE_2_SPARE_BLOCKS quirk definition)

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: delete WL12XX_QUIRK_USE_2_SPARE_BLOCKS

 drivers/net/wireless/wl12xx/boot.c   |   10 ----------
 drivers/net/wireless/wl12xx/tx.c     |    7 ++-----
 drivers/net/wireless/wl12xx/wl12xx.h |    6 ------
 3 files changed, 2 insertions(+), 21 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index a816f2f..930a638 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -104,22 +104,12 @@ static void wl1271_boot_set_ecpu_ctrl(struct wl1271 *wl, u32 flag)
 
 static unsigned int wl12xx_get_fw_ver_quirks(struct wl1271 *wl)
 {
 	unsigned int quirks = 0;
 	unsigned int *fw_ver = wl->chip.fw_ver;
 
-	/* Only for wl127x */
-	if ((fw_ver[FW_VER_CHIP] == FW_VER_CHIP_WL127X) &&
-	    /* Check STA version */
-	    (((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
-	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_STA_MIN)) ||
-	     /* Check AP version */
-	     ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_AP) &&
-	      (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_1_SPARE_AP_MIN))))
-		quirks |= WL12XX_QUIRK_USE_2_SPARE_BLOCKS;
-
 	/* Only new station firmwares support routing fw logs to the host */
 	if ((fw_ver[FW_VER_IF_TYPE] == FW_VER_IF_TYPE_STA) &&
 	    (fw_ver[FW_VER_MINOR] < FW_VER_MINOR_FWLOG_STA_MIN))
 		quirks |= WL12XX_QUIRK_FWLOG_NOT_IMPLEMENTED;
 
 	/* This feature is not yet supported for AP mode */
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 0696aed..c67340f 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -166,18 +166,15 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 {
 	struct wl1271_tx_hw_descr *desc;
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
 	u32 len;
 	u32 total_blocks;
 	int id, ret = -EBUSY;
-	u32 spare_blocks;
 
-	if (unlikely(wl->quirks & WL12XX_QUIRK_USE_2_SPARE_BLOCKS))
-		spare_blocks = 2;
-	else
-		spare_blocks = 1;
+	/* we use 1 spare block */
+	u32 spare_blocks = 1;
 
 	if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
 		return -EAGAIN;
 
 	/* allocate free identifier for the packet */
 	id = wl1271_alloc_tx_id(wl, skb);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index dc0013e..0bdeae5 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -653,18 +653,12 @@ size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
 
 /* Quirks */
 
 /* Each RX/TX transaction requires an end-of-transaction transfer */
 #define WL12XX_QUIRK_END_OF_TRANSACTION		BIT(0)
 
-/*
- * Older firmwares use 2 spare TX blocks
- * (for STA < 6.1.3.50.58 or for AP < 6.2.0.0.47)
- */
-#define WL12XX_QUIRK_USE_2_SPARE_BLOCKS		BIT(1)
-
 /* WL128X requires aggregated packets to be aligned to the SDIO block size */
 #define WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT	BIT(2)
 
 /*
  * WL127X AP mode requires Low Power DRPw (LPD) enable to reduce power
  * consumption
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 04/40] wl12xx: temporarily disable advanced ap functions
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (2 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 03/40] wl12xx: use 1 spare block in all cases Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 05/40] wl12xx: remove rx filtering stuff Eliad Peller
                   ` (36 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

In order to keep to driver compiling during the patchset,
while avoiding one-huge-patch, temporarily disable some
advanced ap functions.

These changes will be reverted later in the patchset, as
part of the patches for advanced ap functions support.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: don't disable 11n

 drivers/net/wireless/wl12xx/main.c |    4 ++++
 drivers/net/wireless/wl12xx/tx.c   |    4 ++++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 7b29573..4fa7602 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -770,12 +770,13 @@ static int wl1271_plt_init(struct wl1271 *wl)
 	kfree(wl->target_mem_map);
 	wl->target_mem_map = NULL;
 
 	return ret;
 }
 
+#if 0
 static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
 {
 	bool fw_ps;
 
 	/* only regulate station links */
 	if (hlid < WL1271_AP_STA_HLID_START)
@@ -820,12 +821,13 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
 		wl->links[hlid].allocated_blks -= cnt;
 
 		wl1271_irq_ps_regulate_link(wl, hlid,
 					    wl->links[hlid].allocated_blks);
 	}
 }
+#endif
 
 static void wl1271_fw_status(struct wl1271 *wl,
 			     struct wl1271_fw_full_status *full_status)
 {
 	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
@@ -858,13 +860,15 @@ static void wl1271_fw_status(struct wl1271 *wl,
 	}
 
 	wl->tx_allocated_blocks -= freed_blocks;
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		/* Update num of allocated TX blocks per link and ps status */
+#if 0
 		wl1271_irq_update_links_status(wl, &full_status->ap);
+#endif
 		wl->tx_blocks_available += freed_blocks;
 	} else {
 		int avail = full_status->sta.tx_total - wl->tx_allocated_blocks;
 
 		/*
 		 * The FW might change the total number of TX memblocks before
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index c67340f..938af1d 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -108,12 +108,13 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
 	hdr = (struct ieee80211_hdr *)(skb->data +
 				       sizeof(struct wl1271_tx_hw_descr));
 	if (ieee80211_is_auth(hdr->frame_control))
 		wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
 }
 
+#if 0
 static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
 {
 	bool fw_ps;
 	u8 tx_blks;
 
 	/* only regulate station links */
@@ -127,12 +128,13 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
 	 * if in FW PS and there is enough data in FW we can put the link
 	 * into high-level PS and clean out its TX queues.
 	 */
 	if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
 		wl1271_ps_link_start(wl, hlid, true);
 }
+#endif
 
 u8 wl1271_tx_get_hlid(struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
 
 	if (control->control.sta) {
@@ -381,13 +383,15 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 		return ret;
 
 	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		wl1271_tx_ap_update_inconnection_sta(wl, skb);
+#if 0
 		wl1271_tx_regulate_link(wl, hlid);
+#endif
 	} else {
 		wl1271_tx_update_filters(wl, skb);
 	}
 
 	/*
 	 * The length of each packet is stored in terms of
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 05/40] wl12xx: remove rx filtering stuff
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (3 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 04/40] wl12xx: temporarily disable advanced ap functions Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 06/40] wl12xx: update fw status struct Eliad Peller
                   ` (35 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

The new fw doesn't support rx_filtering configuration (as a
stand-alone command. the rx filtering is done automatically
according to the active role).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: s/wl1271/wl12xx

 drivers/net/wireless/wl12xx/acx.c     |   28 --------
 drivers/net/wireless/wl12xx/acx.h     |  118 ---------------------------------
 drivers/net/wireless/wl12xx/boot.c    |    3 -
 drivers/net/wireless/wl12xx/cmd.c     |    4 -
 drivers/net/wireless/wl12xx/debugfs.c |    3 -
 drivers/net/wireless/wl12xx/init.c    |   12 +---
 drivers/net/wireless/wl12xx/io.h      |    1 -
 drivers/net/wireless/wl12xx/main.c    |   62 ++----------------
 drivers/net/wireless/wl12xx/reg.h     |   75 ---------------------
 drivers/net/wireless/wl12xx/rx.c      |   11 ---
 drivers/net/wireless/wl12xx/rx.h      |    1 -
 drivers/net/wireless/wl12xx/scan.c    |    3 -
 drivers/net/wireless/wl12xx/tx.c      |    4 +-
 drivers/net/wireless/wl12xx/wl12xx.h  |   22 ------
 14 files changed, 8 insertions(+), 339 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 7e33f1f..6447a09 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -180,40 +180,12 @@ int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl)
 
 out:
 	kfree(acx);
 	return ret;
 }
 
-int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter)
-{
-	struct acx_rx_config *rx_config;
-	int ret;
-
-	wl1271_debug(DEBUG_ACX, "acx rx config");
-
-	rx_config = kzalloc(sizeof(*rx_config), GFP_KERNEL);
-	if (!rx_config) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	rx_config->config_options = cpu_to_le32(config);
-	rx_config->filter_options = cpu_to_le32(filter);
-
-	ret = wl1271_cmd_configure(wl, ACX_RX_CFG,
-				   rx_config, sizeof(*rx_config));
-	if (ret < 0) {
-		wl1271_warning("failed to set rx config: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(rx_config);
-	return ret;
-}
-
 int wl1271_acx_pd_threshold(struct wl1271 *wl)
 {
 	struct acx_packet_detection *pd;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "acx data pd threshold");
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index d2eb86e..4ae0085 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -157,100 +157,12 @@ struct acx_rx_msdu_lifetime {
 	 * The maximum amount of time, in TU, before the
 	 * firmware discards the MSDU.
 	 */
 	__le32 lifetime;
 } __packed;
 
-/*
- * RX Config Options Table
- * Bit		Definition
- * ===		==========
- * 31:14		Reserved
- * 13		Copy RX Status - when set, write three receive status words
- *		to top of rx'd MPDUs.
- *		When cleared, do not write three status words (added rev 1.5)
- * 12		Reserved
- * 11		RX Complete upon FCS error - when set, give rx complete
- *		interrupt for FCS errors, after the rx filtering, e.g. unicast
- *		frames not to us with FCS error will not generate an interrupt.
- * 10		SSID Filter Enable - When set, the WiLink discards all beacon,
- *	        probe request, and probe response frames with an SSID that does
- *		not match the SSID specified by the host in the START/JOIN
- *		command.
- *		When clear, the WiLink receives frames with any SSID.
- * 9		Broadcast Filter Enable - When set, the WiLink discards all
- *		broadcast frames. When clear, the WiLink receives all received
- *		broadcast frames.
- * 8:6		Reserved
- * 5		BSSID Filter Enable - When set, the WiLink discards any frames
- *		with a BSSID that does not match the BSSID specified by the
- *		host.
- *		When clear, the WiLink receives frames from any BSSID.
- * 4		MAC Addr Filter - When set, the WiLink discards any frames
- *		with a destination address that does not match the MAC address
- *		of the adaptor.
- *		When clear, the WiLink receives frames destined to any MAC
- *		address.
- * 3		Promiscuous - When set, the WiLink receives all valid frames
- *		(i.e., all frames that pass the FCS check).
- *		When clear, only frames that pass the other filters specified
- *		are received.
- * 2		FCS - When set, the WiLink includes the FCS with the received
- *		frame.
- *		When cleared, the FCS is discarded.
- * 1		PLCP header - When set, write all data from baseband to frame
- *		buffer including PHY header.
- * 0		Reserved - Always equal to 0.
- *
- * RX Filter Options Table
- * Bit		Definition
- * ===		==========
- * 31:12		Reserved - Always equal to 0.
- * 11		Association - When set, the WiLink receives all association
- *		related frames (association request/response, reassocation
- *		request/response, and disassociation). When clear, these frames
- *		are discarded.
- * 10		Auth/De auth - When set, the WiLink receives all authentication
- *		and de-authentication frames. When clear, these frames are
- *		discarded.
- * 9		Beacon - When set, the WiLink receives all beacon frames.
- *		When clear, these frames are discarded.
- * 8		Contention Free - When set, the WiLink receives all contention
- *		free frames.
- *		When clear, these frames are discarded.
- * 7		Control - When set, the WiLink receives all control frames.
- *		When clear, these frames are discarded.
- * 6		Data - When set, the WiLink receives all data frames.
- *		When clear, these frames are discarded.
- * 5		FCS Error - When set, the WiLink receives frames that have FCS
- *		errors.
- *		When clear, these frames are discarded.
- * 4		Management - When set, the WiLink receives all management
- *		frames.
- *		When clear, these frames are discarded.
- * 3		Probe Request - When set, the WiLink receives all probe request
- *		frames.
- *		When clear, these frames are discarded.
- * 2		Probe Response - When set, the WiLink receives all probe
- *		response frames.
- *		When clear, these frames are discarded.
- * 1		RTS/CTS/ACK - When set, the WiLink receives all RTS, CTS and ACK
- *		frames.
- *		When clear, these frames are discarded.
- * 0		Rsvd Type/Sub Type - When set, the WiLink receives all frames
- *		that have reserved frame types and sub types as defined by the
- *		802.11 specification.
- *		When clear, these frames are discarded.
- */
-struct acx_rx_config {
-	struct acx_header header;
-
-	__le32 config_options;
-	__le32 filter_options;
-} __packed;
-
 struct acx_packet_detection {
 	struct acx_header header;
 
 	__le32 threshold;
 } __packed;
 
@@ -421,41 +333,12 @@ struct acx_event_mask {
 	struct acx_header header;
 
 	__le32 event_mask;
 	__le32 high_event_mask; /* Unused */
 } __packed;
 
-#define CFG_RX_FCS		BIT(2)
-#define CFG_RX_ALL_GOOD		BIT(3)
-#define CFG_UNI_FILTER_EN	BIT(4)
-#define CFG_BSSID_FILTER_EN	BIT(5)
-#define CFG_MC_FILTER_EN	BIT(6)
-#define CFG_MC_ADDR0_EN		BIT(7)
-#define CFG_MC_ADDR1_EN		BIT(8)
-#define CFG_BC_REJECT_EN	BIT(9)
-#define CFG_SSID_FILTER_EN	BIT(10)
-#define CFG_RX_INT_FCS_ERROR	BIT(11)
-#define CFG_RX_INT_ENCRYPTED	BIT(12)
-#define CFG_RX_WR_RX_STATUS	BIT(13)
-#define CFG_RX_FILTER_NULTI	BIT(14)
-#define CFG_RX_RESERVE		BIT(15)
-#define CFG_RX_TIMESTAMP_TSF	BIT(16)
-
-#define CFG_RX_RSV_EN		BIT(0)
-#define CFG_RX_RCTS_ACK		BIT(1)
-#define CFG_RX_PRSP_EN		BIT(2)
-#define CFG_RX_PREQ_EN		BIT(3)
-#define CFG_RX_MGMT_EN		BIT(4)
-#define CFG_RX_FCS_ERROR	BIT(5)
-#define CFG_RX_DATA_EN		BIT(6)
-#define CFG_RX_CTL_EN		BIT(7)
-#define CFG_RX_CF_EN		BIT(8)
-#define CFG_RX_BCN_EN		BIT(9)
-#define CFG_RX_AUTH_EN		BIT(10)
-#define CFG_RX_ASSOC_EN		BIT(11)
-
 #define SCAN_PASSIVE		BIT(0)
 #define SCAN_5GHZ_BAND		BIT(1)
 #define SCAN_TRIGGERED		BIT(2)
 #define SCAN_PRIORITY_HIGH	BIT(3)
 
 /* When set, disable HW encryption */
@@ -1339,13 +1222,12 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl);
 int wl1271_acx_sleep_auth(struct wl1271 *wl, u8 sleep_auth);
 int wl1271_acx_tx_power(struct wl1271 *wl, int power);
 int wl1271_acx_feature_cfg(struct wl1271 *wl);
 int wl1271_acx_mem_map(struct wl1271 *wl,
 		       struct acx_header *mem_map, size_t len);
 int wl1271_acx_rx_msdu_life_time(struct wl1271 *wl);
-int wl1271_acx_rx_config(struct wl1271 *wl, u32 config, u32 filter);
 int wl1271_acx_pd_threshold(struct wl1271 *wl);
 int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time);
 int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
 				 void *mc_list, u32 mc_list_len);
 int wl1271_acx_service_period_timeout(struct wl1271 *wl);
 int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold);
diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 930a638..41791ff 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -842,14 +842,11 @@ int wl1271_boot(struct wl1271 *wl)
 	wl1271_write32(wl, ACX_REG_INTERRUPT_MASK,
 		       WL1271_ACX_ALL_EVENTS_VECTOR);
 
 	/* Enable firmware interrupts now */
 	wl1271_boot_enable_interrupts(wl);
 
-	/* set the wl1271 default filters */
-	wl1271_set_default_filters(wl);
-
 	wl1271_event_mbox_config(wl);
 
 out:
 	return ret;
 }
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 97dd237..b6ef65a 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -379,14 +379,12 @@ int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 
 	/* Reverse order BSSID */
 	bssid = (u8 *) &join->bssid_lsb;
 	for (i = 0; i < ETH_ALEN; i++)
 		bssid[i] = wl->bssid[ETH_ALEN - i - 1];
 
-	join->rx_config_options = cpu_to_le32(wl->rx_config);
-	join->rx_filter_options = cpu_to_le32(wl->rx_filter);
 	join->bss_type = bss_type;
 	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
 	join->supported_rate_set = cpu_to_le32(wl->rate_set);
 
 	if (wl->band == IEEE80211_BAND_5GHZ)
 		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -1001,14 +999,12 @@ int wl1271_cmd_disconnect(struct wl1271 *wl)
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	cmd->rx_config_options = cpu_to_le32(wl->rx_config);
-	cmd->rx_filter_options = cpu_to_le32(wl->rx_filter);
 	/* disconnect reason is not used in immediate disconnections */
 	cmd->type = DISCONNECT_IMMEDIATE;
 
 	ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
 		wl1271_error("failed to send disconnect command");
diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 3b5f240..fd1c301 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -363,15 +363,12 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 	DRIVER_STATE_PRINT_HEX(basic_rate_set);
 	DRIVER_STATE_PRINT_HEX(basic_rate);
 	DRIVER_STATE_PRINT_INT(band);
 	DRIVER_STATE_PRINT_INT(beacon_int);
 	DRIVER_STATE_PRINT_INT(psm_entry_retry);
 	DRIVER_STATE_PRINT_INT(ps_poll_failures);
-	DRIVER_STATE_PRINT_HEX(filters);
-	DRIVER_STATE_PRINT_HEX(rx_config);
-	DRIVER_STATE_PRINT_HEX(rx_filter);
 	DRIVER_STATE_PRINT_INT(power_level);
 	DRIVER_STATE_PRINT_INT(rssi_thold);
 	DRIVER_STATE_PRINT_INT(last_rssi_event);
 	DRIVER_STATE_PRINT_INT(sg_enabled);
 	DRIVER_STATE_PRINT_INT(enable_11a);
 	DRIVER_STATE_PRINT_INT(noise);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index c3e9a2e..44cd515 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -224,24 +224,20 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
-static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
+static int wl12xx_init_rx_config(struct wl1271 *wl)
 {
 	int ret;
 
 	ret = wl1271_acx_rx_msdu_life_time(wl);
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_rx_config(wl, config, filter);
-	if (ret < 0)
-		return ret;
-
 	return 0;
 }
 
 int wl1271_init_phy_config(struct wl1271 *wl)
 {
 	int ret;
@@ -647,17 +643,13 @@ int wl1271_hw_init(struct wl1271 *wl)
 	/* Default memory configuration */
 	ret = wl1271_acx_init_mem_config(wl);
 	if (ret < 0)
 		return ret;
 
 	/* RX config */
-	ret = wl1271_init_rx_config(wl,
-				    RX_CFG_PROMISCUOUS | RX_CFG_TSF,
-				    RX_FILTER_OPTION_DEF);
-	/* RX_CONFIG_OPTION_ANY_DST_ANY_BSS,
-	   RX_FILTER_OPTION_FILTER_ALL); */
+	ret = wl12xx_init_rx_config(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
 	/* PHY layer config */
 	ret = wl1271_init_phy_config(wl);
 	if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/io.h b/drivers/net/wireless/wl12xx/io.h
index a2fe4f5..e839341 100644
--- a/drivers/net/wireless/wl12xx/io.h
+++ b/drivers/net/wireless/wl12xx/io.h
@@ -183,9 +183,8 @@ void wl1271_unregister_hw(struct wl1271 *wl);
 int wl1271_init_ieee80211(struct wl1271 *wl);
 struct ieee80211_hw *wl1271_alloc_hw(void);
 int wl1271_free_hw(struct wl1271 *wl);
 irqreturn_t wl1271_irq(int irq, void *data);
 bool wl1271_set_block_size(struct wl1271 *wl);
 int wl1271_tx_dummy_packet(struct wl1271 *wl);
-void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 4fa7602..7fcdfa3 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1988,13 +1988,12 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	wl->tx_results_count = 0;
 	wl->tx_packets_count = 0;
 	wl->time_offset = 0;
 	wl->session_counter = 0;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
 	wl->vif = NULL;
-	wl->filters = 0;
 	wl1271_free_ap_keys(wl);
 	memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
 	wl->ap_fw_ps_map = 0;
 	wl->ap_ps_map = 0;
 	wl->sched_scanning = false;
 
@@ -2034,57 +2033,21 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
 	}
 
 	mutex_unlock(&wl->mutex);
 	cancel_work_sync(&wl->recovery_work);
 }
 
-void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
-{
-	wl1271_set_default_filters(wl);
-
-	/* combine requested filters with current filter config */
-	filters = wl->filters | filters;
-
-	wl1271_debug(DEBUG_FILTERS, "RX filters set: ");
-
-	if (filters & FIF_PROMISC_IN_BSS) {
-		wl1271_debug(DEBUG_FILTERS, " - FIF_PROMISC_IN_BSS");
-		wl->rx_config &= ~CFG_UNI_FILTER_EN;
-		wl->rx_config |= CFG_BSSID_FILTER_EN;
-	}
-	if (filters & FIF_BCN_PRBRESP_PROMISC) {
-		wl1271_debug(DEBUG_FILTERS, " - FIF_BCN_PRBRESP_PROMISC");
-		wl->rx_config &= ~CFG_BSSID_FILTER_EN;
-		wl->rx_config &= ~CFG_SSID_FILTER_EN;
-	}
-	if (filters & FIF_OTHER_BSS) {
-		wl1271_debug(DEBUG_FILTERS, " - FIF_OTHER_BSS");
-		wl->rx_config &= ~CFG_BSSID_FILTER_EN;
-	}
-	if (filters & FIF_CONTROL) {
-		wl1271_debug(DEBUG_FILTERS, " - FIF_CONTROL");
-		wl->rx_filter |= CFG_RX_CTL_EN;
-	}
-	if (filters & FIF_FCSFAIL) {
-		wl1271_debug(DEBUG_FILTERS, " - FIF_FCSFAIL");
-		wl->rx_filter |= CFG_RX_FCS_ERROR;
-	}
-}
-
 static int wl1271_dummy_join(struct wl1271 *wl)
 {
 	int ret = 0;
 	/* we need to use a dummy BSSID for now */
 	static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
 						  0xad, 0xbe, 0xef };
 
 	memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
 
-	/* pass through frames from all BSS */
-	wl1271_configure_filters(wl, FIF_OTHER_BSS);
-
 	ret = wl1271_cmd_join(wl, wl->set_bss_type);
 	if (ret < 0)
 		goto out;
 
 	set_bit(WL1271_FLAG_JOINED, &wl->flags);
 
@@ -2160,15 +2123,12 @@ static int wl1271_unjoin(struct wl1271 *wl)
 	memset(wl->bssid, 0, ETH_ALEN);
 
 	/* reset TX security counters on a clean disconnect */
 	wl->tx_security_last_seq_lsb = 0;
 	wl->tx_security_seq = 0;
 
-	/* stop filtering packets based on bssid */
-	wl1271_configure_filters(wl, FIF_OTHER_BSS);
-
 out:
 	return ret;
 }
 
 static void wl1271_set_band_rate(struct wl1271 *wl)
 {
@@ -2431,24 +2391,17 @@ static void wl1271_op_configure_filter(struct ieee80211_hw *hw,
 							   fp->mc_list,
 							   fp->mc_list_length);
 		if (ret < 0)
 			goto out_sleep;
 	}
 
-	/* determine, whether supported filter values have changed */
-	if (changed == 0)
-		goto out_sleep;
-
-	/* configure filters */
-	wl->filters = *total;
-	wl1271_configure_filters(wl, 0);
-
-	/* apply configured filters */
-	ret = wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
-	if (ret < 0)
-		goto out_sleep;
+	/*
+	 * the fw doesn't provide an api to configure the filters. instead,
+	 * the filters configuration is based on the active roles / ROC
+	 * state.
+	 */
 
 out_sleep:
 	wl1271_ps_elp_sleep(wl);
 
 out:
 	mutex_unlock(&wl->mutex);
@@ -3165,15 +3118,12 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 				goto out;
 
 			ret = wl1271_build_qos_null_data(wl);
 			if (ret < 0)
 				goto out;
 
-			/* filter out all packets not from this BSSID */
-			wl1271_configure_filters(wl, 0);
-
 			/* Need to update the BSSID (for filtering etc) */
 			do_join = true;
 		}
 	}
 
 	rcu_read_lock();
@@ -4360,14 +4310,12 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	}
 
 	wl->channel = WL1271_DEFAULT_CHANNEL;
 	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
 	wl->default_key = 0;
 	wl->rx_counter = 0;
-	wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
 	wl->psm_entry_retry = 0;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
 	wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
 	wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
 	wl->band = IEEE80211_BAND_2GHZ;
diff --git a/drivers/net/wireless/wl12xx/reg.h b/drivers/net/wireless/wl12xx/reg.h
index 440a4ee..3f570f3 100644
--- a/drivers/net/wireless/wl12xx/reg.h
+++ b/drivers/net/wireless/wl12xx/reg.h
@@ -293,87 +293,12 @@
  The information mailbox pointer is not valid
  until after the host receives the Init Complete interrupt from
  the Wlan hardware.
  ===============================================*/
 #define REG_EVENT_MAILBOX_PTR				(SCR_PAD1)
 
-
-/* Misc */
-
-#define REG_ENABLE_TX_RX				(ENABLE)
-/*
- * Rx configuration (filter) information element
- * ---------------------------------------------
- */
-#define REG_RX_CONFIG				(RX_CFG)
-#define REG_RX_FILTER				(RX_FILTER_CFG)
-
-
-#define RX_CFG_ENABLE_PHY_HEADER_PLCP	 0x0002
-
-/* promiscuous - receives all valid frames */
-#define RX_CFG_PROMISCUOUS		 0x0008
-
-/* receives frames from any BSSID */
-#define RX_CFG_BSSID			 0x0020
-
-/* receives frames destined to any MAC address */
-#define RX_CFG_MAC			 0x0010
-
-#define RX_CFG_ENABLE_ONLY_MY_DEST_MAC	 0x0010
-#define RX_CFG_ENABLE_ANY_DEST_MAC	 0x0000
-#define RX_CFG_ENABLE_ONLY_MY_BSSID	 0x0020
-#define RX_CFG_ENABLE_ANY_BSSID		 0x0000
-
-/* discards all broadcast frames */
-#define RX_CFG_DISABLE_BCAST		 0x0200
-
-#define RX_CFG_ENABLE_ONLY_MY_SSID	 0x0400
-#define RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR 0x0800
-#define RX_CFG_COPY_RX_STATUS		 0x2000
-#define RX_CFG_TSF			 0x10000
-
-#define RX_CONFIG_OPTION_ANY_DST_MY_BSS	 (RX_CFG_ENABLE_ANY_DEST_MAC | \
-					  RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_ANY_BSS	 (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
-					  | RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_ANY_DST_ANY_BSS (RX_CFG_ENABLE_ANY_DEST_MAC | \
-					  RX_CFG_ENABLE_ANY_BSSID)
-
-#define RX_CONFIG_OPTION_MY_DST_MY_BSS	 (RX_CFG_ENABLE_ONLY_MY_DEST_MAC\
-					  | RX_CFG_ENABLE_ONLY_MY_BSSID)
-
-#define RX_CONFIG_OPTION_FOR_SCAN  (RX_CFG_ENABLE_PHY_HEADER_PLCP \
-				    | RX_CFG_ENABLE_RX_CMPLT_FCS_ERROR \
-				    | RX_CFG_COPY_RX_STATUS | RX_CFG_TSF)
-
-#define RX_CONFIG_OPTION_FOR_MEASUREMENT (RX_CFG_ENABLE_ANY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_JOIN	 (RX_CFG_ENABLE_ONLY_MY_BSSID | \
-					  RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_CONFIG_OPTION_FOR_IBSS_JOIN   (RX_CFG_ENABLE_ONLY_MY_SSID | \
-					  RX_CFG_ENABLE_ONLY_MY_DEST_MAC)
-
-#define RX_FILTER_OPTION_DEF	      (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
-				       | CFG_RX_CTL_EN | CFG_RX_BCN_EN\
-				       | CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
-
-#define RX_FILTER_OPTION_FILTER_ALL	 0
-
-#define RX_FILTER_OPTION_DEF_PRSP_BCN  (CFG_RX_PRSP_EN | CFG_RX_MGMT_EN\
-					| CFG_RX_RCTS_ACK | CFG_RX_BCN_EN)
-
-#define RX_FILTER_OPTION_JOIN	     (CFG_RX_MGMT_EN | CFG_RX_DATA_EN\
-				      | CFG_RX_BCN_EN | CFG_RX_AUTH_EN\
-				      | CFG_RX_ASSOC_EN | CFG_RX_RCTS_ACK\
-				      | CFG_RX_PRSP_EN)
-
-
 /*===============================================
  EEPROM Read/Write Request 32bit RW
  ------------------------------------------
  1 EE_READ - EEPROM Read Request 1 - Setting this bit
  loads a single byte of data into the EE_DATA
  register from the EEPROM location specified in
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 46f4af6..7a0c5fe 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -280,17 +280,6 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 					     &wl->rx_streaming_enable_work);
 
 		mod_timer(&wl->rx_streaming_timer,
 			  jiffies + msecs_to_jiffies(timeout));
 	}
 }
-
-void wl1271_set_default_filters(struct wl1271 *wl)
-{
-	if (wl->bss_type == BSS_TYPE_AP_BSS) {
-		wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
-		wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
-	} else {
-		wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
-		wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
-	}
-}
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 0325b9d..d3c0591 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -128,9 +128,8 @@ struct wl1271_rx_descriptor {
 	u8  pad_len;
 	u8  reserved;
 } __packed;
 
 void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
-void wl1271_set_default_filters(struct wl1271 *wl);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index edfe01c..78a9b23 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -164,15 +164,12 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
 	if (cmd->params.n_ch == 0) {
 		ret = WL1271_NOTHING_TO_SCAN;
 		goto out;
 	}
 
 	cmd->params.tx_rate = cpu_to_le32(basic_rate);
-	cmd->params.rx_config_options = cpu_to_le32(CFG_RX_ALL_GOOD);
-	cmd->params.rx_filter_options =
-		cpu_to_le32(CFG_RX_PRSP_EN | CFG_RX_MGMT_EN | CFG_RX_BCN_EN);
 
 	cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
 	cmd->params.tx_rate = cpu_to_le32(basic_rate);
 	cmd->params.tid_trigger = 0;
 	cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
 
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 938af1d..8a745fb 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -87,15 +87,13 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
 	 * responses coming from BSSIDs it isn't familiar with (e.g. on
 	 * roaming)
 	 */
 	if (!ieee80211_is_auth(hdr->frame_control))
 		return 0;
 
-	wl1271_configure_filters(wl, FIF_OTHER_BSS);
-
-	return wl1271_acx_rx_config(wl, wl->rx_config, wl->rx_filter);
+	return 0;
 }
 
 static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
 						 struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 0bdeae5..7707895 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -109,30 +109,12 @@ extern u32 wl12xx_debug_level;
 				       DUMP_PREFIX_OFFSET, 16, 1,	\
 				       buf,				\
 				       min_t(size_t, len, DEBUG_DUMP_LIMIT), \
 				       true);				\
 	} while (0)
 
-#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN |	\
-				  CFG_BSSID_FILTER_EN | \
-				  CFG_MC_FILTER_EN)
-
-#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN |  \
-				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN |   \
-				  CFG_RX_CTL_EN | CFG_RX_BCN_EN |     \
-				  CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
-
-#define WL1271_DEFAULT_AP_RX_CONFIG  0
-
-#define WL1271_DEFAULT_AP_RX_FILTER  (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
-				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
-				  CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
-				  CFG_RX_ASSOC_EN)
-
-
-
 #define WL127X_FW_NAME "ti-connectivity/wl127x-fw-3.bin"
 #define WL128X_FW_NAME "ti-connectivity/wl128x-fw-3.bin"
 
 /*
  * wl127x and wl128x are using the same NVS file name. However, the
  * ini parameters between them are different.  The driver validates
@@ -529,16 +511,12 @@ struct wl1271 {
 
 	/* Rx Streaming */
 	struct work_struct rx_streaming_enable_work;
 	struct work_struct rx_streaming_disable_work;
 	struct timer_list rx_streaming_timer;
 
-	unsigned int filters;
-	unsigned int rx_config;
-	unsigned int rx_filter;
-
 	struct completion *elp_compl;
 	struct completion *ps_compl;
 	struct delayed_work elp_work;
 	struct delayed_work pspoll_work;
 
 	/* counter for ps-poll delivery failures */
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 06/40] wl12xx: update fw status struct
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (4 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 05/40] wl12xx: remove rx filtering stuff Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 07/40] wl12xx: update acx commands Eliad Peller
                   ` (34 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Update the fw status struct according to the new fw api
(fw >= 6/7.0.0.35).
All the roles use the same struct now.

The memory accounting was changed a bit according to
the struct changes.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: s/wl1271/wl12xx, s/__cpu_to_le32/cpu_to_le32

 drivers/net/wireless/wl12xx/debugfs.c |    5 +--
 drivers/net/wireless/wl12xx/main.c    |   82 +++++++++++++-------------------
 drivers/net/wireless/wl12xx/rx.c      |   18 ++++----
 drivers/net/wireless/wl12xx/rx.h      |    2 +-
 drivers/net/wireless/wl12xx/wl12xx.h  |   55 ++++++++++------------
 5 files changed, 68 insertions(+), 94 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index fd1c301..3102652 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -346,16 +346,13 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 	DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
 	DRIVER_STATE_PRINT_INT(tx_packets_count);
 	DRIVER_STATE_PRINT_INT(tx_results_count);
 	DRIVER_STATE_PRINT_LHEX(flags);
-	DRIVER_STATE_PRINT_INT(tx_blocks_freed[0]);
-	DRIVER_STATE_PRINT_INT(tx_blocks_freed[1]);
-	DRIVER_STATE_PRINT_INT(tx_blocks_freed[2]);
-	DRIVER_STATE_PRINT_INT(tx_blocks_freed[3]);
+	DRIVER_STATE_PRINT_INT(tx_blocks_freed);
 	DRIVER_STATE_PRINT_INT(tx_security_last_seq_lsb);
 	DRIVER_STATE_PRINT_INT(rx_counter);
 	DRIVER_STATE_PRINT_INT(session_counter);
 	DRIVER_STATE_PRINT_INT(state);
 	DRIVER_STATE_PRINT_INT(bss_type);
 	DRIVER_STATE_PRINT_INT(channel);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 7fcdfa3..96f76b1 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -823,72 +823,58 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
 		wl1271_irq_ps_regulate_link(wl, hlid,
 					    wl->links[hlid].allocated_blks);
 	}
 }
 #endif
 
-static void wl1271_fw_status(struct wl1271 *wl,
-			     struct wl1271_fw_full_status *full_status)
+static void wl12xx_fw_status(struct wl1271 *wl,
+			     struct wl12xx_fw_status *status)
 {
-	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
 	u32 old_tx_blk_count = wl->tx_blocks_available;
-	u32 freed_blocks = 0;
-	int i;
+	int avail, freed_blocks;
 
-	if (wl->bss_type == BSS_TYPE_AP_BSS) {
-		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
-				sizeof(struct wl1271_fw_ap_status), false);
-	} else {
-		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
-				sizeof(struct wl1271_fw_sta_status), false);
-	}
+	wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
 		     status->intr,
 		     status->fw_rx_counter,
 		     status->drv_rx_counter,
 		     status->tx_results_counter);
 
-	/* update number of available TX blocks */
-	for (i = 0; i < NUM_TX_QUEUES; i++) {
-		freed_blocks += le32_to_cpu(status->tx_released_blks[i]) -
-				wl->tx_blocks_freed[i];
-
-		wl->tx_blocks_freed[i] =
-			le32_to_cpu(status->tx_released_blks[i]);
-	}
+	freed_blocks = le32_to_cpu(status->total_released_blks) -
+		       wl->tx_blocks_freed;
+	wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks);
 
 	wl->tx_allocated_blocks -= freed_blocks;
 
-	if (wl->bss_type == BSS_TYPE_AP_BSS) {
-		/* Update num of allocated TX blocks per link and ps status */
-#if 0
-		wl1271_irq_update_links_status(wl, &full_status->ap);
-#endif
-		wl->tx_blocks_available += freed_blocks;
-	} else {
-		int avail = full_status->sta.tx_total - wl->tx_allocated_blocks;
+	avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
 
-		/*
-		 * The FW might change the total number of TX memblocks before
-		 * we get a notification about blocks being released. Thus, the
-		 * available blocks calculation might yield a temporary result
-		 * which is lower than the actual available blocks. Keeping in
-		 * mind that only blocks that were allocated can be moved from
-		 * TX to RX, tx_blocks_available should never decrease here.
-		 */
-		wl->tx_blocks_available = max((int)wl->tx_blocks_available,
-					      avail);
-	}
+	/*
+	 * The FW might change the total number of TX memblocks before
+	 * we get a notification about blocks being released. Thus, the
+	 * available blocks calculation might yield a temporary result
+	 * which is lower than the actual available blocks. Keeping in
+	 * mind that only blocks that were allocated can be moved from
+	 * TX to RX, tx_blocks_available should never decrease here.
+	 */
+	wl->tx_blocks_available = max((int)wl->tx_blocks_available,
+				      avail);
 
 	/* if more blocks are available now, tx work can be scheduled */
 	if (wl->tx_blocks_available > old_tx_blk_count)
 		clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
 
+	/* for AP update num of allocated TX blocks per link and ps status */
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+#if 0
+		wl1271_irq_update_links_status(wl, status);
+#endif
+	}
+
 	/* update the host-chipset time offset */
 	getnstimeofday(&ts);
 	wl->time_offset = (timespec_to_ns(&ts) >> 10) -
 		(s64)le32_to_cpu(status->fw_localtime);
 }
 
@@ -955,14 +941,14 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
 		 * before acknowledging the chip. Since the mutex is held,
 		 * wl1271_ps_elp_wakeup cannot be called concurrently.
 		 */
 		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
 		smp_mb__after_clear_bit();
 
-		wl1271_fw_status(wl, wl->fw_status);
-		intr = le32_to_cpu(wl->fw_status->common.intr);
+		wl12xx_fw_status(wl, wl->fw_status);
+		intr = le32_to_cpu(wl->fw_status->intr);
 		intr &= WL1271_INTR_MASK;
 		if (!intr) {
 			done = true;
 			continue;
 		}
 
@@ -975,13 +961,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
 			goto out;
 		}
 
 		if (likely(intr & WL1271_ACX_INTR_DATA)) {
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
-			wl1271_rx(wl, &wl->fw_status->common);
+			wl12xx_rx(wl, wl->fw_status);
 
 			/* Check if any tx blocks were freed */
 			spin_lock_irqsave(&wl->wl_lock, flags);
 			if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
 			    wl1271_tx_total_queue_count(wl) > 0) {
 				spin_unlock_irqrestore(&wl->wl_lock, flags);
@@ -992,13 +978,13 @@ irqreturn_t wl1271_irq(int irq, void *cookie)
 				wl1271_tx_work_locked(wl);
 			} else {
 				spin_unlock_irqrestore(&wl->wl_lock, flags);
 			}
 
 			/* check for tx results */
-			if (wl->fw_status->common.tx_results_counter !=
+			if (wl->fw_status->tx_results_counter !=
 			    (wl->tx_results_count & 0xff))
 				wl1271_tx_complete(wl);
 
 			/* Make sure the deferred queues don't get too long */
 			defer_count = skb_queue_len(&wl->deferred_tx_queue) +
 				      skb_queue_len(&wl->deferred_rx_queue);
@@ -1166,14 +1152,14 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
 	 * This might fail if the firmware hanged.
 	 */
 	if (!wl1271_ps_elp_wakeup(wl))
 		wl12xx_cmd_stop_fwlog(wl);
 
 	/* Read the first memory block address */
-	wl1271_fw_status(wl, wl->fw_status);
-	first_addr = __le32_to_cpu(wl->fw_status->sta.log_start_addr);
+	wl12xx_fw_status(wl, wl->fw_status);
+	first_addr = le32_to_cpu(wl->fw_status->log_start_addr);
 	if (!first_addr)
 		goto out;
 
 	/* Traverse the memory blocks linked list */
 	addr = first_addr;
 	do {
@@ -1183,13 +1169,13 @@ static void wl12xx_read_fwlog_panic(struct wl1271 *wl)
 
 		/*
 		 * Memory blocks are linked to one another. The first 4 bytes
 		 * of each memory block hold the hardware address of the next
 		 * one. The last memory block points to the first one.
 		 */
-		addr = __le32_to_cpup((__le32 *)block);
+		addr = le32_to_cpup((__le32 *)block);
 		if (!wl12xx_copy_fwlog(wl, block + sizeof(addr),
 				       WL12XX_HW_BLOCK_SIZE - sizeof(addr)))
 			break;
 	} while (addr && (addr != first_addr));
 
 	wake_up_interruptible(&wl->fwlog_waitq);
@@ -1920,13 +1906,12 @@ out:
 	return ret;
 }
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
 					 bool reset_tx_queues)
 {
-	int i;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
 
 	/* because of hardware recovery, we may get here twice */
 	if (wl->state != WL1271_STATE_ON)
 		return;
@@ -2001,14 +1986,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	 * this is performed after the cancel_work calls and the associated
 	 * mutex_lock, so that wl1271_op_add_interface does not accidentally
 	 * get executed before all these vars have been reset.
 	 */
 	wl->flags = 0;
 
-	for (i = 0; i < NUM_TX_QUEUES; i++)
-		wl->tx_blocks_freed[i] = 0;
+	wl->tx_blocks_freed = 0;
 
 	wl1271_debugfs_reset(wl);
 
 	kfree(wl->fw_status);
 	wl->fw_status = NULL;
 	kfree(wl->tx_res_if);
diff --git a/drivers/net/wireless/wl12xx/rx.c b/drivers/net/wireless/wl12xx/rx.c
index 7a0c5fe..78d8410 100644
--- a/drivers/net/wireless/wl12xx/rx.c
+++ b/drivers/net/wireless/wl12xx/rx.c
@@ -27,27 +27,27 @@
 #include "wl12xx.h"
 #include "acx.h"
 #include "reg.h"
 #include "rx.h"
 #include "io.h"
 
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
+static u8 wl12xx_rx_get_mem_block(struct wl12xx_fw_status *status,
 				  u32 drv_rx_counter)
 {
 	return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
 		RX_MEM_BLOCK_MASK;
 }
 
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
-				  u32 drv_rx_counter)
+static u32 wl12xx_rx_get_buf_size(struct wl12xx_fw_status *status,
+				 u32 drv_rx_counter)
 {
 	return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
 		RX_BUF_SIZE_MASK) >> RX_BUF_SIZE_SHIFT_DIV;
 }
 
-static bool wl1271_rx_get_unaligned(struct wl1271_fw_common_status *status,
+static bool wl12xx_rx_get_unaligned(struct wl12xx_fw_status *status,
 				    u32 drv_rx_counter)
 {
 	/* Convert the value to bool */
 	return !!(le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
 		RX_BUF_UNALIGNED_PAYLOAD);
 }
@@ -178,13 +178,13 @@ static int wl1271_rx_handle_data(struct wl1271 *wl, u8 *data, u32 length,
 	skb_queue_tail(&wl->deferred_rx_queue, skb);
 	queue_work(wl->freezable_wq, &wl->netstack_work);
 
 	return is_data;
 }
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
+void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status)
 {
 	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
 	u32 buf_size;
 	u32 fw_rx_counter  = status->fw_rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
 	u32 drv_rx_counter = wl->rx_counter & NUM_RX_PKT_DESC_MOD_MASK;
 	u32 rx_counter;
@@ -196,13 +196,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 	bool unaligned = false;
 
 	while (drv_rx_counter != fw_rx_counter) {
 		buf_size = 0;
 		rx_counter = drv_rx_counter;
 		while (rx_counter != fw_rx_counter) {
-			pkt_length = wl1271_rx_get_buf_size(status, rx_counter);
+			pkt_length = wl12xx_rx_get_buf_size(status, rx_counter);
 			if (buf_size + pkt_length > WL1271_AGGR_BUFFER_SIZE)
 				break;
 			buf_size += pkt_length;
 			rx_counter++;
 			rx_counter &= NUM_RX_PKT_DESC_MOD_MASK;
 		}
@@ -215,13 +215,13 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 		if (wl->chip.id != CHIP_ID_1283_PG20) {
 			/*
 			 * Choose the block we want to read
 			 * For aggregated packets, only the first memory block
 			 * should be retrieved. The FW takes care of the rest.
 			 */
-			mem_block = wl1271_rx_get_mem_block(status,
+			mem_block = wl12xx_rx_get_mem_block(status,
 							    drv_rx_counter);
 
 			wl->rx_mem_pool_addr.addr = (mem_block << 8) +
 			   le32_to_cpu(wl_mem_map->packet_memory_pool_start);
 
 			wl->rx_mem_pool_addr.addr_extra =
@@ -236,16 +236,16 @@ void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 		wl1271_read(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
 				buf_size, true);
 
 		/* Split data into separate packets */
 		pkt_offset = 0;
 		while (pkt_offset < buf_size) {
-			pkt_length = wl1271_rx_get_buf_size(status,
+			pkt_length = wl12xx_rx_get_buf_size(status,
 					drv_rx_counter);
 
-			unaligned = wl1271_rx_get_unaligned(status,
+			unaligned = wl12xx_rx_get_unaligned(status,
 					drv_rx_counter);
 
 			/*
 			 * the handle data call can only fail in memory-outage
 			 * conditions, in that case the received frame will just
 			 * be dropped.
diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index d3c0591..00c1c1d 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -126,10 +126,10 @@ struct wl1271_rx_descriptor {
 		u8  hlid; /* AP FW */
 	} __packed;
 	u8  pad_len;
 	u8  reserved;
 } __packed;
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
+void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 7707895..f708cd7 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -134,12 +134,13 @@ extern u32 wl12xx_debug_level;
 #define WL1271_ELP_HW_STATE_ASLEEP 0
 #define WL1271_ELP_HW_STATE_IRQ    1
 
 #define WL1271_DEFAULT_BEACON_INT  100
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
+#define WL12XX_MAX_LINKS           8
 #define WL1271_AP_GLOBAL_HLID      0
 #define WL1271_AP_BROADCAST_HLID   1
 #define WL1271_AP_STA_HLID_START   2
 
 /*
  * When in AP-mode, we allow (at least) this number of mem-blocks
@@ -227,59 +228,51 @@ struct wl1271_stats {
 
 #define AP_MAX_STATIONS            5
 
 /* Broadcast and Global links + links to stations */
 #define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
 
-/* FW status registers common for AP/STA */
-struct wl1271_fw_common_status {
+/* FW status registers */
+struct wl12xx_fw_status {
 	__le32 intr;
 	u8  fw_rx_counter;
 	u8  drv_rx_counter;
 	u8  reserved;
 	u8  tx_results_counter;
 	__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
-	__le32 tx_released_blks[NUM_TX_QUEUES];
 	__le32 fw_localtime;
-} __packed;
-
-/* FW status registers for AP */
-struct wl1271_fw_ap_status {
-	struct wl1271_fw_common_status common;
-
-	/* Next fields valid only in AP FW */
 
 	/*
 	 * A bitmap (where each bit represents a single HLID)
 	 * to indicate if the station is in PS mode.
 	 */
 	__le32 link_ps_bitmap;
 
-	/* Number of freed MBs per HLID */
-	u8 tx_lnk_free_blks[AP_MAX_LINKS];
-	u8 padding_1[1];
-} __packed;
+	/*
+	 * A bitmap (where each bit represents a single HLID) to indicate
+	 * if the station is in Fast mode
+	 */
+	__le32 link_fast_bitmap;
 
-/* FW status registers for STA */
-struct wl1271_fw_sta_status {
-	struct wl1271_fw_common_status common;
+	/* Cumulative counter of total released mem blocks since FW-reset */
+	__le32 total_released_blks;
 
-	u8  tx_total;
-	u8  reserved1;
-	__le16 reserved2;
-	__le32 log_start_addr;
-} __packed;
+	/* Size (in Memory Blocks) of TX pool */
+	__le32 tx_total;
 
-struct wl1271_fw_full_status {
-	union {
-		struct wl1271_fw_common_status common;
-		struct wl1271_fw_sta_status sta;
-		struct wl1271_fw_ap_status ap;
-	};
-} __packed;
+	/* Cumulative counter of released mem-blocks per AC */
+	u8 tx_released_blks[NUM_TX_QUEUES];
 
+	/* Cumulative counter of freed MBs per HLID */
+	u8 tx_lnk_free_blks[WL12XX_MAX_LINKS];
+
+	/* Cumulative counter of released Voice memory blocks */
+	u8 tx_voice_released_blks;
+	u8 padding_1[7];
+	__le32 log_start_addr;
+} __packed;
 
 struct wl1271_rx_mem_pool_addr {
 	u32 addr;
 	u32 addr_extra;
 };
 
@@ -398,13 +391,13 @@ struct wl1271 {
 	u8 ssid_len;
 	int channel;
 
 	struct wl1271_acx_mem_map *target_mem_map;
 
 	/* Accounting for allocated / available TX blocks on HW */
-	u32 tx_blocks_freed[NUM_TX_QUEUES];
+	u32 tx_blocks_freed;
 	u32 tx_blocks_available;
 	u32 tx_allocated_blocks;
 	u32 tx_results_count;
 
 	/* Transmitted TX packets counter for chipset interface */
 	u32 tx_packets_count;
@@ -534,13 +527,13 @@ struct wl1271 {
 	struct wl1271_stats stats;
 
 	__le32 buffer_32;
 	u32 buffer_cmd;
 	u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
 
-	struct wl1271_fw_full_status *fw_status;
+	struct wl12xx_fw_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
 
 	struct ieee80211_vif *vif;
 
 	/* Current chipset configuration */
 	struct conf_drv_settings conf;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 07/40] wl12xx: update acx commands
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (5 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 06/40] wl12xx: update fw status struct Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 08/40] wl12xx: update commands & events Eliad Peller
                   ` (33 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Update the acx commands according to the new fw api
(fw >= 6/7.3.0.0.75).

The main change in most of the ACXs is the addition
of a new role_id/link_id field, which is required
for multi-role operation.

Currently, we don't really support multi-role, as
most of our data (inside wl) is global.
As the current fw doesn't support concurrent roles
yet, keep it this way and add wl->role_id and
wl->sta_hlid to save the active role/link.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: s/wl1271/wl12xx

 drivers/net/wireless/wl12xx/acx.c    |  113 ++++++++++++---------------
 drivers/net/wireless/wl12xx/acx.h    |  142 +++++++++++++++++++---------------
 drivers/net/wireless/wl12xx/init.c   |    4 +-
 drivers/net/wireless/wl12xx/main.c   |    5 +-
 drivers/net/wireless/wl12xx/wl12xx.h |    4 +
 5 files changed, 138 insertions(+), 130 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 6447a09..dfb1cbb 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -43,12 +43,13 @@ int wl1271_acx_wake_up_conditions(struct wl1271 *wl)
 	wake_up = kzalloc(sizeof(*wake_up), GFP_KERNEL);
 	if (!wake_up) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	wake_up->role_id = wl->role_id;
 	wake_up->wake_up_event = wl->conf.conn.wake_up_event;
 	wake_up->listen_interval = wl->conf.conn.listen_interval;
 
 	ret = wl1271_cmd_configure(wl, ACX_WAKE_UP_CONDITIONS,
 				   wake_up, sizeof(*wake_up));
 	if (ret < 0) {
@@ -98,12 +99,13 @@ int wl1271_acx_tx_power(struct wl1271 *wl, int power)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->current_tx_power = power * 10;
 
 	ret = wl1271_cmd_configure(wl, DOT11_CUR_TX_PWR, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("configure of tx power failed: %d", ret);
 		goto out;
@@ -125,12 +127,13 @@ int wl1271_acx_feature_cfg(struct wl1271 *wl)
 	if (!feature) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	/* DF_ENCRYPTION_DISABLE and DF_SNIFF_MODE_ENABLE are disabled */
+	feature->role_id = wl->role_id;
 	feature->data_flow_options = 0;
 	feature->options = 0;
 
 	ret = wl1271_cmd_configure(wl, ACX_FEATURE_CFG,
 				   feature, sizeof(*feature));
 	if (ret < 0) {
@@ -219,12 +222,13 @@ int wl1271_acx_slot(struct wl1271 *wl, enum acx_slot_type slot_time)
 	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
 	if (!slot) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	slot->role_id = wl->role_id;
 	slot->wone_index = STATION_WONE_INDEX;
 	slot->slot_time = slot_time;
 
 	ret = wl1271_cmd_configure(wl, ACX_SLOT, slot, sizeof(*slot));
 	if (ret < 0) {
 		wl1271_warning("failed to set slot time: %d", ret);
@@ -248,12 +252,13 @@ int wl1271_acx_group_address_tbl(struct wl1271 *wl, bool enable,
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	/* MAC filtering */
+	acx->role_id = wl->role_id;
 	acx->enabled = enable;
 	acx->num_groups = mc_list_len;
 	memcpy(acx->mac_table, mc_list, mc_list_len * ETH_ALEN);
 
 	ret = wl1271_cmd_configure(wl, DOT11_GROUP_ADDRESS_TBL,
 				   acx, sizeof(*acx));
@@ -277,12 +282,13 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl)
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	wl1271_debug(DEBUG_ACX, "acx service period timeout");
 
+	rx_timeout->role_id = wl->role_id;
 	rx_timeout->ps_poll_timeout = cpu_to_le16(wl->conf.rx.ps_poll_timeout);
 	rx_timeout->upsd_timeout = cpu_to_le16(wl->conf.rx.upsd_timeout);
 
 	ret = wl1271_cmd_configure(wl, ACX_SERVICE_PERIOD_TIMEOUT,
 				   rx_timeout, sizeof(*rx_timeout));
 	if (ret < 0) {
@@ -313,12 +319,13 @@ int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold)
 	rts = kzalloc(sizeof(*rts), GFP_KERNEL);
 	if (!rts) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	rts->role_id = wl->role_id;
 	rts->threshold = cpu_to_le16((u16)rts_threshold);
 
 	ret = wl1271_cmd_configure(wl, DOT11_RTS_THRESHOLD, rts, sizeof(*rts));
 	if (ret < 0) {
 		wl1271_warning("failed to set rts threshold: %d", ret);
 		goto out;
@@ -372,12 +379,13 @@ int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter)
 	beacon_filter = kzalloc(sizeof(*beacon_filter), GFP_KERNEL);
 	if (!beacon_filter) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	beacon_filter->role_id = wl->role_id;
 	beacon_filter->enable = enable_filter;
 
 	/*
 	 * When set to zero, and the filter is enabled, beacons
 	 * without the unicast TIM bit set are dropped.
 	 */
@@ -408,12 +416,13 @@ int wl1271_acx_beacon_filter_table(struct wl1271 *wl)
 	if (!ie_table) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	/* configure default beacon pass-through rules */
+	ie_table->role_id = wl->role_id;
 	ie_table->num_ie = 0;
 	for (i = 0; i < wl->conf.conn.bcn_filt_ie_count; i++) {
 		struct conf_bcn_filt_rule *r = &(wl->conf.conn.bcn_filt_ie[i]);
 		ie_table->table[idx++] = r->ie;
 		ie_table->table[idx++] = r->rule;
 
@@ -469,12 +478,13 @@ int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable)
 
 	if (enable) {
 		threshold = wl->conf.conn.synch_fail_thold;
 		timeout = wl->conf.conn.bss_lose_timeout;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->synch_fail_thold = cpu_to_le32(threshold);
 	acx->bss_lose_timeout = cpu_to_le32(timeout);
 
 	ret = wl1271_cmd_configure(wl, ACX_CONN_MONIT_PARAMS,
 				   acx, sizeof(*acx));
 	if (ret < 0) {
@@ -616,12 +626,13 @@ int wl1271_acx_bcn_dtim_options(struct wl1271 *wl)
 	bb = kzalloc(sizeof(*bb), GFP_KERNEL);
 	if (!bb) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	bb->role_id = wl->role_id;
 	bb->beacon_rx_timeout = cpu_to_le16(wl->conf.conn.beacon_rx_timeout);
 	bb->broadcast_timeout = cpu_to_le16(wl->conf.conn.broadcast_timeout);
 	bb->rx_broadcast_in_ps = wl->conf.conn.rx_broadcast_in_ps;
 	bb->ps_poll_threshold = wl->conf.conn.ps_poll_threshold;
 
 	ret = wl1271_cmd_configure(wl, ACX_BCN_DTIM_OPTIONS, bb, sizeof(*bb));
@@ -645,12 +656,13 @@ int wl1271_acx_aid(struct wl1271 *wl, u16 aid)
 	acx_aid = kzalloc(sizeof(*acx_aid), GFP_KERNEL);
 	if (!acx_aid) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx_aid->role_id = wl->role_id;
 	acx_aid->aid = cpu_to_le16(aid);
 
 	ret = wl1271_cmd_configure(wl, ACX_AID, acx_aid, sizeof(*acx_aid));
 	if (ret < 0) {
 		wl1271_warning("failed to set aid: %d", ret);
 		goto out;
@@ -700,12 +712,13 @@ int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->preamble = preamble;
 
 	ret = wl1271_cmd_configure(wl, ACX_PREAMBLE_TYPE, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("Setting of preamble failed: %d", ret);
 		goto out;
@@ -727,12 +740,13 @@ int wl1271_acx_cts_protect(struct wl1271 *wl,
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->ctsprotect = ctsprotect;
 
 	ret = wl1271_cmd_configure(wl, ACX_CTS_PROTECTION, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("Setting of ctsprotect failed: %d", ret);
 		goto out;
@@ -758,45 +772,49 @@ int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats)
 
 	return 0;
 }
 
 int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
 {
-	struct acx_sta_rate_policy *acx;
+	struct acx_rate_policy *acx;
 	struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
-	int idx = 0;
 	int ret = 0;
 
 	wl1271_debug(DEBUG_ACX, "acx rate policies");
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
+		wl->basic_rate, wl->rate_set);
+
 	/* configure one basic rate class */
-	idx = ACX_TX_BASIC_RATE;
-	acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->basic_rate);
-	acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
-	acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
-	acx->rate_class[idx].aflags = c->aflags;
+	acx->rate_policy_idx = cpu_to_le32(ACX_TX_BASIC_RATE);
+	acx->rate_policy.enabled_rates = cpu_to_le32(wl->basic_rate);
+	acx->rate_policy.short_retry_limit = c->short_retry_limit;
+	acx->rate_policy.long_retry_limit = c->long_retry_limit;
+	acx->rate_policy.aflags = c->aflags;
+
+	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("Setting of rate policies failed: %d", ret);
+		goto out;
+	}
 
 	/* configure one AP supported rate class */
-	idx = ACX_TX_AP_FULL_RATE;
-	acx->rate_class[idx].enabled_rates = cpu_to_le32(wl->rate_set);
-	acx->rate_class[idx].short_retry_limit = c->short_retry_limit;
-	acx->rate_class[idx].long_retry_limit = c->long_retry_limit;
-	acx->rate_class[idx].aflags = c->aflags;
+	acx->rate_policy_idx = cpu_to_le32(ACX_TX_AP_FULL_RATE);
+	acx->rate_policy.enabled_rates = cpu_to_le32(wl->rate_set);
+	acx->rate_policy.short_retry_limit = c->short_retry_limit;
+	acx->rate_policy.long_retry_limit = c->long_retry_limit;
+	acx->rate_policy.aflags = c->aflags;
 
-	acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
 
-	wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
-		acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
-		acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
 
 	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("Setting of rate policies failed: %d", ret);
 		goto out;
 	}
@@ -806,13 +824,13 @@ out:
 	return ret;
 }
 
 int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
 		      u8 idx)
 {
-	struct acx_ap_rate_policy *acx;
+	struct acx_rate_policy *acx;
 	int ret = 0;
 
 	wl1271_debug(DEBUG_ACX, "acx ap rate policy %d rates 0x%x",
 		     idx, c->enabled_rates);
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
@@ -852,12 +870,13 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
 
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->ac = ac;
 	acx->cw_min = cw_min;
 	acx->cw_max = cpu_to_le16(cw_max);
 	acx->aifsn = aifsn;
 	acx->tx_op_limit = cpu_to_le16(txop);
 
@@ -885,12 +904,13 @@ int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
 
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->queue_id = queue_id;
 	acx->channel_type = channel_type;
 	acx->tsid = tsid;
 	acx->ps_scheme = ps_scheme;
 	acx->ack_policy = ack_policy;
 	acx->apsd_conf[0] = cpu_to_le32(apsd_conf0);
@@ -964,58 +984,15 @@ int wl1271_acx_tx_config_options(struct wl1271 *wl)
 
 out:
 	kfree(acx);
 	return ret;
 }
 
-int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
-{
-	struct wl1271_acx_ap_config_memory *mem_conf;
-	struct conf_memory_settings *mem;
-	int ret;
-
-	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
-
-	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
-	if (!mem_conf) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	if (wl->chip.id == CHIP_ID_1283_PG20)
-		/*
-		 * FIXME: The 128x AP FW does not yet support dynamic memory.
-		 * Use the base memory configuration for 128x for now. This
-		 * should be fine tuned in the future.
-		 */
-		mem = &wl->conf.mem_wl128x;
-	else
-		mem = &wl->conf.mem_wl127x;
-
-	/* memory config */
-	mem_conf->num_stations = mem->num_stations;
-	mem_conf->rx_mem_block_num = mem->rx_block_num;
-	mem_conf->tx_min_mem_block_num = mem->tx_min_block_num;
-	mem_conf->num_ssid_profiles = mem->ssid_profiles;
-	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
-
-	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
-				   sizeof(*mem_conf));
-	if (ret < 0) {
-		wl1271_warning("wl1271 mem config failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(mem_conf);
-	return ret;
-}
-
-int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
+int wl12xx_acx_mem_cfg(struct wl1271 *wl)
 {
-	struct wl1271_acx_sta_config_memory *mem_conf;
+	struct wl12xx_acx_config_memory *mem_conf;
 	struct conf_memory_settings *mem;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
 
 	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
@@ -1152,12 +1129,13 @@ int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->enable = enable ? CONF_BET_MODE_ENABLE : CONF_BET_MODE_DISABLE;
 	acx->max_consecutive = wl->conf.conn.bet_max_consecutive;
 
 	ret = wl1271_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx bet enable failed: %d", ret);
@@ -1179,12 +1157,13 @@ int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->version = ACX_IPV4_VERSION;
 	acx->enable = enable;
 
 	if (enable)
 		memcpy(acx->address, &address, ACX_IPV4_ADDR_SIZE);
 
@@ -1238,12 +1217,13 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->enabled = enable;
 
 	ret = wl1271_cmd_configure(wl, ACX_KEEP_ALIVE_MODE, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx keep alive mode failed: %d", ret);
 		goto out;
@@ -1264,12 +1244,13 @@ int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->period = cpu_to_le32(wl->conf.conn.keep_alive_interval);
 	acx->index = index;
 	acx->tpl_validation = tpl_valid;
 	acx->trigger = ACX_KEEP_ALIVE_NO_TX;
 
 	ret = wl1271_cmd_configure(wl, ACX_SET_KEEP_ALIVE_CONFIG,
@@ -1297,12 +1278,13 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	wl->last_rssi_event = -1;
 
+	acx->role_id = wl->role_id;
 	acx->pacing = cpu_to_le16(wl->conf.roam_trigger.trigger_pacing);
 	acx->metric = WL1271_ACX_TRIG_METRIC_RSSI_BEACON;
 	acx->type = WL1271_ACX_TRIG_TYPE_EDGE;
 	if (enable)
 		acx->enable = WL1271_ACX_TRIG_ENABLE;
 	else
@@ -1335,12 +1317,13 @@ int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl)
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->rssi_beacon = c->avg_weight_rssi_beacon;
 	acx->rssi_data = c->avg_weight_rssi_data;
 	acx->snr_beacon = c->avg_weight_snr_beacon;
 	acx->snr_data = c->avg_weight_snr_data;
 
 	ret = wl1271_cmd_configure(wl, ACX_RSSI_SNR_WEIGHTS, acx, sizeof(*acx));
@@ -1356,13 +1339,12 @@ out:
 
 int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 				    struct ieee80211_sta_ht_cap *ht_cap,
 				    bool allow_ht_operation)
 {
 	struct wl1271_acx_ht_capabilities *acx;
-	u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	int ret = 0;
 	u32 ht_capabilites = 0;
 
 	wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
@@ -1387,13 +1369,13 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 
 		/* get data from A-MPDU parameters field */
 		acx->ampdu_max_length = ht_cap->ampdu_factor;
 		acx->ampdu_min_spacing = ht_cap->ampdu_density;
 	}
 
-	memcpy(acx->mac_address, mac_address, ETH_ALEN);
+	acx->hlid = wl->sta_hlid;
 	acx->ht_capabilites = cpu_to_le32(ht_capabilites);
 
 	ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx ht capabilities setting failed: %d", ret);
 		goto out;
@@ -1415,12 +1397,13 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	acx->role_id = wl->role_id;
 	acx->ht_protection =
 		(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
 	acx->rifs_mode = 0;
 	acx->gf_protection =
 		!!(ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 	acx->ht_tx_burst_limit = 0;
@@ -1575,12 +1558,13 @@ int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable)
 		 * this check assumes conf.rx_streaming.queues can't
 		 * be changed while rx_streaming is enabled.
 		 */
 		if (!(conf_queues & BIT(i)))
 			continue;
 
+		rx_streaming->role_id = wl->role_id;
 		rx_streaming->tid = i;
 		rx_streaming->enable = enable_queues & BIT(i);
 		rx_streaming->period = wl->conf.rx_streaming.interval;
 		rx_streaming->timeout = wl->conf.rx_streaming.interval;
 
 		ret = wl1271_cmd_configure(wl, ACX_PS_RX_STREAMING,
@@ -1604,12 +1588,13 @@ int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl)
 	wl1271_debug(DEBUG_ACX, "acx ap max tx retry");
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx)
 		return -ENOMEM;
 
+	acx->role_id = wl->role_id;
 	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.max_tx_retries);
 
 	ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx ap max tx retry failed: %d", ret);
 		goto out;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 4ae0085..67258a1 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -98,12 +98,23 @@ struct acx_error_counter {
 
 	/* the number of missed sequence numbers in the squentially */
 	/* values of frames seq numbers */
 	__le32 seq_num_miss;
 } __packed;
 
+enum wl12xx_role {
+	WL1271_ROLE_STA = 0,
+	WL1271_ROLE_IBSS,
+	WL1271_ROLE_AP,
+	WL1271_ROLE_DEVICE,
+	WL1271_ROLE_P2P_CL,
+	WL1271_ROLE_P2P_GO,
+
+	WL12XX_INVALID_ROLE_TYPE = 0xff
+};
+
 enum wl1271_psm_mode {
 	/* Active mode */
 	WL1271_PSM_CAM = 0,
 
 	/* Power save mode */
 	WL1271_PSM_PS = 1,
@@ -176,57 +187,64 @@ enum acx_slot_type {
 
 #define STATION_WONE_INDEX 0
 
 struct acx_slot {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 wone_index; /* Reserved */
 	u8 slot_time;
-	u8 reserved[6];
+	u8 reserved[5];
 } __packed;
 
 
 #define ACX_MC_ADDRESS_GROUP_MAX	(8)
 #define ADDRESS_GROUP_MAX_LEN	        (ETH_ALEN * ACX_MC_ADDRESS_GROUP_MAX)
 
 struct acx_dot11_grp_addr_tbl {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 enabled;
 	u8 num_groups;
-	u8 pad[2];
+	u8 pad[1];
 	u8 mac_table[ADDRESS_GROUP_MAX_LEN];
 } __packed;
 
 struct acx_rx_timeout {
 	struct acx_header header;
 
+	u8 role_id;
+	u8 reserved;
 	__le16 ps_poll_timeout;
 	__le16 upsd_timeout;
+	u8 padding[2];
 } __packed;
 
 struct acx_rts_threshold {
 	struct acx_header header;
 
+	u8 role_id;
+	u8 reserved;
 	__le16 threshold;
-	u8 pad[2];
 } __packed;
 
 struct acx_beacon_filter_option {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 enable;
 	/*
 	 * The number of beacons without the unicast TIM
 	 * bit set that the firmware buffers before
 	 * signaling the host about ready frames.
 	 * When set to 0 and the filter is enabled, beacons
 	 * without the unicast TIM bit set are dropped.
 	 */
 	u8 max_num_beacons;
-	u8 pad[2];
+	u8 pad[1];
 } __packed;
 
 /*
  * ACXBeaconFilterEntry (not 221)
  * Byte Offset     Size (Bytes)    Definition
  * ===========     ============    ==========
@@ -259,20 +277,23 @@ struct acx_beacon_filter_option {
 			   (BEACON_FILTER_TABLE_MAX_VENDOR_SPECIFIC_IE_NUM * \
 			    BEACON_FILTER_TABLE_EXTRA_VENDOR_SPECIFIC_IE_SIZE))
 
 struct acx_beacon_filter_ie_table {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 num_ie;
-	u8 pad[3];
+	u8 pad[2];
 	u8 table[BEACON_FILTER_TABLE_MAX_SIZE];
 } __packed;
 
 struct acx_conn_monit_params {
        struct acx_header header;
 
+	   u8 role_id;
+	   u8 padding[3];
        __le32 synch_fail_thold; /* number of beacons missed */
        __le32 bss_lose_timeout; /* number of TU's from synch fail */
 } __packed;
 
 struct acx_bt_wlan_coex {
 	struct acx_header header;
@@ -315,21 +336,22 @@ struct acx_energy_detection {
 	u8 pad;
 } __packed;
 
 struct acx_beacon_broadcast {
 	struct acx_header header;
 
-	__le16 beacon_rx_timeout;
-	__le16 broadcast_timeout;
-
+	u8 role_id;
 	/* Enables receiving of broadcast packets in PS mode */
 	u8 rx_broadcast_in_ps;
 
+	__le16 beacon_rx_timeout;
+	__le16 broadcast_timeout;
+
 	/* Consecutive PS Poll failures before updating the host */
 	u8 ps_poll_threshold;
-	u8 pad[2];
+	u8 pad[1];
 } __packed;
 
 struct acx_event_mask {
 	struct acx_header header;
 
 	__le32 event_mask;
@@ -345,39 +367,44 @@ struct acx_event_mask {
 #define DF_ENCRYPTION_DISABLE      0x01
 #define DF_SNIFF_MODE_ENABLE       0x80
 
 struct acx_feature_config {
 	struct acx_header header;
 
+	u8 role_id;
+	u8 padding[3];
 	__le32 options;
 	__le32 data_flow_options;
 } __packed;
 
 struct acx_current_tx_power {
 	struct acx_header header;
 
+	u8  role_id;
 	u8  current_tx_power;
-	u8  padding[3];
+	u8  padding[2];
 } __packed;
 
 struct acx_wake_up_condition {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 wake_up_event; /* Only one bit can be set */
 	u8 listen_interval;
-	u8 pad[2];
+	u8 pad[1];
 } __packed;
 
 struct acx_aid {
 	struct acx_header header;
 
 	/*
 	 * To be set when associated with an AP.
 	 */
+	u8 role_id;
+	u8 reserved;
 	__le16 aid;
-	u8 pad[2];
 } __packed;
 
 enum acx_preamble_type {
 	ACX_PREAMBLE_LONG = 0,
 	ACX_PREAMBLE_SHORT = 1
 };
@@ -386,25 +413,27 @@ struct acx_preamble {
 	struct acx_header header;
 
 	/*
 	 * When set, the WiLink transmits the frames with a short preamble and
 	 * when cleared, the WiLink transmits the frames with a long preamble.
 	 */
+	u8 role_id;
 	u8 preamble;
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
 enum acx_ctsprotect_type {
 	CTSPROTECT_DISABLE = 0,
 	CTSPROTECT_ENABLE = 1
 };
 
 struct acx_ctsprotect {
 	struct acx_header header;
+	u8 role_id;
 	u8 ctsprotect;
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
 struct acx_tx_statistics {
 	__le32 internal_desc_overflow;
 }  __packed;
 
@@ -633,48 +662,40 @@ struct acx_rate_class {
 	u8 aflags;
 	u8 reserved;
 };
 
 #define ACX_TX_BASIC_RATE      0
 #define ACX_TX_AP_FULL_RATE    1
-#define ACX_TX_RATE_POLICY_CNT 2
-struct acx_sta_rate_policy {
-	struct acx_header header;
-
-	__le32 rate_class_cnt;
-	struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
-} __packed;
-
-
 #define ACX_TX_AP_MODE_MGMT_RATE 4
 #define ACX_TX_AP_MODE_BCST_RATE 5
-struct acx_ap_rate_policy {
+struct acx_rate_policy {
 	struct acx_header header;
 
 	__le32 rate_policy_idx;
 	struct acx_rate_class rate_policy;
 } __packed;
 
 struct acx_ac_cfg {
 	struct acx_header header;
+	u8 role_id;
 	u8 ac;
+	u8 aifsn;
 	u8 cw_min;
 	__le16 cw_max;
-	u8 aifsn;
-	u8 reserved;
 	__le16 tx_op_limit;
 } __packed;
 
 struct acx_tid_config {
 	struct acx_header header;
+	u8 role_id;
 	u8 queue_id;
 	u8 channel_type;
 	u8 tsid;
 	u8 ps_scheme;
 	u8 ack_policy;
-	u8 padding[3];
+	u8 padding[2];
 	__le32 apsd_conf[2];
 } __packed;
 
 struct acx_frag_threshold {
 	struct acx_header header;
 	__le16 frag_threshold;
@@ -684,25 +705,13 @@ struct acx_frag_threshold {
 struct acx_tx_config_options {
 	struct acx_header header;
 	__le16 tx_compl_timeout;     /* msec */
 	__le16 tx_compl_threshold;   /* number of packets */
 } __packed;
 
-#define ACX_TX_DESCRIPTORS    32
-
-struct wl1271_acx_ap_config_memory {
-	struct acx_header header;
-
-	u8 rx_mem_block_num;
-	u8 tx_min_mem_block_num;
-	u8 num_stations;
-	u8 num_ssid_profiles;
-	__le32 total_tx_descriptors;
-} __packed;
-
-struct wl1271_acx_sta_config_memory {
+struct wl12xx_acx_config_memory {
 	struct acx_header header;
 
 	u8 rx_mem_block_num;
 	u8 tx_min_mem_block_num;
 	u8 num_stations;
 	u8 num_ssid_profiles;
@@ -770,30 +779,32 @@ struct wl1271_acx_rx_config_opt {
 } __packed;
 
 
 struct wl1271_acx_bet_enable {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 enable;
 	u8 max_consecutive;
-	u8 padding[2];
+	u8 padding[1];
 } __packed;
 
 #define ACX_IPV4_VERSION 4
 #define ACX_IPV6_VERSION 6
 #define ACX_IPV4_ADDR_SIZE 4
 
 /* bitmap of enabled arp_filter features */
 #define ACX_ARP_FILTER_ARP_FILTERING	BIT(0)
 #define ACX_ARP_FILTER_AUTO_ARP		BIT(1)
 
 struct wl1271_acx_arp_filter {
 	struct acx_header header;
+	u8 role_id;
 	u8 version;         /* ACX_IPV4_VERSION, ACX_IPV6_VERSION */
 	u8 enable;          /* bitmap of enabled ARP filtering features */
-	u8 padding[2];
+	u8 padding[1];
 	u8 address[16];     /* The configured device IP address - all ARP
 			       requests directed to this IP address will pass
 			       through. For IPv4, the first four bytes are
 			       used. */
 } __packed;
 
@@ -805,14 +816,15 @@ struct wl1271_acx_pm_config {
 	u8 padding[3];
 } __packed;
 
 struct wl1271_acx_keep_alive_mode {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 enabled;
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
 enum {
 	ACX_KEEP_ALIVE_NO_TX = 0,
 	ACX_KEEP_ALIVE_PERIOD_ONLY
 };
@@ -822,17 +834,17 @@ enum {
 	ACX_KEEP_ALIVE_TPL_VALID
 };
 
 struct wl1271_acx_keep_alive_config {
 	struct acx_header header;
 
-	__le32 period;
+	u8 role_id;
 	u8 index;
 	u8 tpl_validation;
 	u8 trigger;
-	u8 padding;
+	__le32 period;
 } __packed;
 
 #define HOST_IF_CFG_RX_FIFO_ENABLE     BIT(0)
 #define HOST_IF_CFG_TX_EXTRA_BLKS_SWAP BIT(1)
 #define HOST_IF_CFG_TX_PAD_TO_SDIO_BLK BIT(3)
 
@@ -870,26 +882,29 @@ enum {
 	WL1271_ACX_TRIG_COUNT = 8,
 };
 
 struct wl1271_acx_rssi_snr_trigger {
 	struct acx_header header;
 
-	__le16 threshold;
-	__le16 pacing; /* 0 - 60000 ms */
+	u8 role_id;
 	u8 metric;
 	u8 type;
 	u8 dir;
+	__le16 threshold;
+	__le16 pacing; /* 0 - 60000 ms */
 	u8 hysteresis;
 	u8 index;
 	u8 enable;
-	u8 padding[2];
+	u8 padding[1];
 };
 
 struct wl1271_acx_rssi_snr_avg_weights {
 	struct acx_header header;
 
+	u8 role_id;
+	u8 padding[3];
 	u8 rssi_beacon;
 	u8 rssi_data;
 	u8 snr_beacon;
 	u8 snr_data;
 };
 
@@ -913,28 +928,25 @@ struct wl1271_acx_ht_capabilities {
 	 * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD.
 	 *         Exact policy setting for this feature is TBD.
 	 *         Note, this bit can only be set to 1 if bit 3 is set to 1.
 	 */
 	__le32 ht_capabilites;
 
-	/*
-	 * Indicates to which peer these capabilities apply.
-	 * For infrastructure use ff:ff:ff:ff:ff:ff that indicates relevance
-	 * for all peers.
-	 * Only valid for IBSS/DLS operation.
-	 */
-	u8 mac_address[ETH_ALEN];
+	/* Indicates to which link these capabilities apply. */
+	u8 hlid;
 
 	/*
 	 * This the maximum A-MPDU length supported by the AP. The FW may not
 	 * exceed this length when sending A-MPDUs
 	 */
 	u8 ampdu_max_length;
 
 	/* This is the minimal spacing required when sending A-MPDUs to the AP*/
 	u8 ampdu_min_spacing;
+
+	u8 padding;
 } __packed;
 
 /* HT Capabilites Fw Bit Mask Mapping */
 #define WL1271_ACX_FW_CAP_HT_OPERATION                 BIT(0)
 #define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT      BIT(1)
 #define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS   BIT(2)
@@ -947,12 +959,14 @@ struct wl1271_acx_ht_capabilities {
  * ACX_HT_BSS_OPERATION
  * Configure HT capabilities - AP rules for behavior in the BSS.
  */
 struct wl1271_acx_ht_information {
 	struct acx_header header;
 
+	u8 role_id;
+
 	/* Values: 0 - RIFS not allowed, 1 - RIFS allowed */
 	u8 rifs_mode;
 
 	/* Values: 0 - 3 like in spec */
 	u8 ht_protection;
 
@@ -968,13 +982,13 @@ struct wl1271_acx_ht_information {
 	 * Note: When this value is set to 1 FW will protect all TXOP with RTS
 	 * frame and will not use CTS-to-self regardless of the value of the
 	 * ACX_CTS_PROTECTION information element
 	 */
 	u8 dual_cts_protection;
 
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
 #define RX_BA_WIN_SIZE 8
 
 struct wl1271_acx_ba_session_policy {
 	struct acx_header header;
@@ -1038,31 +1052,35 @@ struct wl1271_acx_fw_tsf_information {
 	u8 padding[3];
 } __packed;
 
 struct wl1271_acx_ps_rx_streaming {
 	struct acx_header header;
 
+	u8 role_id;
 	u8 tid;
 	u8 enable;
 
 	/* interval between triggers (10-100 msec) */
 	u8 period;
 
 	/* timeout before first trigger (0-200 msec) */
 	u8 timeout;
+	u8 padding[3];
 } __packed;
 
 struct wl1271_acx_ap_max_tx_retry {
 	struct acx_header header;
 
+	u8 role_id;
+	u8 padding_1;
+
 	/*
 	 * the number of frames transmission failures before
 	 * issuing the aging event.
 	 */
 	__le16 max_tx_retry;
-	u8 padding_1[2];
 } __packed;
 
 struct wl1271_acx_config_ps {
 	struct acx_header header;
 
 	u8 exit_retries;
@@ -1148,16 +1166,13 @@ enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
 	ACX_SLOT                    = 0x0004,
 	ACX_AC_CFG                  = 0x0007,
 	ACX_MEM_MAP                 = 0x0008,
 	ACX_AID                     = 0x000A,
-	/* ACX_FW_REV is missing in the ref driver, but seems to work */
-	ACX_FW_REV                  = 0x000D,
 	ACX_MEDIUM_USAGE            = 0x000F,
-	ACX_RX_CFG                  = 0x0010,
 	ACX_TX_QUEUE_CFG            = 0x0011, /* FIXME: only used by wl1251 */
 	ACX_STATISTICS              = 0x0013, /* Debug API */
 	ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
 	ACX_FEATURE_CFG             = 0x0015,
 	ACX_TID_CFG                 = 0x001A,
 	ACX_PS_RX_STREAMING         = 0x001B,
@@ -1167,13 +1182,12 @@ enum {
 	ACX_HDK_VERSION             = 0x0022, /* ??? */
 	ACX_PD_THRESHOLD            = 0x0023,
 	ACX_TX_CONFIG_OPT           = 0x0024,
 	ACX_CCA_THRESHOLD           = 0x0025,
 	ACX_EVENT_MBOX_MASK         = 0x0026,
 	ACX_CONN_MONIT_PARAMS       = 0x002D,
-	ACX_CONS_TX_FAILURE         = 0x002F,
 	ACX_BCN_DTIM_OPTIONS        = 0x0031,
 	ACX_SG_ENABLE               = 0x0032,
 	ACX_SG_CFG                  = 0x0033,
 	ACX_FM_COEX_CFG             = 0x0034,
 	ACX_BEACON_FILTER_TABLE     = 0x0038,
 	ACX_ARP_IP_FILTER           = 0x0039,
@@ -1199,12 +1213,15 @@ enum {
 	ACX_SET_KEEP_ALIVE_CONFIG   = 0x0054,
 	ACX_BA_SESSION_POLICY_CFG   = 0x0055,
 	ACX_BA_SESSION_RX_SETUP     = 0x0056,
 	ACX_PEER_HT_CAP             = 0x0057,
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
+	ACX_BURST_MODE              = 0x005C,
+	ACX_SET_RATE_MGMT_PARAMS    = 0x005D,
+	ACX_SET_RATE_ADAPT_PARAMS   = 0x0060,
 	ACX_SET_DCO_ITRIM_PARAMS    = 0x0061,
 	ACX_GEN_FW_CMD              = 0x0070,
 	ACX_HOST_IF_CFG_BITMAP      = 0x0071,
 	ACX_MAX_TX_FAILURE          = 0x0072,
 	ACX_UPDATE_INCONNECTION_STA_LIST = 0x0073,
 	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
@@ -1253,14 +1270,13 @@ int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifsn, u16 txop);
 int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
 		       u8 tsid, u8 ps_scheme, u8 ack_policy,
 		       u32 apsd_conf0, u32 apsd_conf1);
 int wl1271_acx_frag_threshold(struct wl1271 *wl, u32 frag_threshold);
 int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
-int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
+int wl12xx_acx_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_host_if_cfg_bitmap(struct wl1271 *wl, u32 host_cfg_bitmap);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
 int wl1271_acx_bet_enable(struct wl1271 *wl, bool enable);
 int wl1271_acx_arp_ip_filter(struct wl1271 *wl, u8 enable, __be32 address);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 44cd515..5a33257 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -385,13 +385,13 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
 		return ret;
 
 	ret = wl1271_acx_sta_rate_policies(wl);
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_sta_mem_cfg(wl);
+	ret = wl12xx_acx_mem_cfg(wl);
 	if (ret < 0)
 		return ret;
 
 	/* Configure the FW logger */
 	ret = wl12xx_init_fwlog(wl);
 	if (ret < 0)
@@ -444,13 +444,13 @@ static int wl1271_ap_hw_init(struct wl1271 *wl)
 		return ret;
 
 	ret = wl1271_acx_ap_max_tx_retry(wl);
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_ap_mem_cfg(wl);
+	ret = wl12xx_acx_mem_cfg(wl);
 	if (ret < 0)
 		return ret;
 
 	/* initialize Tx power */
 	ret = wl1271_acx_tx_power(wl, wl->power_level);
 	if (ret < 0)
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 96f76b1..07d50b7 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -715,13 +715,13 @@ static int wl1271_plt_init(struct wl1271 *wl)
 
 	/* Energy detection */
 	ret = wl1271_init_energy_detection(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	ret = wl1271_acx_sta_mem_cfg(wl);
+	ret = wl12xx_acx_mem_cfg(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
 	/* Default fragmentation threshold */
 	ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
 	if (ret < 0)
@@ -1978,12 +1978,13 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	wl->vif = NULL;
 	wl1271_free_ap_keys(wl);
 	memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
 	wl->ap_fw_ps_map = 0;
 	wl->ap_ps_map = 0;
 	wl->sched_scanning = false;
+	wl->role_id = WL12XX_INVALID_ROLE_ID;
 
 	/*
 	 * this is performed after the cancel_work calls and the associated
 	 * mutex_lock, so that wl1271_op_add_interface does not accidentally
 	 * get executed before all these vars have been reset.
 	 */
@@ -4314,12 +4315,14 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->ap_fw_ps_map = 0;
 	wl->quirks = 0;
 	wl->platform_quirks = 0;
 	wl->sched_scanning = false;
 	wl->tx_security_seq = 0;
 	wl->tx_security_last_seq_lsb = 0;
+	wl->role_id = WL12XX_INVALID_ROLE_ID;
+	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
 
 	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
 		    (unsigned long) wl);
 	wl->fwlog_size = 0;
 	init_waitqueue_head(&wl->fwlog_waitq);
 
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index f708cd7..9f71dc7 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -135,12 +135,14 @@ extern u32 wl12xx_debug_level;
 #define WL1271_ELP_HW_STATE_IRQ    1
 
 #define WL1271_DEFAULT_BEACON_INT  100
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
 #define WL12XX_MAX_LINKS           8
+#define WL12XX_INVALID_ROLE_ID     0xff
+#define WL12XX_INVALID_LINK_ID     0xff
 #define WL1271_AP_GLOBAL_HLID      0
 #define WL1271_AP_BROADCAST_HLID   1
 #define WL1271_AP_STA_HLID_START   2
 
 /*
  * When in AP-mode, we allow (at least) this number of mem-blocks
@@ -387,12 +389,14 @@ struct wl1271 {
 	u8 mac_addr[ETH_ALEN];
 	u8 bss_type;
 	u8 set_bss_type;
 	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
 	u8 ssid_len;
 	int channel;
+	u8 role_id;
+	u8 sta_hlid;
 
 	struct wl1271_acx_mem_map *target_mem_map;
 
 	/* Accounting for allocated / available TX blocks on HW */
 	u32 tx_blocks_freed;
 	u32 tx_blocks_available;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 08/40] wl12xx: update commands & events
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (6 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 07/40] wl12xx: update acx commands Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 09/40] wl12xx: enable/disable role on interface add/remove Eliad Peller
                   ` (32 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Change the commands and events according to the new fw api
(fw >= 6/7.3.0.0.75).

The main change is the replacement of JOIN/DISCONNECT commands,
with ROLE_START/ROLE_STOP commands.

The use of these commands should be preceded by the ROLE_ENABLE
command (allocating role resources), and followed by the
ROLE_DISABLE command (freeing role resources).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: unify event_mask, s/wl1271/wl12xx, improve debug prints
and ret values, etc.

 drivers/net/wireless/wl12xx/boot.c   |   17 +-
 drivers/net/wireless/wl12xx/cmd.c    |  515 ++++++++++++++++++++--------------
 drivers/net/wireless/wl12xx/cmd.h    |  314 +++++++++++----------
 drivers/net/wireless/wl12xx/event.c  |    4 +-
 drivers/net/wireless/wl12xx/event.h  |   80 ++----
 drivers/net/wireless/wl12xx/init.c   |    6 -
 drivers/net/wireless/wl12xx/main.c   |   26 +-
 drivers/net/wireless/wl12xx/tx.c     |    5 +-
 drivers/net/wireless/wl12xx/wl12xx.h |    5 +
 9 files changed, 527 insertions(+), 445 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/boot.c b/drivers/net/wireless/wl12xx/boot.c
index 41791ff..cc70422 100644
--- a/drivers/net/wireless/wl12xx/boot.c
+++ b/drivers/net/wireless/wl12xx/boot.c
@@ -491,27 +491,24 @@ static int wl1271_boot_run_firmware(struct wl1271 *wl)
 	 */
 
 	/* unmask required mbox events  */
 	wl->event_mask = BSS_LOSE_EVENT_ID |
 		SCAN_COMPLETE_EVENT_ID |
 		PS_REPORT_EVENT_ID |
-		JOIN_EVENT_COMPLETE_ID |
 		DISCONNECT_EVENT_COMPLETE_ID |
 		RSSI_SNR_TRIGGER_0_EVENT_ID |
 		PSPOLL_DELIVERY_FAILURE_EVENT_ID |
 		SOFT_GEMINI_SENSE_EVENT_ID |
 		PERIODIC_SCAN_REPORT_EVENT_ID |
-		PERIODIC_SCAN_COMPLETE_EVENT_ID;
-
-	if (wl->bss_type == BSS_TYPE_AP_BSS)
-		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID |
-				  INACTIVE_STA_EVENT_ID |
-				  MAX_TX_RETRY_EVENT_ID;
-	else
-		wl->event_mask |= DUMMY_PACKET_EVENT_ID |
-			BA_SESSION_RX_CONSTRAINT_EVENT_ID;
+		PERIODIC_SCAN_COMPLETE_EVENT_ID |
+		DUMMY_PACKET_EVENT_ID |
+		PEER_REMOVE_COMPLETE_EVENT_ID |
+		BA_SESSION_RX_CONSTRAINT_EVENT_ID |
+		REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID |
+		INACTIVE_STA_EVENT_ID |
+		MAX_TX_RETRY_EVENT_ID;
 
 	ret = wl1271_event_unmask(wl);
 	if (ret < 0) {
 		wl1271_error("EVENT mask setting failed");
 		return ret;
 	}
diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index b6ef65a..b13eed1 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -360,67 +360,300 @@ static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
 		return ret;
 	}
 
 	return 0;
 }
 
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
+int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id)
 {
-	struct wl1271_cmd_join *join;
-	int ret, i;
-	u8 *bssid;
+	struct wl12xx_cmd_role_enable *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd role enable");
+
+	if (WARN_ON(*role_id != WL12XX_INVALID_ROLE_ID))
+		return -EBUSY;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* get role id */
+	cmd->role_id = find_first_zero_bit(wl->roles_map, WL12XX_MAX_ROLES);
+	if (cmd->role_id >= WL12XX_MAX_ROLES) {
+		ret = -EBUSY;
+		goto out_free;
+	}
+
+	memcpy(cmd->mac_address, wl->mac_addr, ETH_ALEN);
+	cmd->role_type = role_type;
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_ENABLE, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role enable");
+		goto out_free;
+	}
+
+	__set_bit(cmd->role_id, wl->roles_map);
+	*role_id = cmd->role_id;
 
-	join = kzalloc(sizeof(*join), GFP_KERNEL);
-	if (!join) {
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id)
+{
+	struct wl12xx_cmd_role_disable *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd role disable");
+
+	if (WARN_ON(*role_id == WL12XX_INVALID_ROLE_ID))
+		return -ENOENT;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
+	cmd->role_id = *role_id;
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_DISABLE, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role disable");
+		goto out_free;
+	}
 
-	wl1271_debug(DEBUG_CMD, "cmd join");
+	__clear_bit(*role_id, wl->roles_map);
+	*role_id = WL12XX_INVALID_ROLE_ID;
 
-	/* Reverse order BSSID */
-	bssid = (u8 *) &join->bssid_lsb;
-	for (i = 0; i < ETH_ALEN; i++)
-		bssid[i] = wl->bssid[ETH_ALEN - i - 1];
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+static int wl12xx_allocate_link(struct wl1271 *wl, u8 *hlid)
+{
+	u8 link = find_first_zero_bit(wl->links_map, WL12XX_MAX_LINKS);
+	if (link >= WL12XX_MAX_LINKS)
+		return -EBUSY;
+
+	__set_bit(link, wl->links_map);
+	*hlid = link;
+	return 0;
+}
+
+static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
+{
+	if (*hlid == WL12XX_INVALID_LINK_ID)
+		return;
+
+	__clear_bit(*hlid, wl->links_map);
+	*hlid = WL12XX_INVALID_LINK_ID;
+}
+
+int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_start *cmd;
+	int ret;
 
-	join->bss_type = bss_type;
-	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
-	join->supported_rate_set = cpu_to_le32(wl->rate_set);
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
+	wl1271_debug(DEBUG_CMD, "cmd role start sta %d", wl->role_id);
+
+	cmd->role_id = wl->role_id;
 	if (wl->band == IEEE80211_BAND_5GHZ)
-		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
+		cmd->band = WL12XX_BAND_5GHZ;
+	cmd->channel = wl->channel;
+	cmd->sta.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	cmd->sta.beacon_interval = cpu_to_le16(wl->beacon_int);
+	cmd->sta.ssid_type = WL12XX_SSID_TYPE_ANY;
+	cmd->sta.ssid_len = wl->ssid_len;
+	memcpy(cmd->sta.ssid, wl->ssid, wl->ssid_len);
+	memcpy(cmd->sta.bssid, wl->bssid, ETH_ALEN);
+	cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
+
+	if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
+		ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
+		if (ret)
+			goto out_free;
+	}
+	cmd->sta.hlid = wl->sta_hlid;
+	cmd->sta.session = wl->session_counter;
+	cmd->sta.remote_rates = cpu_to_le32(wl->rate_set);
+
+	wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
+		     "basic_rate_set: 0x%x, remote_rates: 0x%x",
+		     wl->role_id, cmd->sta.hlid, cmd->sta.session,
+		     wl->basic_rate_set, wl->rate_set);
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role start sta");
+		goto err_hlid;
+	}
+
+	goto out_free;
+
+err_hlid:
+	/* clear links on error. */
+	wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
 
-	join->beacon_interval = cpu_to_le16(wl->beacon_int);
-	join->dtim_interval = WL1271_DEFAULT_DTIM_PERIOD;
+int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_stop *cmd;
+	int ret;
+
+	if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID))
+		return -EINVAL;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
 
-	join->channel = wl->channel;
-	join->ssid_len = wl->ssid_len;
-	memcpy(join->ssid, wl->ssid, wl->ssid_len);
+	wl1271_debug(DEBUG_CMD, "cmd role stop sta %d", wl->role_id);
 
-	join->ctrl |= wl->session_counter << WL1271_JOIN_CMD_TX_SESSION_OFFSET;
+	cmd->role_id = wl->role_id;
+	cmd->disc_type = DISCONNECT_IMMEDIATE;
+	cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
 
-	wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
-		join->basic_rate_set, join->supported_rate_set);
+	ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role stop sta");
+		goto out_free;
+	}
 
-	ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
+	ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
 	if (ret < 0) {
-		wl1271_error("failed to initiate cmd join");
+		wl1271_error("cmd role stop sta event completion error");
 		goto out_free;
 	}
 
-	ret = wl1271_cmd_wait_for_event(wl, JOIN_EVENT_COMPLETE_ID);
-	if (ret < 0)
-		wl1271_error("cmd join event completion error");
+	wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_start *cmd;
+	struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd role start ap %d", wl->role_id);
+
+	/*
+	 * We currently do not support hidden SSID. The real SSID
+	 * should be fetched from mac80211 first.
+	 */
+	if (wl->ssid_len == 0) {
+		wl1271_warning("Hidden SSID currently not supported for AP");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->role_id = wl->role_id;
+	cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
+	cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
+	cmd->ap.global_hlid = WL1271_AP_GLOBAL_HLID;
+	cmd->ap.broadcast_hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int);
+	cmd->ap.dtim_interval = bss_conf->dtim_period;
+	cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
+	cmd->channel = wl->channel;
+	cmd->ap.ssid_len = wl->ssid_len;
+	cmd->ap.ssid_type = WL12XX_SSID_TYPE_PUBLIC;
+	memcpy(cmd->ap.ssid, wl->ssid, wl->ssid_len);
+	cmd->ap.local_rates = cpu_to_le32(0xffffffff);
+
+	switch (wl->band) {
+	case IEEE80211_BAND_2GHZ:
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		cmd->band = RADIO_BAND_5GHZ;
+		break;
+	default:
+		wl1271_warning("ap start - unknown band: %d", (int)wl->band);
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role start ap");
+		goto out_free;
+	}
 
 out_free:
-	kfree(join);
+	kfree(cmd);
 
 out:
 	return ret;
 }
 
+int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_stop *cmd;
+	int ret;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wl1271_debug(DEBUG_CMD, "cmd role stop ap %d", wl->role_id);
+
+	cmd->role_id = wl->role_id;
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role stop ap");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+
 /**
  * send test command to firmware
  *
  * @wl: wl struct
  * @buf: buffer containing the command, with all headers, must work with dma
  * @len: length of the buffer
@@ -562,12 +795,13 @@ int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
 	ps_params = kzalloc(sizeof(*ps_params), GFP_KERNEL);
 	if (!ps_params) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	ps_params->role_id = wl->role_id;
 	ps_params->ps_mode = ps_mode;
 
 	ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
 			      sizeof(*ps_params), 0);
 	if (ret < 0) {
 		wl1271_error("cmd set_ps_mode failed");
@@ -808,63 +1042,34 @@ int wl1271_build_qos_null_data(struct wl1271 *wl)
 
 	return wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, &template,
 				       sizeof(template), 0,
 				       wl->basic_rate);
 }
 
-int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
+int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid)
 {
-	struct wl1271_cmd_set_sta_keys *cmd;
+	struct wl1271_cmd_set_keys *cmd;
 	int ret = 0;
 
 	wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	cmd->id = id;
-	cmd->key_action = cpu_to_le16(KEY_SET_ID);
-	cmd->key_type = KEY_WEP;
-
-	ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
-	if (ret < 0) {
-		wl1271_warning("cmd set_default_wep_key failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(cmd);
-
-	return ret;
-}
-
-int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
-{
-	struct wl1271_cmd_set_ap_keys *cmd;
-	int ret = 0;
-
-	wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	cmd->hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->hlid = hlid;
 	cmd->key_id = id;
 	cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
 	cmd->key_action = cpu_to_le16(KEY_SET_ID);
 	cmd->key_type = KEY_WEP;
 
 	ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
-		wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
+		wl1271_warning("cmd set_default_wep_key failed: %d", ret);
 		goto out;
 	}
 
 out:
 	kfree(cmd);
 
@@ -872,35 +1077,38 @@ out:
 }
 
 int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		       u8 key_size, const u8 *key, const u8 *addr,
 		       u32 tx_seq_32, u16 tx_seq_16)
 {
-	struct wl1271_cmd_set_sta_keys *cmd;
+	struct wl1271_cmd_set_keys *cmd;
 	int ret = 0;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	if (key_type != KEY_WEP)
-		memcpy(cmd->addr, addr, ETH_ALEN);
+	cmd->hlid = wl->sta_hlid;
+
+	if (key_type == KEY_WEP)
+		cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
+	else if (is_broadcast_ether_addr(addr))
+		cmd->lid_key_type = BROADCAST_LID_TYPE;
+	else
+		cmd->lid_key_type = UNICAST_LID_TYPE;
 
 	cmd->key_action = cpu_to_le16(action);
 	cmd->key_size = key_size;
 	cmd->key_type = key_type;
 
 	cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
 	cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
 
-	/* we have only one SSID profile */
-	cmd->ssid_profile = 0;
-
-	cmd->id = id;
+	cmd->key_id = id;
 
 	if (key_type == KEY_TKIP) {
 		/*
 		 * We get the key in the following form:
 		 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
 		 * but the target is expecting:
@@ -925,17 +1133,21 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 out:
 	kfree(cmd);
 
 	return ret;
 }
 
+/*
+ * TODO: merge with sta/ibss into 1 set_key function.
+ * note there are slight diffs
+ */
 int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
 			u16 tx_seq_16)
 {
-	struct wl1271_cmd_set_ap_keys *cmd;
+	struct wl1271_cmd_set_keys *cmd;
 	int ret = 0;
 	u8 lid_type;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
@@ -986,172 +1198,46 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 
 out:
 	kfree(cmd);
 	return ret;
 }
 
-int wl1271_cmd_disconnect(struct wl1271 *wl)
-{
-	struct wl1271_cmd_disconnect *cmd;
-	int ret = 0;
-
-	wl1271_debug(DEBUG_CMD, "cmd disconnect");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* disconnect reason is not used in immediate disconnections */
-	cmd->type = DISCONNECT_IMMEDIATE;
-
-	ret = wl1271_cmd_send(wl, CMD_DISCONNECT, cmd, sizeof(*cmd), 0);
-	if (ret < 0) {
-		wl1271_error("failed to send disconnect command");
-		goto out_free;
-	}
-
-	ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
-	if (ret < 0)
-		wl1271_error("cmd disconnect event completion error");
-
-out_free:
-	kfree(cmd);
-
-out:
-	return ret;
-}
-
-int wl1271_cmd_set_sta_state(struct wl1271 *wl)
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl)
 {
-	struct wl1271_cmd_set_sta_state *cmd;
+	struct wl12xx_cmd_set_peer_state *cmd;
 	int ret = 0;
 
-	wl1271_debug(DEBUG_CMD, "cmd set sta state");
+	wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", wl->sta_hlid);
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	cmd->hlid = wl->sta_hlid;
 	cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
 
-	ret = wl1271_cmd_send(wl, CMD_SET_STA_STATE, cmd, sizeof(*cmd), 0);
+	ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
-		wl1271_error("failed to send set STA state command");
+		wl1271_error("failed to send set peer state command");
 		goto out_free;
 	}
 
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
-
-int wl1271_cmd_start_bss(struct wl1271 *wl)
-{
-	struct wl1271_cmd_bss_start *cmd;
-	struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
-	int ret;
-
-	wl1271_debug(DEBUG_CMD, "cmd start bss");
-
-	/*
-	 * FIXME: We currently do not support hidden SSID. The real SSID
-	 * should be fetched from mac80211 first.
-	 */
-	if (wl->ssid_len == 0) {
-		wl1271_warning("Hidden SSID currently not supported for AP");
-		ret = -EINVAL;
-		goto out;
-	}
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
-
-	cmd->aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
-	cmd->bss_index = WL1271_AP_BSS_INDEX;
-	cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
-	cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
-	cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
-	cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
-	cmd->dtim_interval = bss_conf->dtim_period;
-	cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
-	cmd->channel = wl->channel;
-	cmd->ssid_len = wl->ssid_len;
-	cmd->ssid_type = SSID_TYPE_PUBLIC;
-	memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
-
-	switch (wl->band) {
-	case IEEE80211_BAND_2GHZ:
-		cmd->band = RADIO_BAND_2_4GHZ;
-		break;
-	case IEEE80211_BAND_5GHZ:
-		cmd->band = RADIO_BAND_5GHZ;
-		break;
-	default:
-		wl1271_warning("bss start - unknown band: %d", (int)wl->band);
-		cmd->band = RADIO_BAND_2_4GHZ;
-		break;
-	}
-
-	ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
-	if (ret < 0) {
-		wl1271_error("failed to initiate cmd start bss");
-		goto out_free;
-	}
-
-out_free:
-	kfree(cmd);
-
-out:
-	return ret;
-}
-
-int wl1271_cmd_stop_bss(struct wl1271 *wl)
-{
-	struct wl1271_cmd_bss_start *cmd;
-	int ret;
-
-	wl1271_debug(DEBUG_CMD, "cmd stop bss");
-
-	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
-	if (!cmd) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	cmd->bss_index = WL1271_AP_BSS_INDEX;
-
-	ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
-	if (ret < 0) {
-		wl1271_error("failed to initiate cmd stop bss");
-		goto out_free;
-	}
-
-out_free:
-	kfree(cmd);
-
-out:
-	return ret;
-}
-
-int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
 {
-	struct wl1271_cmd_add_sta *cmd;
+	struct wl12xx_cmd_add_peer *cmd;
 	int ret;
 
-	wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
+	wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -1165,56 +1251,57 @@ int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
 	cmd->hlid = hlid;
 	cmd->wmm = sta->wme ? 1 : 0;
 
 	cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
 						sta->supp_rates[wl->band]));
 
-	wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
+	wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates);
 
-	ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
+	ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
-		wl1271_error("failed to initiate cmd add sta");
+		wl1271_error("failed to initiate cmd add peer");
 		goto out_free;
 	}
 
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
 
-int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid)
 {
-	struct wl1271_cmd_remove_sta *cmd;
+	struct wl12xx_cmd_remove_peer *cmd;
 	int ret;
 
-	wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
+	wl1271_debug(DEBUG_CMD, "cmd remove peer %d", (int)hlid);
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	cmd->hlid = hlid;
 	/* We never send a deauth, mac80211 is in charge of this */
 	cmd->reason_opcode = 0;
 	cmd->send_deauth_flag = 0;
 
-	ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
+	ret = wl1271_cmd_send(wl, CMD_REMOVE_PEER, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
-		wl1271_error("failed to initiate cmd remove sta");
+		wl1271_error("failed to initiate cmd remove peer");
 		goto out_free;
 	}
 
 	/*
 	 * We are ok with a timeout here. The event is sometimes not sent
 	 * due to a firmware bug.
 	 */
-	wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID);
+	wl1271_cmd_wait_for_event_or_timeout(wl,
+					     PEER_REMOVE_COMPLETE_EVENT_ID);
 
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index bba077e..16e0a87 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -33,13 +33,20 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
 		    size_t res_len);
 int wl1271_cmd_general_parms(struct wl1271 *wl);
 int wl128x_cmd_general_parms(struct wl1271 *wl);
 int wl1271_cmd_radio_parms(struct wl1271 *wl);
 int wl128x_cmd_radio_parms(struct wl1271 *wl);
 int wl1271_cmd_ext_radio_parms(struct wl1271 *wl);
-int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type);
+int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 role_type, u8 *role_id);
+int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl);
+int wl12xx_cmd_role_start_sta(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_sta(struct wl1271 *wl);
+int wl12xx_cmd_role_start_ap(struct wl1271 *wl);
+int wl12xx_cmd_role_stop_ap(struct wl1271 *wl);
 int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
 int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
@@ -53,26 +60,22 @@ int wl1271_cmd_build_probe_req(struct wl1271 *wl,
 			       const u8 *ie, size_t ie_len, u8 band);
 struct sk_buff *wl1271_cmd_build_ap_probe_req(struct wl1271 *wl,
 					      struct sk_buff *skb);
 int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
 int wl1271_build_qos_null_data(struct wl1271 *wl);
 int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
-int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id);
-int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
+int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid);
 int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			   u8 key_size, const u8 *key, const u8 *addr,
 			   u32 tx_seq_32, u16 tx_seq_16);
 int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			  u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
 			  u16 tx_seq_16);
-int wl1271_cmd_disconnect(struct wl1271 *wl);
-int wl1271_cmd_set_sta_state(struct wl1271 *wl);
-int wl1271_cmd_start_bss(struct wl1271 *wl);
-int wl1271_cmd_stop_bss(struct wl1271 *wl);
-int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
-int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl);
+int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
+int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
 int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
 int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
 int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
@@ -80,48 +83,58 @@ enum wl1271_commands {
 	CMD_ENABLE_RX       = 3,
 	CMD_ENABLE_TX       = 4,
 	CMD_DISABLE_RX      = 5,
 	CMD_DISABLE_TX      = 6,
 	CMD_SCAN            = 8,
 	CMD_STOP_SCAN       = 9,
-	CMD_START_JOIN      = 11,
 	CMD_SET_KEYS        = 12,
 	CMD_READ_MEMORY     = 13,
 	CMD_WRITE_MEMORY    = 14,
 	CMD_SET_TEMPLATE    = 19,
 	CMD_TEST            = 23,
 	CMD_NOISE_HIST      = 28,
-	CMD_LNA_CONTROL     = 32,
+	CMD_QUIET_ELEMENT_SET_STATE  = 29,
 	CMD_SET_BCN_MODE    = 33,
 	CMD_MEASUREMENT      = 34,
 	CMD_STOP_MEASUREMENT = 35,
-	CMD_DISCONNECT       = 36,
 	CMD_SET_PS_MODE      = 37,
 	CMD_CHANNEL_SWITCH   = 38,
 	CMD_STOP_CHANNEL_SWICTH = 39,
 	CMD_AP_DISCOVERY     = 40,
 	CMD_STOP_AP_DISCOVERY = 41,
-	CMD_SPS_SCAN = 42,
-	CMD_STOP_SPS_SCAN = 43,
 	CMD_HEALTH_CHECK     = 45,
 	CMD_DEBUG            = 46,
 	CMD_TRIGGER_SCAN_TO  = 47,
 	CMD_CONNECTION_SCAN_CFG      = 48,
 	CMD_CONNECTION_SCAN_SSID_CFG = 49,
 	CMD_START_PERIODIC_SCAN      = 50,
 	CMD_STOP_PERIODIC_SCAN       = 51,
-	CMD_SET_STA_STATE            = 52,
-	CMD_CONFIG_FWLOGGER          = 53,
-	CMD_START_FWLOGGER           = 54,
-	CMD_STOP_FWLOGGER            = 55,
+	CMD_SET_PEER_STATE           = 52,
+	CMD_REMAIN_ON_CHANNEL        = 53,
+	CMD_CANCEL_REMAIN_ON_CHANNEL = 54,
 
-	/* AP mode commands */
-	CMD_BSS_START                = 60,
-	CMD_BSS_STOP                 = 61,
-	CMD_ADD_STA                  = 62,
-	CMD_REMOVE_STA               = 63,
+	CMD_CONFIG_FWLOGGER          = 55,
+	CMD_START_FWLOGGER           = 56,
+	CMD_STOP_FWLOGGER            = 57,
+
+	/* AP commands */
+	CMD_ADD_PEER                 = 62,
+	CMD_REMOVE_PEER              = 63,
+
+	/* Role API */
+	CMD_ROLE_ENABLE              = 70,
+	CMD_ROLE_DISABLE             = 71,
+	CMD_ROLE_START               = 72,
+	CMD_ROLE_STOP                = 73,
+
+	/* WIFI Direct */
+	CMD_WFD_START_DISCOVERY      = 80,
+	CMD_WFD_STOP_DISCOVERY	     = 81,
+	CMD_WFD_ATTRIBUTE_CONFIG     = 82,
+
+	CMD_NOP                      = 100,
 
 	NUM_COMMANDS,
 	MAX_COMMAND_ID = 0xFFFF,
 };
 
 #define MAX_CMD_PARAMS 572
@@ -144,20 +157,18 @@ enum cmd_templ {
 	CMD_TEMPL_PROBE_REQ_2_4, /* for firmware internal use only */
 	CMD_TEMPL_PROBE_REQ_5,   /* for firmware internal use only */
 	CMD_TEMPL_BAR,           /* for firmware internal use only */
 	CMD_TEMPL_CTS,           /*
 				  * For CTS-to-self (FastCTS) mechanism
 				  * for BT/WLAN coexistence (SoftGemini). */
-	CMD_TEMPL_ARP_RSP,
-	CMD_TEMPL_LINK_MEASUREMENT_REPORT,
-
-	/* AP-mode specific */
-	CMD_TEMPL_AP_BEACON = 13,
+	CMD_TEMPL_AP_BEACON,
 	CMD_TEMPL_AP_PROBE_RESPONSE,
-	CMD_TEMPL_AP_ARP_RSP,
+	CMD_TEMPL_ARP_RSP,
 	CMD_TEMPL_DEAUTH_AP,
+	CMD_TEMPL_TEMPORARY,
+	CMD_TEMPL_LINK_MEASUREMENT_REPORT,
 
 	CMD_TEMPL_MAX = 0xff
 };
 
 /* unit ms */
 #define WL1271_COMMAND_TIMEOUT     2000
@@ -190,12 +201,13 @@ enum {
 	CMD_STATUS_OUT_OF_MEMORY		= 16,
 	CMD_STATUS_STA_TABLE_FULL		= 17,
 	CMD_STATUS_RADIO_ERROR		= 18,
 	CMD_STATUS_WRONG_NESTING		= 19,
 	CMD_STATUS_TIMEOUT		= 21, /* Driver internal use.*/
 	CMD_STATUS_FW_RESET		= 22, /* Driver internal use.*/
+	CMD_STATUS_TEMPLATE_OOM		= 23,
 	MAX_COMMAND_STATUS		= 0xff
 };
 
 #define CMDMBOX_HEADER_LEN 4
 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4
 
@@ -207,44 +219,120 @@ enum {
 };
 
 #define WL1271_JOIN_CMD_CTRL_TX_FLUSH     0x80 /* Firmware flushes all Tx */
 #define WL1271_JOIN_CMD_TX_SESSION_OFFSET 1
 #define WL1271_JOIN_CMD_BSS_TYPE_5GHZ 0x10
 
-struct wl1271_cmd_join {
+struct wl12xx_cmd_role_enable {
 	struct wl1271_cmd_header header;
 
-	__le32 bssid_lsb;
-	__le16 bssid_msb;
-	__le16 beacon_interval; /* in TBTTs */
-	__le32 rx_config_options;
-	__le32 rx_filter_options;
+	u8 role_id;
+	u8 role_type;
+	u8 mac_address[ETH_ALEN];
+} __packed;
 
-	/*
-	 * The target uses this field to determine the rate at
-	 * which to transmit control frame responses (such as
-	 * ACK or CTS frames).
-	 */
-	__le32 basic_rate_set;
-	__le32 supported_rate_set;
-	u8 dtim_interval;
-	/*
-	 * bits 0-2: This bitwise field specifies the type
-	 * of BSS to start or join (BSS_TYPE_*).
-	 * bit 4: Band - The radio band in which to join
-	 * or start.
-	 *  0 - 2.4GHz band
-	 *  1 - 5GHz band
-	 * bits 3, 5-7: Reserved
-	 */
-	u8 bss_type;
+struct wl12xx_cmd_role_disable {
+	struct wl1271_cmd_header header;
+
+	u8 role_id;
+	u8 padding[3];
+} __packed;
+
+enum wl12xx_band {
+	WL12XX_BAND_2_4GHZ		= 0,
+	WL12XX_BAND_5GHZ		= 1,
+	WL12XX_BAND_JAPAN_4_9_GHZ	= 2,
+	WL12XX_BAND_DEFAULT		= WL12XX_BAND_2_4GHZ,
+	WL12XX_BAND_INVALID		= 0x7E,
+	WL12XX_BAND_MAX_RADIO		= 0x7F,
+};
+
+struct wl12xx_cmd_role_start {
+	struct wl1271_cmd_header header;
+
+	u8 role_id;
+	u8 band;
 	u8 channel;
-	u8 ssid_len;
-	u8 ssid[IEEE80211_MAX_SSID_LEN];
-	u8 ctrl; /* JOIN_CMD_CTRL_* */
-	u8 reserved[3];
+	u8 padding;
+
+	union {
+		struct {
+			u8 hlid;
+			u8 session;
+			u8 padding_1[54];
+		} __packed device;
+		/* sta & p2p_cli use the same struct */
+		struct {
+			u8 bssid[ETH_ALEN];
+			u8 hlid; /* data hlid */
+			u8 session;
+			__le32 remote_rates; /* remote supported rates */
+
+			/*
+			 * The target uses this field to determine the rate at
+			 * which to transmit control frame responses (such as
+			 * ACK or CTS frames).
+			 */
+			__le32 basic_rate_set;
+			__le32 local_rates; /* local supported rates */
+
+			u8 ssid_type;
+			u8 ssid_len;
+			u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+			__le16 beacon_interval; /* in TBTTs */
+		} __packed sta;
+		struct {
+			u8 bssid[ETH_ALEN];
+			u8 hlid; /* data hlid */
+			u8 dtim_interval;
+			__le32 remote_rates; /* remote supported rates */
+
+			__le32 basic_rate_set;
+			__le32 local_rates; /* local supported rates */
+
+			u8 ssid_type;
+			u8 ssid_len;
+			u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+			__le16 beacon_interval; /* in TBTTs */
+
+			u8 padding_1[4];
+		} __packed ibss;
+		/* ap & p2p_go use the same struct */
+		struct {
+			__le16 aging_period; /* in secs */
+			u8 beacon_expiry; /* in ms */
+			u8 bss_index;
+			/* The host link id for the AP's global queue */
+			u8 global_hlid;
+			/* The host link id for the AP's broadcast queue */
+			u8 broadcast_hlid;
+
+			__le16 beacon_interval; /* in TBTTs */
+
+			__le32 basic_rate_set;
+			__le32 local_rates; /* local supported rates */
+
+			u8 dtim_interval;
+
+			u8 ssid_type;
+			u8 ssid_len;
+			u8 ssid[IEEE80211_MAX_SSID_LEN];
+
+			u8 padding_1[5];
+		} __packed ap;
+	};
+} __packed;
+
+struct wl12xx_cmd_role_stop {
+	struct wl1271_cmd_header header;
+
+	u8 role_id;
+	u8 disc_type; /* only STA and P2P_CLI */
+	__le16 reason; /* only STA and P2P_CLI */
 } __packed;
 
 struct cmd_enabledisable_path {
 	struct wl1271_cmd_header header;
 
 	u8 channel;
@@ -284,72 +372,42 @@ enum wl1271_cmd_ps_mode {
 	STATION_POWER_SAVE_MODE
 };
 
 struct wl1271_cmd_ps_params {
 	struct wl1271_cmd_header header;
 
+	u8 role_id;
 	u8 ps_mode; /* STATION_* */
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
 /* HW encryption keys */
 #define NUM_ACCESS_CATEGORIES_COPY 4
 
 enum wl1271_cmd_key_action {
 	KEY_ADD_OR_REPLACE = 1,
 	KEY_REMOVE         = 2,
 	KEY_SET_ID         = 3,
 	MAX_KEY_ACTION     = 0xffff,
 };
 
+enum wl1271_cmd_lid_key_type {
+	UNICAST_LID_TYPE     = 0,
+	BROADCAST_LID_TYPE   = 1,
+	WEP_DEFAULT_LID_TYPE = 2
+};
+
 enum wl1271_cmd_key_type {
 	KEY_NONE = 0,
 	KEY_WEP  = 1,
 	KEY_TKIP = 2,
 	KEY_AES  = 3,
 	KEY_GEM  = 4,
 };
 
-/* FIXME: Add description for key-types */
-
-struct wl1271_cmd_set_sta_keys {
-	struct wl1271_cmd_header header;
-
-	/* Ignored for default WEP key */
-	u8 addr[ETH_ALEN];
-
-	/* key_action_e */
-	__le16 key_action;
-
-	__le16 reserved_1;
-
-	/* key size in bytes */
-	u8 key_size;
-
-	/* key_type_e */
-	u8 key_type;
-	u8 ssid_profile;
-
-	/*
-	 * TKIP, AES: frame's key id field.
-	 * For WEP default key: key id;
-	 */
-	u8 id;
-	u8 reserved_2[6];
-	u8 key[MAX_KEY_SIZE];
-	__le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
-	__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
-} __packed;
-
-enum wl1271_cmd_lid_key_type {
-	UNICAST_LID_TYPE     = 0,
-	BROADCAST_LID_TYPE   = 1,
-	WEP_DEFAULT_LID_TYPE = 2
-};
-
-struct wl1271_cmd_set_ap_keys {
+struct wl1271_cmd_set_keys {
 	struct wl1271_cmd_header header;
 
 	/*
 	 * Indicates whether the HLID is a unicast key set
 	 * or broadcast key set. A special value 0xFF is
 	 * used to indicate that the HLID is on WEP-default
@@ -493,75 +551,29 @@ struct wl1271_ext_radio_parms_cmd {
 enum wl1271_disconnect_type {
 	DISCONNECT_IMMEDIATE,
 	DISCONNECT_DEAUTH,
 	DISCONNECT_DISASSOC
 };
 
-struct wl1271_cmd_disconnect {
-	struct wl1271_cmd_header header;
-
-	__le32 rx_config_options;
-	__le32 rx_filter_options;
-
-	__le16 reason;
-	u8  type;
-
-	u8  padding;
-} __packed;
-
 #define WL1271_CMD_STA_STATE_CONNECTED  1
 
-struct wl1271_cmd_set_sta_state {
+struct wl12xx_cmd_set_peer_state {
 	struct wl1271_cmd_header header;
 
+	u8 hlid;
 	u8 state;
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
-enum wl1271_ssid_type {
-	SSID_TYPE_PUBLIC = 0,
-	SSID_TYPE_HIDDEN = 1
+enum wl12xx_ssid_type {
+	WL12XX_SSID_TYPE_PUBLIC = 0,
+	WL12XX_SSID_TYPE_HIDDEN = 1,
+	WL12XX_SSID_TYPE_ANY = 2,
 };
 
-struct wl1271_cmd_bss_start {
-	struct wl1271_cmd_header header;
-
-	/* wl1271_ssid_type */
-	u8 ssid_type;
-	u8 ssid_len;
-	u8 ssid[IEEE80211_MAX_SSID_LEN];
-	u8 padding_1[2];
-
-	/* Basic rate set */
-	__le32 basic_rate_set;
-	/* Aging period in seconds*/
-	__le16 aging_period;
-
-	/*
-	 * This field specifies the time between target beacon
-	 * transmission times (TBTTs), in time units (TUs).
-	 * Valid values are 1 to 1024.
-	 */
-	__le16 beacon_interval;
-	u8 bssid[ETH_ALEN];
-	u8 bss_index;
-	/* Radio band */
-	u8 band;
-	u8 channel;
-	/* The host link id for the AP's global queue */
-	u8 global_hlid;
-	/* The host link id for the AP's broadcast queue */
-	u8 broadcast_hlid;
-	/* DTIM count */
-	u8 dtim_interval;
-	/* Beacon expiry time in ms */
-	u8 beacon_expiry;
-	u8 padding_2[3];
-} __packed;
-
-struct wl1271_cmd_add_sta {
+struct wl12xx_cmd_add_peer {
 	struct wl1271_cmd_header header;
 
 	u8 addr[ETH_ALEN];
 	u8 hlid;
 	u8 aid;
 	u8 psd_type[NUM_ACCESS_CATEGORIES_COPY];
@@ -569,13 +581,13 @@ struct wl1271_cmd_add_sta {
 	u8 bss_index;
 	u8 sp_len;
 	u8 wmm;
 	u8 padding1;
 } __packed;
 
-struct wl1271_cmd_remove_sta {
+struct wl12xx_cmd_remove_peer {
 	struct wl1271_cmd_header header;
 
 	u8 hlid;
 	u8 reason_opcode;
 	u8 send_deauth_flag;
 	u8 padding1;
diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 304aaa2..431ceae 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -282,16 +282,16 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 		if (wl->vif)
 			wl1271_event_rssi_trigger(wl, mbox);
 	}
 
 	if ((vector & BA_SESSION_RX_CONSTRAINT_EVENT_ID) && !is_ap) {
 		wl1271_debug(DEBUG_EVENT, "BA_SESSION_RX_CONSTRAINT_EVENT_ID. "
-			     "ba_allowed = 0x%x", mbox->ba_allowed);
+			     "ba_allowed = 0x%x", mbox->rx_ba_allowed);
 
 		if (wl->vif)
-			wl1271_stop_ba_event(wl, mbox->ba_allowed);
+			wl1271_stop_ba_event(wl, mbox->rx_ba_allowed);
 	}
 
 	if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
 		wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
 		if (wl->vif)
 			wl1271_tx_dummy_packet(wl);
diff --git a/drivers/net/wireless/wl12xx/event.h b/drivers/net/wireless/wl12xx/event.h
index e524ad6..49c1a0e 100644
--- a/drivers/net/wireless/wl12xx/event.h
+++ b/drivers/net/wireless/wl12xx/event.h
@@ -46,106 +46,88 @@ enum {
 	RSSI_SNR_TRIGGER_5_EVENT_ID              = BIT(5),
 	RSSI_SNR_TRIGGER_6_EVENT_ID              = BIT(6),
 	RSSI_SNR_TRIGGER_7_EVENT_ID              = BIT(7),
 	MEASUREMENT_START_EVENT_ID		 = BIT(8),
 	MEASUREMENT_COMPLETE_EVENT_ID		 = BIT(9),
 	SCAN_COMPLETE_EVENT_ID			 = BIT(10),
-	SCHEDULED_SCAN_COMPLETE_EVENT_ID	 = BIT(11),
+	WFD_DISCOVERY_COMPLETE_EVENT_ID		 = BIT(11),
 	AP_DISCOVERY_COMPLETE_EVENT_ID		 = BIT(12),
 	PS_REPORT_EVENT_ID			 = BIT(13),
 	PSPOLL_DELIVERY_FAILURE_EVENT_ID	 = BIT(14),
 	DISCONNECT_EVENT_COMPLETE_ID		 = BIT(15),
-	JOIN_EVENT_COMPLETE_ID			 = BIT(16),
+	/* BIT(16) is reserved */
 	CHANNEL_SWITCH_COMPLETE_EVENT_ID	 = BIT(17),
 	BSS_LOSE_EVENT_ID			 = BIT(18),
 	REGAINED_BSS_EVENT_ID			 = BIT(19),
 	MAX_TX_RETRY_EVENT_ID			 = BIT(20),
-	/* STA: dummy paket for dynamic mem blocks */
-	DUMMY_PACKET_EVENT_ID                    = BIT(21),
-	/* AP: STA remove complete */
-	STA_REMOVE_COMPLETE_EVENT_ID             = BIT(21),
+	DUMMY_PACKET_EVENT_ID			 = BIT(21),
 	SOFT_GEMINI_SENSE_EVENT_ID		 = BIT(22),
-	/* STA: SG prediction */
-	SOFT_GEMINI_PREDICTION_EVENT_ID		 = BIT(23),
-	/* AP: Inactive STA */
-	INACTIVE_STA_EVENT_ID			 = BIT(23),
+	CHANGE_AUTO_MODE_TIMEOUT_EVENT_ID	 = BIT(23),
 	SOFT_GEMINI_AVALANCHE_EVENT_ID		 = BIT(24),
 	PLT_RX_CALIBRATION_COMPLETE_EVENT_ID	 = BIT(25),
-	DBG_EVENT_ID				 = BIT(26),
-	HEALTH_CHECK_REPLY_EVENT_ID		 = BIT(27),
+	INACTIVE_STA_EVENT_ID			 = BIT(26),
+	PEER_REMOVE_COMPLETE_EVENT_ID		 = BIT(27),
 	PERIODIC_SCAN_COMPLETE_EVENT_ID		 = BIT(28),
 	PERIODIC_SCAN_REPORT_EVENT_ID		 = BIT(29),
 	BA_SESSION_RX_CONSTRAINT_EVENT_ID	 = BIT(30),
+	REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID	 = BIT(31),
 	EVENT_MBOX_ALL_EVENT_ID			 = 0x7fffffff,
 };
 
 enum {
 	EVENT_ENTER_POWER_SAVE_FAIL = 0,
 	EVENT_ENTER_POWER_SAVE_SUCCESS,
 };
 
-struct event_debug_report {
-	u8 debug_event_id;
-	u8 num_params;
-	__le16 pad;
-	__le32 report_1;
-	__le32 report_2;
-	__le32 report_3;
-} __packed;
-
 #define NUM_OF_RSSI_SNR_TRIGGERS 8
 
 struct event_mailbox {
 	__le32 events_vector;
 	__le32 events_mask;
 	__le32 reserved_1;
 	__le32 reserved_2;
 
-	u8 dbg_event_id;
-	u8 num_relevant_params;
-	__le16 reserved_3;
-	__le32 event_report_p1;
-	__le32 event_report_p2;
-	__le32 event_report_p3;
-
 	u8 number_of_scan_results;
 	u8 scan_tag;
-	u8 reserved_4[2];
-	__le32 compl_scheduled_scan_status;
+	u8 completed_scan_status;
+	u8 reserved_3;
 
-	__le16 scheduled_scan_attended_channels;
 	u8 soft_gemini_sense_info;
 	u8 soft_gemini_protective_info;
 	s8 rssi_snr_trigger_metric[NUM_OF_RSSI_SNR_TRIGGERS];
 	u8 channel_switch_status;
 	u8 scheduled_scan_status;
 	u8 ps_status;
+	/* tuned channel (roc) */
+	u8 roc_channel;
 
-	/* AP FW only */
-	u8 hlid_removed;
+	__le16 hlid_removed_bitmap;
 
-	/* a bitmap of hlids for stations that have been inactive too long */
+	/* bitmap of aged stations (by HLID) */
 	__le16 sta_aging_status;
 
-	/* a bitmap of hlids for stations which didn't respond to TX */
+	/* bitmap of stations (by HLID) which exceeded max tx retries */
 	__le16 sta_tx_retry_exceeded;
 
-	/*
-	 * Bitmap, Each bit set represents the Role ID for which this constraint
-	 * is set. Range: 0 - FF, FF means ANY role
-	 */
-	u8 ba_role_id;
-	/*
-	 * Bitmap, Each bit set represents the Link ID for which this constraint
-	 * is set. Not applicable if ba_role_id is set to ANY role (FF).
-	 * Range: 0 - FFFF, FFFF means ANY link in that role
-	 */
-	u8 ba_link_id;
-	u8 ba_allowed;
-
-	u8 reserved_5[21];
+	/* discovery completed results */
+	u8 discovery_tag;
+	u8 number_of_preq_results;
+	u8 number_of_prsp_results;
+	u8 reserved_5;
+
+	/* rx ba constraint */
+	u8 role_id; /* 0xFF means any role. */
+	u8 rx_ba_allowed;
+	u8 reserved_6[2];
+
+	u8 ps_poll_delivery_failure_role_ids;
+	u8 stopped_role_ids;
+	u8 started_role_ids;
+	u8 change_auto_mode_timeout;
+
+	u8 reserved_7[12];
 } __packed;
 
 int wl1271_event_unmask(struct wl1271 *wl);
 void wl1271_event_mbox_config(struct wl1271 *wl);
 int wl1271_event_handle(struct wl1271 *wl, u8 mbox);
 void wl1271_pspoll_work(struct work_struct *work);
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 5a33257..76e6f37 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -401,18 +401,12 @@ static int wl1271_sta_hw_init(struct wl1271 *wl)
 }
 
 static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
 {
 	int ret, i;
 
-	ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
-	if (ret < 0) {
-		wl1271_warning("couldn't set default key");
-		return ret;
-	}
-
 	/* disable all keep-alive templates */
 	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
 		ret = wl1271_acx_keep_alive_config(wl, i,
 						   ACX_KEEP_ALIVE_TPL_INVALID);
 		if (ret < 0)
 			return ret;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 07d50b7..4689d0b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -412,13 +412,13 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
 	if (operstate != IF_OPER_UP)
 		return 0;
 
 	if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
 		return 0;
 
-	ret = wl1271_cmd_set_sta_state(wl);
+	ret = wl12xx_cmd_set_peer_state(wl);
 	if (ret < 0)
 		return ret;
 
 	wl1271_info("Association completed.");
 	return 0;
 }
@@ -1979,12 +1979,14 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	wl1271_free_ap_keys(wl);
 	memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
 	wl->ap_fw_ps_map = 0;
 	wl->ap_ps_map = 0;
 	wl->sched_scanning = false;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
+	memset(wl->roles_map, 0, sizeof(wl->roles_map));
+	memset(wl->links_map, 0, sizeof(wl->links_map));
 
 	/*
 	 * this is performed after the cancel_work calls and the associated
 	 * mutex_lock, so that wl1271_op_add_interface does not accidentally
 	 * get executed before all these vars have been reset.
 	 */
@@ -2027,13 +2029,13 @@ static int wl1271_dummy_join(struct wl1271 *wl)
 	/* we need to use a dummy BSSID for now */
 	static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
 						  0xad, 0xbe, 0xef };
 
 	memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
 
-	ret = wl1271_cmd_join(wl, wl->set_bss_type);
+	ret = wl12xx_cmd_role_start_sta(wl);
 	if (ret < 0)
 		goto out;
 
 	set_bit(WL1271_FLAG_JOINED, &wl->flags);
 
 out:
@@ -2056,13 +2058,13 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
 	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		wl1271_info("JOIN while associated.");
 
 	if (set_assoc)
 		set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
 
-	ret = wl1271_cmd_join(wl, wl->set_bss_type);
+	ret = wl12xx_cmd_role_start_sta(wl);
 	if (ret < 0)
 		goto out;
 
 	set_bit(WL1271_FLAG_JOINED, &wl->flags);
 
 	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
@@ -2097,13 +2099,13 @@ out:
 
 static int wl1271_unjoin(struct wl1271 *wl)
 {
 	int ret;
 
 	/* to stop listening to a channel, we disconnect */
-	ret = wl1271_cmd_disconnect(wl);
+	ret = wl12xx_cmd_role_stop_sta(wl);
 	if (ret < 0)
 		goto out;
 
 	clear_bit(WL1271_FLAG_JOINED, &wl->flags);
 	memset(wl->bssid, 0, ETH_ALEN);
 
@@ -2469,13 +2471,14 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
 
 		if (key->key_type == KEY_WEP)
 			wep_key_added = true;
 	}
 
 	if (wep_key_added) {
-		ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key);
+		ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key,
+						     WL1271_AP_BROADCAST_HLID);
 		if (ret < 0)
 			goto out;
 	}
 
 out:
 	wl1271_free_ap_keys(wl);
@@ -2547,14 +2550,15 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 					     tx_seq_16);
 		if (ret < 0)
 			return ret;
 
 		/* the default WEP key needs to be configured at least once */
 		if (key_type == KEY_WEP) {
-			ret = wl1271_cmd_set_sta_default_wep_key(wl,
-							wl->default_key);
+			ret = wl12xx_cmd_set_default_wep_key(wl,
+							     wl->default_key,
+							     wl->sta_hlid);
 			if (ret < 0)
 				return ret;
 		}
 	}
 
 	return 0;
@@ -3005,26 +3009,26 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
 	if (ret < 0)
 		goto out;
 
 	if ((changed & BSS_CHANGED_BEACON_ENABLED)) {
 		if (bss_conf->enable_beacon) {
 			if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
-				ret = wl1271_cmd_start_bss(wl);
+				ret = wl12xx_cmd_role_start_ap(wl);
 				if (ret < 0)
 					goto out;
 
 				set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
 				wl1271_debug(DEBUG_AP, "started AP");
 
 				ret = wl1271_ap_init_hwenc(wl);
 				if (ret < 0)
 					goto out;
 			}
 		} else {
 			if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
-				ret = wl1271_cmd_stop_bss(wl);
+				ret = wl12xx_cmd_role_stop_ap(wl);
 				if (ret < 0)
 					goto out;
 
 				clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
 				wl1271_debug(DEBUG_AP, "stopped AP");
 			}
@@ -3529,13 +3533,13 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
 		goto out;
 
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out_free_sta;
 
-	ret = wl1271_cmd_add_sta(wl, sta, hlid);
+	ret = wl12xx_cmd_add_peer(wl, sta, hlid);
 	if (ret < 0)
 		goto out_sleep;
 
 out_sleep:
 	wl1271_ps_elp_sleep(wl);
 
@@ -3572,13 +3576,13 @@ static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
 		goto out;
 
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-	ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
+	ret = wl12xx_cmd_remove_peer(wl, wl_sta->hlid);
 	if (ret < 0)
 		goto out_sleep;
 
 	wl1271_free_sta(wl, wl_sta->hlid);
 
 out_sleep:
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 8a745fb..f497336 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -34,15 +34,16 @@
 static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
 {
 	int ret;
 	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
 	if (is_ap)
-		ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
+		ret = wl12xx_cmd_set_default_wep_key(wl, id,
+						     WL1271_AP_BROADCAST_HLID);
 	else
-		ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
+		ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid);
 
 	if (ret < 0)
 		return ret;
 
 	wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id);
 	return 0;
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9f71dc7..3d43875 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -134,12 +134,13 @@ extern u32 wl12xx_debug_level;
 #define WL1271_ELP_HW_STATE_ASLEEP 0
 #define WL1271_ELP_HW_STATE_IRQ    1
 
 #define WL1271_DEFAULT_BEACON_INT  100
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
+#define WL12XX_MAX_ROLES           4
 #define WL12XX_MAX_LINKS           8
 #define WL12XX_INVALID_ROLE_ID     0xff
 #define WL12XX_INVALID_LINK_ID     0xff
 #define WL1271_AP_GLOBAL_HLID      0
 #define WL1271_AP_BROADCAST_HLID   1
 #define WL1271_AP_STA_HLID_START   2
@@ -391,12 +392,16 @@ struct wl1271 {
 	u8 set_bss_type;
 	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
 	u8 ssid_len;
 	int channel;
 	u8 role_id;
 	u8 sta_hlid;
+	u8 dev_hlid;
+
+	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
+	unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 
 	struct wl1271_acx_mem_map *target_mem_map;
 
 	/* Accounting for allocated / available TX blocks on HW */
 	u32 tx_blocks_freed;
 	u32 tx_blocks_available;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 09/40] wl12xx: enable/disable role on interface add/remove
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (7 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 08/40] wl12xx: update commands & events Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 10/40] wl12xx: add device role commands Eliad Peller
                   ` (31 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

According to the new multi-role flow, we have to enable the
role before using (starting) it, and disable it on cleanup
(after it's no longer needed).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: consider WL12XX_INVALID_ROLE_TYPE, skip cmd on wake-up error.

 drivers/net/wireless/wl12xx/main.c |   41 ++++++++++++++++++++++++++++++++++++
 1 files changed, 41 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 4689d0b..3e77f59 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1776,19 +1776,35 @@ static int wl1271_op_start(struct ieee80211_hw *hw)
 
 static void wl1271_op_stop(struct ieee80211_hw *hw)
 {
 	wl1271_debug(DEBUG_MAC80211, "mac80211 stop");
 }
 
+static u8 wl12xx_get_role_type(struct wl1271 *wl)
+{
+	switch (wl->bss_type) {
+	case BSS_TYPE_AP_BSS:
+		return WL1271_ROLE_AP;
+
+	case BSS_TYPE_STA_BSS:
+		return WL1271_ROLE_STA;
+
+	default:
+		wl1271_error("invalid bss_type: %d", wl->bss_type);
+	}
+	return WL12XX_INVALID_ROLE_TYPE;
+}
+
 static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 {
 	struct wl1271 *wl = hw->priv;
 	struct wiphy *wiphy = hw->wiphy;
 	int retries = WL1271_BOOT_RETRIES;
 	int ret = 0;
+	u8 role_type;
 	bool booted = false;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 add interface type %d mac %pM",
 		     vif->type, vif->addr);
 
 	mutex_lock(&wl->mutex);
@@ -1823,12 +1839,17 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 		break;
 	default:
 		ret = -EOPNOTSUPP;
 		goto out;
 	}
 
+	role_type = wl12xx_get_role_type(wl);
+	if (role_type == WL12XX_INVALID_ROLE_TYPE) {
+		ret = -EINVAL;
+		goto out;
+	}
 	memcpy(wl->mac_addr, vif->addr, ETH_ALEN);
 
 	if (wl->state != WL1271_STATE_OFF) {
 		wl1271_error("cannot start because not in off state: %d",
 			     wl->state);
 		ret = -EBUSY;
@@ -1842,12 +1863,16 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 			goto power_off;
 
 		ret = wl1271_boot(wl);
 		if (ret < 0)
 			goto power_off;
 
+		ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id);
+		if (ret < 0)
+			goto irq_disable;
+
 		ret = wl1271_hw_init(wl);
 		if (ret < 0)
 			goto irq_disable;
 
 		booted = true;
 		break;
@@ -1906,12 +1931,13 @@ out:
 	return ret;
 }
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
 					 bool reset_tx_queues)
 {
+	int ret;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
 
 	/* because of hardware recovery, we may get here twice */
 	if (wl->state != WL1271_STATE_ON)
 		return;
@@ -1930,12 +1956,27 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 		wl->scan.state = WL1271_SCAN_STATE_IDLE;
 		memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
 		wl->scan.req = NULL;
 		ieee80211_scan_completed(wl->hw, true);
 	}
 
+	if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
+		/* disable active roles */
+		ret = wl1271_ps_elp_wakeup(wl);
+		if (ret < 0)
+			goto deinit;
+
+		ret = wl12xx_cmd_role_disable(wl, &wl->role_id);
+		if (ret < 0)
+			goto deinit;
+
+		wl1271_ps_elp_sleep(wl);
+	}
+deinit:
+	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+
 	/*
 	 * this must be before the cancel_work calls below, so that the work
 	 * functions don't perform further work.
 	 */
 	wl->state = WL1271_STATE_OFF;
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 10/40] wl12xx: add device role commands
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (8 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 09/40] wl12xx: enable/disable role on interface add/remove Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 11/40] wl12xx: update scan cmd api Eliad Peller
                   ` (30 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

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)

Since this role is required for the sta association process,
we enable it when a new sta interface is created.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: s/wl1271/wl12xx, add comment

 drivers/net/wireless/wl12xx/cmd.c    |   91 ++++++++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/main.c   |   25 +++++++++-
 drivers/net/wireless/wl12xx/wl12xx.h |    1 +
 3 files changed, 116 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index b13eed1..e29343e 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -455,12 +455,103 @@ static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
 		return;
 
 	__clear_bit(*hlid, wl->links_map);
 	*hlid = WL12XX_INVALID_LINK_ID;
 }
 
+int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_start *cmd;
+	int ret;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wl1271_debug(DEBUG_CMD, "cmd role start dev %d", wl->dev_role_id);
+
+	cmd->role_id = wl->dev_role_id;
+	if (wl->band == IEEE80211_BAND_5GHZ)
+		cmd->band = WL12XX_BAND_5GHZ;
+	cmd->channel = wl->channel;
+
+	if (wl->dev_hlid == WL12XX_INVALID_LINK_ID) {
+		ret = wl12xx_allocate_link(wl, &wl->dev_hlid);
+		if (ret)
+			goto out_free;
+	}
+	cmd->device.hlid = wl->dev_hlid;
+	cmd->device.session = wl->session_counter;
+
+	wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d",
+		     cmd->role_id, cmd->device.hlid, cmd->device.session);
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role enable");
+		goto err_hlid;
+	}
+
+	goto out_free;
+
+err_hlid:
+	/* clear links on error */
+	__clear_bit(wl->dev_hlid, wl->links_map);
+	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl12xx_cmd_role_stop_dev(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_stop *cmd;
+	int ret;
+
+	if (WARN_ON(wl->dev_hlid == WL12XX_INVALID_LINK_ID))
+		return -EINVAL;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wl1271_debug(DEBUG_CMD, "cmd role stop dev");
+
+	cmd->role_id = wl->dev_role_id;
+	cmd->disc_type = DISCONNECT_IMMEDIATE;
+	cmd->reason = cpu_to_le16(WLAN_REASON_UNSPECIFIED);
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role stop");
+		goto out_free;
+	}
+
+	ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
+	if (ret < 0) {
+		wl1271_error("cmd role stop dev event completion error");
+		goto out_free;
+	}
+
+	wl12xx_free_link(wl, &wl->dev_hlid);
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
 int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
 {
 	struct wl12xx_cmd_role_start *cmd;
 	int ret;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3e77f59..7b0b7c3 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1863,12 +1863,26 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 			goto power_off;
 
 		ret = wl1271_boot(wl);
 		if (ret < 0)
 			goto power_off;
 
+		if (wl->bss_type == BSS_TYPE_STA_BSS) {
+			/*
+			 * 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,
+							 WL1271_ROLE_DEVICE,
+							 &wl->dev_role_id);
+			if (ret < 0)
+				goto irq_disable;
+		}
+
 		ret = wl12xx_cmd_role_enable(wl, role_type, &wl->role_id);
 		if (ret < 0)
 			goto irq_disable;
 
 		ret = wl1271_hw_init(wl);
 		if (ret < 0)
@@ -1962,20 +1976,27 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 	if (!test_bit(WL1271_FLAG_RECOVERY_IN_PROGRESS, &wl->flags)) {
 		/* disable active roles */
 		ret = wl1271_ps_elp_wakeup(wl);
 		if (ret < 0)
 			goto deinit;
 
+		if (wl->bss_type == BSS_TYPE_STA_BSS) {
+			ret = wl12xx_cmd_role_disable(wl, &wl->dev_role_id);
+			if (ret < 0)
+				goto deinit;
+		}
+
 		ret = wl12xx_cmd_role_disable(wl, &wl->role_id);
 		if (ret < 0)
 			goto deinit;
 
 		wl1271_ps_elp_sleep(wl);
 	}
 deinit:
 	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
+	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
 
 	/*
 	 * this must be before the cancel_work calls below, so that the work
 	 * functions don't perform further work.
 	 */
 	wl->state = WL1271_STATE_OFF;
@@ -2020,12 +2041,13 @@ deinit:
 	wl1271_free_ap_keys(wl);
 	memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
 	wl->ap_fw_ps_map = 0;
 	wl->ap_ps_map = 0;
 	wl->sched_scanning = false;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
+	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
 	memset(wl->roles_map, 0, sizeof(wl->roles_map));
 	memset(wl->links_map, 0, sizeof(wl->links_map));
 
 	/*
 	 * this is performed after the cancel_work calls and the associated
 	 * mutex_lock, so that wl1271_op_add_interface does not accidentally
@@ -4362,13 +4384,14 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->platform_quirks = 0;
 	wl->sched_scanning = false;
 	wl->tx_security_seq = 0;
 	wl->tx_security_last_seq_lsb = 0;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
 	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
-
+	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
+	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
 	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
 		    (unsigned long) wl);
 	wl->fwlog_size = 0;
 	init_waitqueue_head(&wl->fwlog_waitq);
 
 	memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 3d43875..ab46664 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -391,12 +391,13 @@ struct wl1271 {
 	u8 bss_type;
 	u8 set_bss_type;
 	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
 	u8 ssid_len;
 	int channel;
 	u8 role_id;
+	u8 dev_role_id;
 	u8 sta_hlid;
 	u8 dev_hlid;
 
 	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
 	unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 11/40] wl12xx: update scan cmd api
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (9 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 10/40] wl12xx: add device role commands Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 12/40] wl12xx: update rx/tx Eliad Peller
                   ` (29 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Update the scan command to use the new fw api
(fw 6/7.3.0.0.75).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/scan.c |    8 +++++++-
 drivers/net/wireless/wl12xx/scan.h |   25 ++++++++++++++++---------
 2 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 78a9b23..54a4e75 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -153,24 +153,28 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
 	scan_options = WL1271_SCAN_OPT_PRIORITY_HIGH;
 
 	/* No SSIDs means that we have a forced passive scan */
 	if (passive || wl->scan.req->n_ssids == 0)
 		scan_options |= WL1271_SCAN_OPT_PASSIVE;
 
+	if (WARN_ON(wl->role_id == WL12XX_INVALID_ROLE_ID)) {
+		ret = -EINVAL;
+		goto out;
+	}
+	cmd->params.role_id = wl->role_id;
 	cmd->params.scan_options = cpu_to_le16(scan_options);
 
 	cmd->params.n_ch = wl1271_get_scan_channels(wl, wl->scan.req,
 						    cmd->channels,
 						    band, passive);
 	if (cmd->params.n_ch == 0) {
 		ret = WL1271_NOTHING_TO_SCAN;
 		goto out;
 	}
 
 	cmd->params.tx_rate = cpu_to_le32(basic_rate);
-
 	cmd->params.n_probe_reqs = wl->conf.scan.num_probe_reqs;
 	cmd->params.tx_rate = cpu_to_le32(basic_rate);
 	cmd->params.tid_trigger = 0;
 	cmd->params.scan_tag = WL1271_SCAN_DEFAULT_TAG;
 
 	if (band == IEEE80211_BAND_2GHZ)
@@ -180,12 +184,14 @@ static int wl1271_scan_send(struct wl1271 *wl, enum ieee80211_band band,
 
 	if (wl->scan.ssid_len && wl->scan.ssid) {
 		cmd->params.ssid_len = wl->scan.ssid_len;
 		memcpy(cmd->params.ssid, wl->scan.ssid, wl->scan.ssid_len);
 	}
 
+	memcpy(cmd->addr, wl->mac_addr, ETH_ALEN);
+
 	ret = wl1271_cmd_build_probe_req(wl, wl->scan.ssid, wl->scan.ssid_len,
 					 wl->scan.req->ie, wl->scan.req->ie_len,
 					 band);
 	if (ret < 0) {
 		wl1271_error("PROBE request template failed");
 		goto out;
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index 0b2a298..9211515 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -43,13 +43,16 @@ void wl1271_scan_sched_scan_results(struct wl1271 *wl);
 
 #define WL1271_SCAN_MAX_CHANNELS       24
 #define WL1271_SCAN_DEFAULT_TAG        1
 #define WL1271_SCAN_CURRENT_TX_PWR     0
 #define WL1271_SCAN_OPT_ACTIVE         0
 #define WL1271_SCAN_OPT_PASSIVE	       1
+#define WL1271_SCAN_OPT_TRIGGERED_SCAN 2
 #define WL1271_SCAN_OPT_PRIORITY_HIGH  4
+/* scan even if we fail to enter psm */
+#define WL1271_SCAN_OPT_FORCE          8
 #define WL1271_SCAN_BAND_2_4_GHZ 0
 #define WL1271_SCAN_BAND_5_GHZ 1
 
 #define WL1271_SCAN_TIMEOUT    10000 /* msec */
 
 enum {
@@ -59,33 +62,33 @@ enum {
 	WL1271_SCAN_STATE_5GHZ_ACTIVE,
 	WL1271_SCAN_STATE_5GHZ_PASSIVE,
 	WL1271_SCAN_STATE_DONE
 };
 
 struct basic_scan_params {
-	__le32 rx_config_options;
-	__le32 rx_filter_options;
 	/* Scan option flags (WL1271_SCAN_OPT_*) */
 	__le16 scan_options;
+	u8 role_id;
 	/* Number of scan channels in the list (maximum 30) */
 	u8 n_ch;
 	/* This field indicates the number of probe requests to send
 	   per channel for an active scan */
 	u8 n_probe_reqs;
-	/* Rate bit field for sending the probes */
-	__le32 tx_rate;
 	u8 tid_trigger;
 	u8 ssid_len;
-	/* in order to align */
-	u8 padding1[2];
+	u8 use_ssid_list;
+
+	/* Rate bit field for sending the probes */
+	__le32 tx_rate;
+
 	u8 ssid[IEEE80211_MAX_SSID_LEN];
 	/* Band to scan */
 	u8 band;
-	u8 use_ssid_list;
+
 	u8 scan_tag;
-	u8 padding2;
+	u8 padding2[2];
 } __packed;
 
 struct basic_scan_channel_params {
 	/* Duration in TU to wait for frames on a channel for active scan */
 	__le32 min_duration;
 	__le32 max_duration;
@@ -102,12 +105,16 @@ struct basic_scan_channel_params {
 
 struct wl1271_cmd_scan {
 	struct wl1271_cmd_header header;
 
 	struct basic_scan_params params;
 	struct basic_scan_channel_params channels[WL1271_SCAN_MAX_CHANNELS];
+
+	/* src mac address */
+	u8 addr[ETH_ALEN];
+	u8 padding[2];
 } __packed;
 
 struct wl1271_cmd_trigger_scan_to {
 	struct wl1271_cmd_header header;
 
 	__le32 timeout;
@@ -181,13 +188,13 @@ struct wl1271_cmd_sched_scan_config {
 	struct conn_scan_ch_params channels_2[MAX_CHANNELS_2GHZ];
 	struct conn_scan_ch_params channels_5[MAX_CHANNELS_5GHZ];
 	struct conn_scan_ch_params channels_4[MAX_CHANNELS_4GHZ];
 } __packed;
 
 
-#define SCHED_SCAN_MAX_SSIDS 8
+#define SCHED_SCAN_MAX_SSIDS 16
 
 enum {
 	SCAN_SSID_TYPE_PUBLIC = 0,
 	SCAN_SSID_TYPE_HIDDEN = 1,
 };
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 12/40] wl12xx: update rx/tx
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (10 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 11/40] wl12xx: update scan cmd api Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 13/40] wl12xx: change max/default template size Eliad Peller
                   ` (28 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Update the rx/tx descriptors according to the new fw api
(fw >= 6/7.3.0.0.75)

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/rx.h     |    7 ++-----
 drivers/net/wireless/wl12xx/tx.c     |   15 +++++++++++----
 drivers/net/wireless/wl12xx/tx.h     |   14 ++++----------
 drivers/net/wireless/wl12xx/wl12xx.h |    2 +-
 4 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/rx.h b/drivers/net/wireless/wl12xx/rx.h
index 00c1c1d..86ba6b1 100644
--- a/drivers/net/wireless/wl12xx/rx.h
+++ b/drivers/net/wireless/wl12xx/rx.h
@@ -83,13 +83,13 @@
  * RX Descriptor status
  *
  * Bits 0-2 - error code
  * Bits 3-5 - process_id tag (AP mode FW)
  * Bits 6-7 - reserved
  */
-#define WL1271_RX_DESC_STATUS_MASK      0x07
+#define WL1271_RX_DESC_STATUS_MASK      0x03
 
 #define WL1271_RX_DESC_SUCCESS          0x00
 #define WL1271_RX_DESC_DECRYPT_FAIL     0x01
 #define WL1271_RX_DESC_MIC_FAIL         0x02
 #define WL1271_RX_DESC_DRIVER_RX_Q_FAIL 0x03
 
@@ -118,16 +118,13 @@ struct wl1271_rx_descriptor {
 	u8  rate;
 	u8  channel;
 	s8  rssi;
 	u8  snr;
 	__le32 timestamp;
 	u8  packet_class;
-	union {
-		u8  process_id; /* STA FW */
-		u8  hlid; /* AP FW */
-	} __packed;
+	u8  hlid;
 	u8  pad_len;
 	u8  reserved;
 } __packed;
 
 void wl12xx_rx(struct wl1271 *wl, struct wl12xx_fw_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index f497336..23ce7aa 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -273,24 +273,23 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
 	} else {
 		/* configure the tx attributes */
 		tx_attr =
 			wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
 	}
 
-	if (wl->bss_type != BSS_TYPE_AP_BSS) {
-		desc->aid = hlid;
+	desc->hlid = hlid;
 
+	if (wl->bss_type != BSS_TYPE_AP_BSS) {
 		/* if the packets are destined for AP (have a STA entry)
 		   send them with AP rate policies, otherwise use default
 		   basic rates */
 		if (control->control.sta)
 			rate_idx = ACX_TX_AP_FULL_RATE;
 		else
 			rate_idx = ACX_TX_BASIC_RATE;
 	} else {
-		desc->hlid = hlid;
 		switch (hlid) {
 		case WL1271_AP_GLOBAL_HLID:
 			rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
 			break;
 		case WL1271_AP_BROADCAST_HLID:
 			rate_idx = ACX_TX_AP_MODE_BCST_RATE;
@@ -372,13 +371,21 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 		}
 	}
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS)
 		hlid = wl1271_tx_get_hlid(skb);
 	else
-		hlid = TX_HW_DEFAULT_AID;
+		if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+			hlid = wl->sta_hlid;
+		else
+			hlid = wl->dev_hlid;
+
+	if (hlid == WL12XX_INVALID_LINK_ID) {
+		wl1271_error("invalid hlid. dropping skb 0x%p", skb);
+		return -EINVAL;
+	}
 
 	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
 	if (ret < 0)
 		return ret;
 
 	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index 5d719b5..b712d7b 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -26,15 +26,12 @@
 #define __TX_H__
 
 #define TX_HW_BLOCK_SIZE                 252
 
 #define TX_HW_MGMT_PKT_LIFETIME_TU       2000
 #define TX_HW_AP_MODE_PKT_LIFETIME_TU    8000
-/* The chipset reference driver states, that the "aid" value 1
- * is for infra-BSS, but is still always used */
-#define TX_HW_DEFAULT_AID                1
 
 #define TX_HW_ATTR_SAVE_RETRIES          BIT(0)
 #define TX_HW_ATTR_HEADER_PAD            BIT(1)
 #define TX_HW_ATTR_SESSION_COUNTER       (BIT(2) | BIT(3) | BIT(4))
 #define TX_HW_ATTR_RATE_POLICY           (BIT(5) | BIT(6) | BIT(7) | \
 					  BIT(8) | BIT(9))
@@ -113,30 +110,27 @@ struct wl1271_tx_hw_descr {
 	/* Bitwise fields - see TX_ATTR... definitions above. */
 	__le16 tx_attr;
 	/* Packet identifier used also in the Tx-Result. */
 	u8 id;
 	/* The packet TID value (as User-Priority) */
 	u8 tid;
-	union {
-		/* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
-		u8 aid;
-		/* AP - host link ID (HLID) */
-		u8 hlid;
-	} __packed;
+	/* host link ID (HLID) */
+	u8 hlid;
 	u8 reserved;
 } __packed;
 
 enum wl1271_tx_hw_res_status {
 	TX_SUCCESS          = 0,
 	TX_HW_ERROR         = 1,
 	TX_DISABLED         = 2,
 	TX_RETRY_EXCEEDED   = 3,
 	TX_TIMEOUT          = 4,
 	TX_KEY_NOT_FOUND    = 5,
 	TX_PEER_NOT_FOUND   = 6,
-	TX_SESSION_MISMATCH = 7
+	TX_SESSION_MISMATCH = 7,
+	TX_LINK_NOT_VALID   = 8,
 };
 
 struct wl1271_tx_hw_res_descr {
 	/* Packet Identifier - same value used in the Tx descriptor.*/
 	u8 id;
 	/* The status of the transmission, indicating success or one of
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index ab46664..93e689d 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -156,13 +156,13 @@ extern u32 wl12xx_debug_level;
  */
 #define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)
 
 #define WL1271_AP_BSS_INDEX        0
 #define WL1271_AP_DEF_BEACON_EXP   20
 
-#define ACX_TX_DESCRIPTORS         32
+#define ACX_TX_DESCRIPTORS         16
 
 #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
 
 enum wl1271_state {
 	WL1271_STATE_OFF,
 	WL1271_STATE_ON,
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 13/40] wl12xx: change max/default template size
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (11 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 12/40] wl12xx: update rx/tx Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 14/40] wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap Eliad Peller
                   ` (27 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

The max template size was increased in the new fw.
However, we should use the max size only when needed, as it
consumes some of the chip's memory.

Thus, by default initialize the templates to the default size.
Initialize to the maximum size only when required.

Use WL1271_CMD_TEMPL_DFLT_SIZE instead of some of the
predefined structs, as some of them didn't account
for additional IEs that might be added to the template.

Delete structs defintions not used after these changes.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/cmd.h          |    3 ++-
 drivers/net/wireless/wl12xx/init.c         |   18 +++++++-----------
 drivers/net/wireless/wl12xx/main.c         |    2 +-
 drivers/net/wireless/wl12xx/wl12xx_80211.h |   25 -------------------------
 4 files changed, 10 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 16e0a87..6950759 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -169,13 +169,14 @@ enum cmd_templ {
 
 	CMD_TEMPL_MAX = 0xff
 };
 
 /* unit ms */
 #define WL1271_COMMAND_TIMEOUT     2000
-#define WL1271_CMD_TEMPL_MAX_SIZE  252
+#define WL1271_CMD_TEMPL_DFLT_SIZE 252
+#define WL1271_CMD_TEMPL_MAX_SIZE  548
 #define WL1271_EVENT_TIMEOUT       750
 
 struct wl1271_cmd_header {
 	__le16 id;
 	__le16 status;
 	/* payload */
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 76e6f37..683c8d1 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -36,19 +36,19 @@
 int wl1271_sta_init_templates_config(struct wl1271 *wl)
 {
 	int ret, i;
 
 	/* send empty templates for fw memory reservation */
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_2_4, NULL,
-				      WL1271_CMD_TEMPL_MAX_SIZE,
+				      WL1271_CMD_TEMPL_DFLT_SIZE,
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_CFG_PROBE_REQ_5,
-				      NULL, WL1271_CMD_TEMPL_MAX_SIZE, 0,
+				      NULL, WL1271_CMD_TEMPL_DFLT_SIZE, 0,
 				      WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
 				      sizeof(struct wl12xx_null_data_template),
@@ -67,21 +67,19 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
 				      (struct wl12xx_qos_null_data_template),
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_PROBE_RESPONSE, NULL,
-				      sizeof
-				      (struct wl12xx_probe_resp_template),
+				      WL1271_CMD_TEMPL_DFLT_SIZE,
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON, NULL,
-				      sizeof
-				      (struct wl12xx_beacon_template),
+				      WL1271_CMD_TEMPL_DFLT_SIZE,
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_ARP_RSP, NULL,
 				      sizeof
@@ -89,13 +87,13 @@ int wl1271_sta_init_templates_config(struct wl1271 *wl)
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
 		ret = wl1271_cmd_template_set(wl, CMD_TEMPL_KLV, NULL,
-					      WL1271_CMD_TEMPL_MAX_SIZE, i,
+					      WL1271_CMD_TEMPL_DFLT_SIZE, i,
 					      WL1271_RATE_AUTOMATIC);
 		if (ret < 0)
 			return ret;
 	}
 
 	return 0;
@@ -188,21 +186,19 @@ static int wl1271_ap_init_templates_config(struct wl1271 *wl)
 
 	/*
 	 * Put very large empty placeholders for all templates. These
 	 * reserve memory for later.
 	 */
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
-				      sizeof
-				      (struct wl12xx_probe_resp_template),
+				      WL1271_CMD_TEMPL_MAX_SIZE,
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
-				      sizeof
-				      (struct wl12xx_beacon_template),
+				      WL1271_CMD_TEMPL_MAX_SIZE,
 				      0, WL1271_RATE_AUTOMATIC);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
 				      sizeof
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 7b0b7c3..1389c5c 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -4263,13 +4263,13 @@ int wl1271_init_ieee80211(struct wl1271 *wl)
 	wl->hw->wiphy->max_scan_ssids = 1;
 	/*
 	 * Maximum length of elements in scanning probe request templates
 	 * should be the maximum length possible for a template, without
 	 * the IEEE80211 header of the template
 	 */
-	wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
+	wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_DFLT_SIZE -
 			sizeof(struct ieee80211_header);
 
 	/* make sure all our channels fit in the scanned_ch bitmask */
 	BUILD_BUG_ON(ARRAY_SIZE(wl1271_channels) +
 		     ARRAY_SIZE(wl1271_channels_5ghz) >
 		     WL1271_MAX_CHANNELS);
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index f334ea0..f7971d3 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -102,24 +102,12 @@ struct wl12xx_ie_country {
 	struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
 } __packed;
 
 
 /* Templates */
 
-struct wl12xx_beacon_template {
-	struct ieee80211_header header;
-	__le32 time_stamp[2];
-	__le16 beacon_interval;
-	__le16 capability;
-	struct wl12xx_ie_ssid ssid;
-	struct wl12xx_ie_rates rates;
-	struct wl12xx_ie_rates ext_rates;
-	struct wl12xx_ie_ds_params ds_params;
-	struct wl12xx_ie_country country;
-} __packed;
-
 struct wl12xx_null_data_template {
 	struct ieee80211_header header;
 } __packed;
 
 struct wl12xx_ps_poll_template {
 	__le16 fc;
@@ -143,25 +131,12 @@ struct wl12xx_arp_rsp_template {
 	u8 sender_hw[ETH_ALEN];
 	__be32 sender_ip;
 	u8 target_hw[ETH_ALEN];
 	__be32 target_ip;
 } __packed;
 
-
-struct wl12xx_probe_resp_template {
-	struct ieee80211_header header;
-	__le32 time_stamp[2];
-	__le16 beacon_interval;
-	__le16 capability;
-	struct wl12xx_ie_ssid ssid;
-	struct wl12xx_ie_rates rates;
-	struct wl12xx_ie_rates ext_rates;
-	struct wl12xx_ie_ds_params ds_params;
-	struct wl12xx_ie_country country;
-} __packed;
-
 struct wl12xx_disconn_template {
 	struct ieee80211_header header;
 	__le16 disconn_reason;
 } __packed;
 
 #endif
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 14/40] wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (12 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 13/40] wl12xx: change max/default template size Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 15/40] wl12xx: add set_rate_mgmt_params acx Eliad Peller
                   ` (26 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Use ACX_BEACON_FILTER_OPT for both station and ap roles
(use the generic wl1271_acx_beacon_filter_opt()
instead of wl1271_acx_set_ap_beacon_filter() ).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c  |   25 -------------------------
 drivers/net/wireless/wl12xx/acx.h  |    9 ---------
 drivers/net/wireless/wl12xx/init.c |    2 +-
 drivers/net/wireless/wl12xx/main.c |    4 ++--
 4 files changed, 3 insertions(+), 37 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index dfb1cbb..968d219 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1657,37 +1657,12 @@ int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr)
 
 out:
 	kfree(acx);
 	return ret;
 }
 
-int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable)
-{
-	struct acx_ap_beacon_filter *acx = NULL;
-	int ret;
-
-	wl1271_debug(DEBUG_ACX, "acx set ap beacon filter: %d", enable);
-
-	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
-	if (!acx)
-		return -ENOMEM;
-
-	acx->enable = enable ? 1 : 0;
-
-	ret = wl1271_cmd_configure(wl, ACX_AP_BEACON_FILTER_OPT,
-				   acx, sizeof(*acx));
-	if (ret < 0) {
-		wl1271_warning("acx set ap beacon filter failed: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(acx);
-	return ret;
-}
-
 int wl1271_acx_fm_coex(struct wl1271 *wl)
 {
 	struct wl1271_acx_fm_coex *acx;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "acx fm coex setting");
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 67258a1..3aec410 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1093,19 +1093,12 @@ struct wl1271_acx_inconnection_sta {
 	struct acx_header header;
 
 	u8 addr[ETH_ALEN];
 	u8 padding1[2];
 } __packed;
 
-struct acx_ap_beacon_filter {
-	struct acx_header header;
-
-	u8 enable;
-	u8 pad[3];
-} __packed;
-
 /*
  * ACX_FM_COEX_CFG
  * set the FM co-existence parameters.
  */
 struct wl1271_acx_fm_coex {
 	struct acx_header header;
@@ -1174,13 +1167,12 @@ enum {
 	ACX_STATISTICS              = 0x0013, /* Debug API */
 	ACX_PWR_CONSUMPTION_STATISTICS = 0x0014,
 	ACX_FEATURE_CFG             = 0x0015,
 	ACX_TID_CFG                 = 0x001A,
 	ACX_PS_RX_STREAMING         = 0x001B,
 	ACX_BEACON_FILTER_OPT       = 0x001F,
-	ACX_AP_BEACON_FILTER_OPT    = 0x0020,
 	ACX_NOISE_HIST              = 0x0021,
 	ACX_HDK_VERSION             = 0x0022, /* ??? */
 	ACX_PD_THRESHOLD            = 0x0023,
 	ACX_TX_CONFIG_OPT           = 0x0024,
 	ACX_CCA_THRESHOLD           = 0x0025,
 	ACX_EVENT_MBOX_MASK         = 0x0026,
@@ -1298,10 +1290,9 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
 				       bool enable);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
 int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
 int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
 int wl1271_acx_config_ps(struct wl1271 *wl);
 int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
-int wl1271_acx_set_ap_beacon_filter(struct wl1271 *wl, bool enable);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 683c8d1..3a66609 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -466,13 +466,13 @@ int wl1271_ap_init_templates(struct wl1271 *wl)
 		return ret;
 
 	/*
 	 * when operating as AP we want to receive external beacons for
 	 * configuring ERP protection.
 	 */
-	ret = wl1271_acx_set_ap_beacon_filter(wl, false);
+	ret = wl1271_acx_beacon_filter_opt(wl, false);
 	if (ret < 0)
 		return ret;
 
 	return 0;
 }
 
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 1389c5c..d683bca 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1636,13 +1636,13 @@ static int wl1271_configure_suspend_ap(struct wl1271 *wl)
 		goto out_unlock;
 
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out_unlock;
 
-	ret = wl1271_acx_set_ap_beacon_filter(wl, true);
+	ret = wl1271_acx_beacon_filter_opt(wl, true);
 
 	wl1271_ps_elp_sleep(wl);
 out_unlock:
 	mutex_unlock(&wl->mutex);
 	return ret;
 
@@ -1674,13 +1674,13 @@ static void wl1271_configure_resume(struct wl1271 *wl)
 	if (is_sta) {
 		/* exit psm if it wasn't configured */
 		if (!test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags))
 			wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
 					   wl->basic_rate, true);
 	} else if (is_ap) {
-		wl1271_acx_set_ap_beacon_filter(wl, false);
+		wl1271_acx_beacon_filter_opt(wl, false);
 	}
 
 	wl1271_ps_elp_sleep(wl);
 out:
 	mutex_unlock(&wl->mutex);
 }
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 15/40] wl12xx: add set_rate_mgmt_params acx
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (13 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 14/40] wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 16/40] wl12xx: add system_hlid Eliad Peller
                   ` (25 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Configure rate management parameters on hw init

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: remove BUILD_BUG_ON, fix typos, reorder conf struct.
 drivers/net/wireless/wl12xx/acx.c  |   42 ++++++++++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/acx.h  |   25 +++++++++++++++++++++
 drivers/net/wireless/wl12xx/conf.h |   20 +++++++++++++++++
 drivers/net/wireless/wl12xx/init.c |    4 +++
 drivers/net/wireless/wl12xx/main.c |   21 ++++++++++++++++++
 5 files changed, 112 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index 968d219..a784ba6 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1696,6 +1696,48 @@ int wl1271_acx_fm_coex(struct wl1271 *wl)
 	}
 
 out:
 	kfree(acx);
 	return ret;
 }
+
+int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl)
+{
+	struct wl12xx_acx_set_rate_mgmt_params *acx = NULL;
+	struct conf_rate_policy_settings *conf = &wl->conf.rate;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx set rate mgmt params");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx)
+		return -ENOMEM;
+
+	acx->index = ACX_RATE_MGMT_ALL_PARAMS;
+	acx->rate_retry_score = cpu_to_le16(conf->rate_retry_score);
+	acx->per_add = cpu_to_le16(conf->per_add);
+	acx->per_th1 = cpu_to_le16(conf->per_th1);
+	acx->per_th2 = cpu_to_le16(conf->per_th2);
+	acx->max_per = cpu_to_le16(conf->max_per);
+	acx->inverse_curiosity_factor = conf->inverse_curiosity_factor;
+	acx->tx_fail_low_th = conf->tx_fail_low_th;
+	acx->tx_fail_high_th = conf->tx_fail_high_th;
+	acx->per_alpha_shift = conf->per_alpha_shift;
+	acx->per_add_shift = conf->per_add_shift;
+	acx->per_beta1_shift = conf->per_beta1_shift;
+	acx->per_beta2_shift = conf->per_beta2_shift;
+	acx->rate_check_up = conf->rate_check_up;
+	acx->rate_check_down = conf->rate_check_down;
+	memcpy(acx->rate_retry_policy, conf->rate_retry_policy,
+	       sizeof(acx->rate_retry_policy));
+
+	ret = wl1271_cmd_configure(wl, ACX_SET_RATE_MGMT_PARAMS,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx set rate mgmt params failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 3aec410..6909bc5 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1152,12 +1152,36 @@ struct wl1271_acx_fm_coex {
 	 * The swallow clock difference of the swallowing mechanism.
 	 * 0xFF = use FW default
 	 */
 	u8 swallow_clk_diff;
 } __packed;
 
+#define ACX_RATE_MGMT_ALL_PARAMS 0xff
+struct wl12xx_acx_set_rate_mgmt_params {
+	struct acx_header header;
+
+	u8 index; /* 0xff to configure all params */
+	u8 padding1;
+	__le16 rate_retry_score;
+	__le16 per_add;
+	__le16 per_th1;
+	__le16 per_th2;
+	__le16 max_per;
+	u8 inverse_curiosity_factor;
+	u8 tx_fail_low_th;
+	u8 tx_fail_high_th;
+	u8 per_alpha_shift;
+	u8 per_add_shift;
+	u8 per_beta1_shift;
+	u8 per_beta2_shift;
+	u8 rate_check_up;
+	u8 rate_check_down;
+	u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
+	u8 padding2[2];
+} __packed;
+
 enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
 	ACX_SLOT                    = 0x0004,
 	ACX_AC_CFG                  = 0x0007,
 	ACX_MEM_MAP                 = 0x0008,
@@ -1291,8 +1315,9 @@ int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
 int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
 int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
 int wl1271_acx_config_ps(struct wl1271 *wl);
 int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
+int wl12xx_acx_set_rate_mgmt_params(struct wl1271 *wl);
 
 #endif /* __WL1271_ACX_H__ */
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 6080e01..30ee7d3 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -1306,12 +1306,31 @@ struct conf_fwlog {
 	u8 output;
 
 	/* Regulates the frequency of log messages */
 	u8 threshold;
 };
 
+#define ACX_RATE_MGMT_NUM_OF_RATES 13
+struct conf_rate_policy_settings {
+	u16 rate_retry_score;
+	u16 per_add;
+	u16 per_th1;
+	u16 per_th2;
+	u16 max_per;
+	u8 inverse_curiosity_factor;
+	u8 tx_fail_low_th;
+	u8 tx_fail_high_th;
+	u8 per_alpha_shift;
+	u8 per_add_shift;
+	u8 per_beta1_shift;
+	u8 per_beta2_shift;
+	u8 rate_check_up;
+	u8 rate_check_down;
+	u8 rate_retry_policy[ACX_RATE_MGMT_NUM_OF_RATES];
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
 	struct conf_tx_settings tx;
 	struct conf_conn_settings conn;
 	struct conf_itrim_settings itrim;
@@ -1323,10 +1342,11 @@ struct conf_drv_settings {
 	struct conf_ht_setting ht;
 	struct conf_memory_settings mem_wl127x;
 	struct conf_memory_settings mem_wl128x;
 	struct conf_fm_coex fm_coex;
 	struct conf_rx_streaming_settings rx_streaming;
 	struct conf_fwlog fwlog;
+	struct conf_rate_policy_settings rate;
 	u8 hci_io_ds;
 };
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 3a66609..1bc246f 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -712,12 +712,16 @@ int wl1271_hw_init(struct wl1271 *wl)
 	else
 		ret = wl1271_sta_hw_init_post_mem(wl);
 
 	if (ret < 0)
 		goto out_free_memmap;
 
+	ret = wl12xx_acx_set_rate_mgmt_params(wl);
+	if (ret < 0)
+		goto out_free_memmap;
+
 	/* Configure initiator BA sessions policies */
 	ret = wl1271_set_ba_policies(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
 	return 0;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index d683bca..3db191d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -376,12 +376,33 @@ static struct conf_drv_settings default_conf = {
 		.severity                     = 0,
 		.timestamp                    = WL12XX_FWLOG_TIMESTAMP_DISABLED,
 		.output                       = WL12XX_FWLOG_OUTPUT_HOST,
 		.threshold                    = 0,
 	},
 	.hci_io_ds = HCI_IO_DS_6MA,
+	.rate = {
+		.rate_retry_score = 32000,
+		.per_add = 8192,
+		.per_th1 = 2048,
+		.per_th2 = 4096,
+		.max_per = 8100,
+		.inverse_curiosity_factor = 5,
+		.tx_fail_low_th = 4,
+		.tx_fail_high_th = 10,
+		.per_alpha_shift = 4,
+		.per_add_shift = 13,
+		.per_beta1_shift = 10,
+		.per_beta2_shift = 8,
+		.rate_check_up = 2,
+		.rate_check_down = 12,
+		.rate_retry_policy = {
+			0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00, 0x00, 0x00,
+			0x00, 0x00, 0x00,
+		},
+	},
 };
 
 static char *fwlog_param;
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
 					 bool reset_tx_queues);
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 16/40] wl12xx: add system_hlid
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (14 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 15/40] wl12xx: add set_rate_mgmt_params acx Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 17/40] wl12xx: add ROC/CROC commands Eliad Peller
                   ` (24 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

system_hlid is a const hlid (always 0), used by the fw and driver
for packets which are not bound to specific role (e.g. dynamic
memory packets).
indicate it as always allocated.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: remove memset, refactor wl1271_tx_get_hlid

 drivers/net/wireless/wl12xx/main.c   |    9 ++++++-
 drivers/net/wireless/wl12xx/tx.c     |   40 +++++++++++++++++++++------------
 drivers/net/wireless/wl12xx/tx.h     |    2 +-
 drivers/net/wireless/wl12xx/wl12xx.h |    2 +
 4 files changed, 36 insertions(+), 17 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3db191d..e4081e2 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1488,13 +1488,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	u8 hlid = 0;
 
 	mapping = skb_get_queue_mapping(skb);
 	q = wl1271_tx_get_queue(mapping);
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS)
-		hlid = wl1271_tx_get_hlid(skb);
+		hlid = wl12xx_tx_get_hlid_ap(wl, skb);
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
 
 	wl->tx_queue_count[q]++;
 
 	/*
@@ -2066,12 +2066,15 @@ deinit:
 	wl->sched_scanning = false;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
 	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
 	memset(wl->roles_map, 0, sizeof(wl->roles_map));
 	memset(wl->links_map, 0, sizeof(wl->links_map));
 
+	/* The system link is always allocated */
+	__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
+
 	/*
 	 * this is performed after the cancel_work calls and the associated
 	 * mutex_lock, so that wl1271_op_add_interface does not accidentally
 	 * get executed before all these vars have been reset.
 	 */
 	wl->flags = 0;
@@ -4404,20 +4407,24 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->quirks = 0;
 	wl->platform_quirks = 0;
 	wl->sched_scanning = false;
 	wl->tx_security_seq = 0;
 	wl->tx_security_last_seq_lsb = 0;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
+	wl->system_hlid = WL12XX_SYSTEM_HLID;
 	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
 	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
 	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
 	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
 		    (unsigned long) wl);
 	wl->fwlog_size = 0;
 	init_waitqueue_head(&wl->fwlog_waitq);
 
+	/* The system link is always allocated */
+	__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
+
 	memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
 	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
 		wl->tx_frames[i] = NULL;
 
 	spin_lock_init(&wl->wl_lock);
 
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 23ce7aa..ffdaf97 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -129,33 +129,55 @@ static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
 	 */
 	if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
 		wl1271_ps_link_start(wl, hlid, true);
 }
 #endif
 
-u8 wl1271_tx_get_hlid(struct sk_buff *skb)
+static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
+{
+	return wl->dummy_packet == skb;
+}
+
+u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
 
 	if (control->control.sta) {
 		struct wl1271_station *wl_sta;
 
 		wl_sta = (struct wl1271_station *)
 				control->control.sta->drv_priv;
 		return wl_sta->hlid;
 	} else {
 		struct ieee80211_hdr *hdr;
 
+		if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
+			return wl->system_hlid;
+
 		hdr = (struct ieee80211_hdr *)skb->data;
 		if (ieee80211_is_mgmt(hdr->frame_control))
 			return WL1271_AP_GLOBAL_HLID;
 		else
 			return WL1271_AP_BROADCAST_HLID;
 	}
 }
 
+static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
+{
+	if (wl12xx_is_dummy_packet(wl, skb))
+		return wl->system_hlid;
+
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		return wl12xx_tx_get_hlid_ap(wl, skb);
+
+	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+		return wl->sta_hlid;
+	else
+		return wl->dev_hlid;
+}
+
 static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
 						unsigned int packet_length)
 {
 	if (wl->quirks & WL12XX_QUIRK_BLOCKSIZE_ALIGNMENT)
 		return ALIGN(packet_length, WL12XX_BUS_BLOCK_SIZE);
 	else
@@ -218,17 +240,12 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 		wl1271_free_tx_id(wl, id);
 	}
 
 	return ret;
 }
 
-static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
-{
-	return wl->dummy_packet == skb;
-}
-
 static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
 			      u32 extra, struct ieee80211_tx_info *control,
 			      u8 hlid)
 {
 	struct timespec ts;
 	struct wl1271_tx_hw_descr *desc;
@@ -368,20 +385,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 			if (ret < 0)
 				return ret;
 			wl->default_key = idx;
 		}
 	}
 
-	if (wl->bss_type == BSS_TYPE_AP_BSS)
-		hlid = wl1271_tx_get_hlid(skb);
-	else
-		if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
-			hlid = wl->sta_hlid;
-		else
-			hlid = wl->dev_hlid;
-
+	hlid = wl1271_tx_get_hlid(wl, skb);
 	if (hlid == WL12XX_INVALID_LINK_ID) {
 		wl1271_error("invalid hlid. dropping skb 0x%p", skb);
 		return -EINVAL;
 	}
 
 	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
@@ -561,13 +571,13 @@ static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
 	unsigned long flags;
 	int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 
 	if (wl12xx_is_dummy_packet(wl, skb)) {
 		set_bit(WL1271_FLAG_DUMMY_PACKET_PENDING, &wl->flags);
 	} else if (wl->bss_type == BSS_TYPE_AP_BSS) {
-		u8 hlid = wl1271_tx_get_hlid(skb);
+		u8 hlid = wl1271_tx_get_hlid(wl, skb);
 		skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
 
 		/* make sure we dequeue the same packet next time */
 		wl->last_tx_hlid = (hlid + AP_MAX_LINKS - 1) % AP_MAX_LINKS;
 	} else {
 		skb_queue_head(&wl->tx_queue[q], skb);
diff --git a/drivers/net/wireless/wl12xx/tx.h b/drivers/net/wireless/wl12xx/tx.h
index b712d7b..7da35c0 100644
--- a/drivers/net/wireless/wl12xx/tx.h
+++ b/drivers/net/wireless/wl12xx/tx.h
@@ -207,11 +207,11 @@ void wl1271_tx_work_locked(struct wl1271 *wl);
 void wl1271_tx_complete(struct wl1271 *wl);
 void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues);
 void wl1271_tx_flush(struct wl1271 *wl);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
 u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
-u8 wl1271_tx_get_hlid(struct sk_buff *skb);
+u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb);
 void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
 void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
 
 #endif
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 93e689d..089304d 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -138,12 +138,13 @@ extern u32 wl12xx_debug_level;
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
 #define WL12XX_MAX_ROLES           4
 #define WL12XX_MAX_LINKS           8
 #define WL12XX_INVALID_ROLE_ID     0xff
 #define WL12XX_INVALID_LINK_ID     0xff
+#define WL12XX_SYSTEM_HLID         0
 #define WL1271_AP_GLOBAL_HLID      0
 #define WL1271_AP_BROADCAST_HLID   1
 #define WL1271_AP_STA_HLID_START   2
 
 /*
  * When in AP-mode, we allow (at least) this number of mem-blocks
@@ -392,12 +393,13 @@ struct wl1271 {
 	u8 set_bss_type;
 	u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
 	u8 ssid_len;
 	int channel;
 	u8 role_id;
 	u8 dev_role_id;
+	u8 system_hlid;
 	u8 sta_hlid;
 	u8 dev_hlid;
 
 	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
 	unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 17/40] wl12xx: add ROC/CROC commands
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (15 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 16/40] wl12xx: add system_hlid Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 18/40] wl12xx: replace dummy_join with " Eliad Peller
                   ` (23 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Add structs and functions to support the ROC/CROC commands.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: bail out on invalid band

 drivers/net/wireless/wl12xx/cmd.c |   73 +++++++++++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/cmd.h |   16 ++++++++
 2 files changed, 89 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index e29343e..1b04102 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1478,6 +1478,79 @@ int wl12xx_cmd_stop_fwlog(struct wl1271 *wl)
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
+
+static int wl12xx_cmd_roc(struct wl1271 *wl, u8 role_id)
+{
+	struct wl12xx_cmd_roc *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd roc %d (%d)", wl->channel, role_id);
+
+	if (WARN_ON(role_id == WL12XX_INVALID_ROLE_ID))
+		return -EINVAL;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->role_id = role_id;
+	cmd->channel = wl->channel;
+	switch (wl->band) {
+	case IEEE80211_BAND_2GHZ:
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		cmd->band = RADIO_BAND_5GHZ;
+		break;
+	default:
+		wl1271_error("roc - unknown band: %d", (int)wl->band);
+		ret = -EINVAL;
+		goto out_free;
+	}
+
+
+	ret = wl1271_cmd_send(wl, CMD_REMAIN_ON_CHANNEL, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send ROC command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
+{
+	struct wl12xx_cmd_croc *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd croc (%d)", role_id);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+	cmd->role_id = role_id;
+
+	ret = wl1271_cmd_send(wl, CMD_CANCEL_REMAIN_ON_CHANNEL, cmd,
+			      sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to send ROC command");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 6950759..80b02ed 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -562,12 +562,28 @@ struct wl12xx_cmd_set_peer_state {
 
 	u8 hlid;
 	u8 state;
 	u8 padding[2];
 } __packed;
 
+struct wl12xx_cmd_roc {
+	struct wl1271_cmd_header header;
+
+	u8 role_id;
+	u8 channel;
+	u8 band;
+	u8 padding;
+};
+
+struct wl12xx_cmd_croc {
+	struct wl1271_cmd_header header;
+
+	u8 role_id;
+	u8 padding[3];
+};
+
 enum wl12xx_ssid_type {
 	WL12XX_SSID_TYPE_PUBLIC = 0,
 	WL12XX_SSID_TYPE_HIDDEN = 1,
 	WL12XX_SSID_TYPE_ANY = 2,
 };
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 18/40] wl12xx: replace dummy_join with ROC/CROC commands
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (16 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 17/40] wl12xx: add ROC/CROC commands Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 19/40] wl12xx: handle dummy packet event also in ap mode Eliad Peller
                   ` (22 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

The ROC command asks the fw stay on the channel of the given
hlid. it currently has 2 primary functions:

1. Allow tx/rx from the device role.

In order to tx/rx packets while the stations is not associated
(e.g. auth req/resp), the device role has to be used, along
with ROC on its link.

Keep the logic similiar to the one used in dummy_join. However,
since we can't scan while we ROC, we add CROC before starting
a scan, and ROC again (if needed) on scan complete.

2. Keeping the antenna for a specific link.

We ROC until the connection was completed (after EAPOLs exchange)
in order to prevent BT coex operations from taking the antenna
and failing the connection (after this stage, psm can be used).

During association, we ROC on the station role, and then CROC
the device role, thus assuring being ROC during all the connection
process.

Delete the WL1271_FLAG_JOINED flag, and use a roc bitmap
to indicate what roles are currently ROCed.

Add wl12xx_roc/croc functions in order to wrap the roc/croc
commands while taking care of the roc bitmap.

The current ROC/CROC state-machine is a bit complicated. In
the future we'll probably want to use wpa_supplicant to control
the ROC during connection.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: squash, remove WL1271_FLAG_ROC

 drivers/net/wireless/wl12xx/cmd.c    |   39 +++++++++
 drivers/net/wireless/wl12xx/cmd.h    |    2 +
 drivers/net/wireless/wl12xx/main.c   |  144 ++++++++++++++++++++++++++-------
 drivers/net/wireless/wl12xx/scan.c   |   20 ++++--
 drivers/net/wireless/wl12xx/tx.c     |   13 +++
 drivers/net/wireless/wl12xx/wl12xx.h |    2 +-
 6 files changed, 182 insertions(+), 38 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 1b04102..c620a9d 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1551,6 +1551,45 @@ static int wl12xx_cmd_croc(struct wl1271 *wl, u8 role_id)
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
+
+int wl12xx_roc(struct wl1271 *wl, u8 role_id)
+{
+	int ret = 0;
+
+	if (WARN_ON(test_bit(role_id, wl->roc_map)))
+		return 0;
+
+	ret = wl12xx_cmd_roc(wl, role_id);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_cmd_wait_for_event(wl,
+					REMAIN_ON_CHANNEL_COMPLETE_EVENT_ID);
+	if (ret < 0) {
+		wl1271_error("cmd roc event completion error");
+		goto out;
+	}
+
+	__set_bit(role_id, wl->roc_map);
+out:
+	return ret;
+}
+
+int wl12xx_croc(struct wl1271 *wl, u8 role_id)
+{
+	int ret = 0;
+
+	if (WARN_ON(!test_bit(role_id, wl->roc_map)))
+		return 0;
+
+	ret = wl12xx_cmd_croc(wl, role_id);
+	if (ret < 0)
+		goto out;
+
+	__clear_bit(role_id, wl->roc_map);
+out:
+	return ret;
+}
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 80b02ed..5cf92e2 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -68,12 +68,14 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			   u8 key_size, const u8 *key, const u8 *addr,
 			   u32 tx_seq_32, u16 tx_seq_16);
 int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			  u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
 			  u16 tx_seq_16);
 int wl12xx_cmd_set_peer_state(struct wl1271 *wl);
+int wl12xx_roc(struct wl1271 *wl, u8 role_id);
+int wl12xx_croc(struct wl1271 *wl, u8 role_id);
 int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
 int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
 int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
 int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
 int wl12xx_cmd_stop_fwlog(struct wl1271 *wl);
 
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e4081e2..57b10e9 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -437,12 +437,14 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
 		return 0;
 
 	ret = wl12xx_cmd_set_peer_state(wl);
 	if (ret < 0)
 		return ret;
 
+	wl12xx_croc(wl, wl->role_id);
+
 	wl1271_info("Association completed.");
 	return 0;
 }
 static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
 			     void *arg)
 {
@@ -2065,12 +2067,13 @@ deinit:
 	wl->ap_ps_map = 0;
 	wl->sched_scanning = false;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
 	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
 	memset(wl->roles_map, 0, sizeof(wl->roles_map));
 	memset(wl->links_map, 0, sizeof(wl->links_map));
+	memset(wl->roc_map, 0, sizeof(wl->roc_map));
 
 	/* The system link is always allocated */
 	__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
 
 	/*
 	 * this is performed after the cancel_work calls and the associated
@@ -2107,31 +2110,12 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
 	}
 
 	mutex_unlock(&wl->mutex);
 	cancel_work_sync(&wl->recovery_work);
 }
 
-static int wl1271_dummy_join(struct wl1271 *wl)
-{
-	int ret = 0;
-	/* we need to use a dummy BSSID for now */
-	static const u8 dummy_bssid[ETH_ALEN] = { 0x0b, 0xad, 0xde,
-						  0xad, 0xbe, 0xef };
-
-	memcpy(wl->bssid, dummy_bssid, ETH_ALEN);
-
-	ret = wl12xx_cmd_role_start_sta(wl);
-	if (ret < 0)
-		goto out;
-
-	set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
-out:
-	return ret;
-}
-
 static int wl1271_join(struct wl1271 *wl, bool set_assoc)
 {
 	int ret;
 
 	/*
 	 * One of the side effects of the JOIN command is that is clears
@@ -2149,14 +2133,12 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
 		set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
 
 	ret = wl12xx_cmd_role_start_sta(wl);
 	if (ret < 0)
 		goto out;
 
-	set_bit(WL1271_FLAG_JOINED, &wl->flags);
-
 	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		goto out;
 
 	/*
 	 * The join command disable the keep-alive mode, shut down its process,
 	 * and also clear the template config, so we need to reset it all after
@@ -2190,13 +2172,12 @@ static int wl1271_unjoin(struct wl1271 *wl)
 
 	/* to stop listening to a channel, we disconnect */
 	ret = wl12xx_cmd_role_stop_sta(wl);
 	if (ret < 0)
 		goto out;
 
-	clear_bit(WL1271_FLAG_JOINED, &wl->flags);
 	memset(wl->bssid, 0, ETH_ALEN);
 
 	/* reset TX security counters on a clean disconnect */
 	wl->tx_security_last_seq_lsb = 0;
 	wl->tx_security_seq = 0;
 
@@ -2209,19 +2190,35 @@ static void wl1271_set_band_rate(struct wl1271 *wl)
 	if (wl->band == IEEE80211_BAND_2GHZ)
 		wl->basic_rate_set = wl->conf.tx.basic_rate;
 	else
 		wl->basic_rate_set = wl->conf.tx.basic_rate_5;
 }
 
+static bool wl12xx_is_roc(struct wl1271 *wl)
+{
+	u8 role_id;
+
+	role_id = find_first_bit(wl->roc_map, WL12XX_MAX_ROLES);
+	if (role_id >= WL12XX_MAX_ROLES)
+		return false;
+
+	return true;
+}
+
 static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
 {
 	int ret;
 
 	if (idle) {
-		if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
-			ret = wl1271_unjoin(wl);
+		/* no need to croc if we weren't busy (e.g. during boot) */
+		if (wl12xx_is_roc(wl)) {
+			ret = wl12xx_croc(wl, wl->dev_role_id);
+			if (ret < 0)
+				goto out;
+
+			ret = wl12xx_cmd_role_stop_dev(wl);
 			if (ret < 0)
 				goto out;
 		}
 		wl->rate_set = wl1271_tx_min_rate_get(wl);
 		ret = wl1271_acx_sta_rate_policies(wl);
 		if (ret < 0)
@@ -2241,13 +2238,17 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
 		/* The current firmware only supports sched_scan in idle */
 		if (wl->sched_scanning) {
 			wl1271_scan_sched_scan_stop(wl);
 			ieee80211_sched_scan_stopped(wl->hw);
 		}
 
-		ret = wl1271_dummy_join(wl);
+		ret = wl12xx_cmd_role_start_dev(wl);
+		if (ret < 0)
+			goto out;
+
+		ret = wl12xx_roc(wl, wl->dev_role_id);
 		if (ret < 0)
 			goto out;
 		clear_bit(WL1271_FLAG_IDLE, &wl->flags);
 	}
 
 out:
@@ -2321,17 +2322,40 @@ static int wl1271_op_config(struct ieee80211_hw *hw, u32 changed)
 			wl->basic_rate = wl1271_tx_min_rate_get(wl);
 			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
 				wl1271_warning("rate policy for channel "
 					       "failed %d", ret);
 
-			if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+			if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+				if (wl12xx_is_roc(wl)) {
+					/* roaming */
+					ret = wl12xx_croc(wl, wl->dev_role_id);
+					if (ret < 0)
+						goto out_sleep;
+				}
 				ret = wl1271_join(wl, false);
 				if (ret < 0)
 					wl1271_warning("cmd join on channel "
 						       "failed %d", ret);
+			} else {
+				/*
+				 * change the ROC channel. do it only if we are
+				 * not idle. otherwise, CROC will be called
+				 * anyway.
+				 */
+				if (wl12xx_is_roc(wl) &&
+				    !(conf->flags & IEEE80211_CONF_IDLE)) {
+					ret = wl12xx_croc(wl, wl->dev_role_id);
+					if (ret < 0)
+						goto out_sleep;
+
+					ret = wl12xx_roc(wl, wl->dev_role_id);
+					if (ret < 0)
+						wl1271_warning("roc failed %d",
+							       ret);
+				}
 			}
 		}
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) {
 		ret = wl1271_sta_handle_idle(wl,
@@ -2781,16 +2805,26 @@ static int wl1271_op_hw_scan(struct ieee80211_hw *hw,
 	}
 
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-	ret = wl1271_scan(hw->priv, ssid, len, req);
+	/* cancel ROC before scanning */
+	if (wl12xx_is_roc(wl)) {
+		if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+			/* don't allow scanning right now */
+			ret = -EBUSY;
+			goto out_sleep;
+		}
+		wl12xx_croc(wl, wl->dev_role_id);
+		wl12xx_cmd_role_stop_dev(wl);
+	}
 
+	ret = wl1271_scan(hw->priv, ssid, len, req);
+out_sleep:
 	wl1271_ps_elp_sleep(wl);
-
 out:
 	mutex_unlock(&wl->mutex);
 
 	return ret;
 }
 
@@ -3308,13 +3342,15 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 			}
 		} else {
 			/* use defaults when not associated */
 			bool was_assoc =
 			    !!test_and_clear_bit(WL1271_FLAG_STA_ASSOCIATED,
 						 &wl->flags);
-			clear_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags);
+			bool was_ifup =
+			    !!test_and_clear_bit(WL1271_FLAG_STA_STATE_SENT,
+						 &wl->flags);
 			wl->aid = 0;
 
 			/* free probe-request template */
 			dev_kfree_skb(wl->probereq);
 			wl->probereq = NULL;
 
@@ -3335,14 +3371,38 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 			ret = wl1271_acx_keep_alive_mode(wl, false);
 			if (ret < 0)
 				goto out;
 
 			/* restore the bssid filter and go to dummy bssid */
 			if (was_assoc) {
+				u32 conf_flags = wl->hw->conf.flags;
+				/*
+				 * we might have to disable roc, if there was
+				 * no IF_OPER_UP notification.
+				 */
+				if (!was_ifup) {
+					ret = wl12xx_croc(wl, wl->role_id);
+					if (ret < 0)
+						goto out;
+				}
+				/*
+				 * (we also need to disable roc in case of
+				 * roaming on the same channel. until we will
+				 * have a better flow...)
+				 */
+				if (test_bit(wl->dev_role_id, wl->roc_map)) {
+					ret = wl12xx_croc(wl, wl->dev_role_id);
+					if (ret < 0)
+						goto out;
+				}
+
 				wl1271_unjoin(wl);
-				wl1271_dummy_join(wl);
+				if (!(conf_flags & IEEE80211_CONF_IDLE)) {
+					wl12xx_cmd_role_start_dev(wl);
+					wl12xx_roc(wl, wl->dev_role_id);
+				}
 			}
 		}
 	}
 
 	if (changed & BSS_CHANGED_IBSS) {
 		wl1271_debug(DEBUG_ADHOC, "ibss_joined: %d",
@@ -3397,13 +3457,35 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 	if (do_join) {
 		ret = wl1271_join(wl, set_assoc);
 		if (ret < 0) {
 			wl1271_warning("cmd join failed %d", ret);
 			goto out;
 		}
-		wl1271_check_operstate(wl, ieee80211_get_operstate(vif));
+
+		/* ROC until connected (after EAPOL exchange) */
+		if (!is_ibss) {
+			ret = wl12xx_roc(wl, wl->role_id);
+			if (ret < 0)
+				goto out;
+
+			wl1271_check_operstate(wl,
+					       ieee80211_get_operstate(vif));
+		}
+		/*
+		 * stop device role if started (we might already be in
+		 * STA role). TODO: make it better.
+		 */
+		if (wl->dev_role_id != WL12XX_INVALID_ROLE_ID) {
+			ret = wl12xx_croc(wl, wl->dev_role_id);
+			if (ret < 0)
+				goto out;
+
+			ret = wl12xx_cmd_role_stop_dev(wl);
+			if (ret < 0)
+				goto out;
+		}
 	}
 
 out:
 	return;
 }
 
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 54a4e75..653091a 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -30,12 +30,13 @@
 #include "ps.h"
 
 void wl1271_scan_complete_work(struct work_struct *work)
 {
 	struct delayed_work *dwork;
 	struct wl1271 *wl;
+	int ret;
 
 	dwork = container_of(work, struct delayed_work, work);
 	wl = container_of(dwork, struct wl1271, scan_complete_work);
 
 	wl1271_debug(DEBUG_SCAN, "Scanning complete");
 
@@ -47,27 +48,34 @@ void wl1271_scan_complete_work(struct work_struct *work)
 	if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
 		goto out;
 
 	wl->scan.state = WL1271_SCAN_STATE_IDLE;
 	memset(wl->scan.scanned_ch, 0, sizeof(wl->scan.scanned_ch));
 	wl->scan.req = NULL;
-	ieee80211_scan_completed(wl->hw, false);
 
-	/* restore hardware connection monitoring template */
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
 	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
-		if (wl1271_ps_elp_wakeup(wl) == 0) {
-			wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
-			wl1271_ps_elp_sleep(wl);
-		}
+		/* restore hardware connection monitoring template */
+		wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
+	} else {
+		/* restore remain on channel */
+		wl12xx_cmd_role_start_dev(wl);
+		wl12xx_roc(wl, wl->dev_role_id);
 	}
+	wl1271_ps_elp_sleep(wl);
 
 	if (wl->scan.failed) {
 		wl1271_info("Scan completed due to error.");
 		wl12xx_queue_recovery_work(wl);
 	}
 
+	ieee80211_scan_completed(wl->hw, false);
+
 out:
 	mutex_unlock(&wl->mutex);
 
 }
 
 
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ffdaf97..1ea5482 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -75,12 +75,13 @@ static void wl1271_free_tx_id(struct wl1271 *wl, int id)
 }
 
 static int wl1271_tx_update_filters(struct wl1271 *wl,
 						 struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr;
+	int ret;
 
 	hdr = (struct ieee80211_hdr *)(skb->data +
 				       sizeof(struct wl1271_tx_hw_descr));
 
 	/*
 	 * stop bssid-based filtering before transmitting authentication
@@ -88,12 +89,24 @@ static int wl1271_tx_update_filters(struct wl1271 *wl,
 	 * responses coming from BSSIDs it isn't familiar with (e.g. on
 	 * roaming)
 	 */
 	if (!ieee80211_is_auth(hdr->frame_control))
 		return 0;
 
+	if (wl->dev_hlid != WL12XX_INVALID_LINK_ID)
+		goto out;
+
+	wl1271_debug(DEBUG_CMD, "starting device role for roaming");
+	ret = wl12xx_cmd_role_start_dev(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl12xx_roc(wl, wl->dev_role_id);
+	if (ret < 0)
+		goto out;
+out:
 	return 0;
 }
 
 static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
 						 struct sk_buff *skb)
 {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 089304d..a136795 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -316,13 +316,12 @@ struct wl1271_ap_key {
 	u32 tx_seq_32;
 	u16 tx_seq_16;
 };
 
 enum wl12xx_flags {
 	WL1271_FLAG_STA_ASSOCIATED,
-	WL1271_FLAG_JOINED,
 	WL1271_FLAG_GPIO_POWER,
 	WL1271_FLAG_TX_QUEUE_STOPPED,
 	WL1271_FLAG_TX_PENDING,
 	WL1271_FLAG_IN_ELP,
 	WL1271_FLAG_ELP_REQUESTED,
 	WL1271_FLAG_PSM,
@@ -399,12 +398,13 @@ struct wl1271 {
 	u8 system_hlid;
 	u8 sta_hlid;
 	u8 dev_hlid;
 
 	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
 	unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
+	unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 
 	struct wl1271_acx_mem_map *target_mem_map;
 
 	/* Accounting for allocated / available TX blocks on HW */
 	u32 tx_blocks_freed;
 	u32 tx_blocks_available;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 19/40] wl12xx: handle dummy packet event also in ap mode
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (17 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 18/40] wl12xx: replace dummy_join with " Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 20/40] wl12xx: update BT coex configuration params Eliad Peller
                   ` (21 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Allow handling of DUMMY_PACKET_EVENT_ID also in ap mode.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/event.c |    2 +-
 drivers/net/wireless/wl12xx/tx.c    |   12 ++++++++----
 2 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/event.c b/drivers/net/wireless/wl12xx/event.c
index 431ceae..0bd7b02 100644
--- a/drivers/net/wireless/wl12xx/event.c
+++ b/drivers/net/wireless/wl12xx/event.c
@@ -288,13 +288,13 @@ static int wl1271_event_process(struct wl1271 *wl, struct event_mailbox *mbox)
 			     "ba_allowed = 0x%x", mbox->rx_ba_allowed);
 
 		if (wl->vif)
 			wl1271_stop_ba_event(wl, mbox->rx_ba_allowed);
 	}
 
-	if ((vector & DUMMY_PACKET_EVENT_ID) && !is_ap) {
+	if ((vector & DUMMY_PACKET_EVENT_ID)) {
 		wl1271_debug(DEBUG_EVENT, "DUMMY_PACKET_ID_EVENT_ID");
 		if (wl->vif)
 			wl1271_tx_dummy_packet(wl);
 	}
 
 	/*
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 1ea5482..057db6f 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -831,16 +831,20 @@ void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
 	int total[NUM_TX_QUEUES];
 
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
 		total[i] = 0;
 		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
 			wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
-			info = IEEE80211_SKB_CB(skb);
-			info->status.rates[0].idx = -1;
-			info->status.rates[0].count = 0;
-			ieee80211_tx_status_ni(wl->hw, skb);
+
+			if (!wl12xx_is_dummy_packet(wl, skb)) {
+				info = IEEE80211_SKB_CB(skb);
+				info->status.rates[0].idx = -1;
+				info->status.rates[0].count = 0;
+				ieee80211_tx_status_ni(wl->hw, skb);
+			}
+
 			total[i]++;
 		}
 	}
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
 	for (i = 0; i < NUM_TX_QUEUES; i++)
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 20/40] wl12xx: update BT coex configuration params
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (18 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 19/40] wl12xx: handle dummy packet event also in ap mode Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 21/40] wl12xx: fix session counter Eliad Peller
                   ` (20 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

The BT coex params api have been changed.
Update it, and init coex for both sta and ap.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: fix comments, don't disable fm coex

 drivers/net/wireless/wl12xx/acx.c  |   40 +----
 drivers/net/wireless/wl12xx/acx.h  |   16 +--
 drivers/net/wireless/wl12xx/conf.h |  318 ++++++++++++------------------------
 drivers/net/wireless/wl12xx/init.c |    5 +-
 drivers/net/wireless/wl12xx/main.c |  165 +++++++------------
 5 files changed, 177 insertions(+), 367 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index a784ba6..d783fce 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -525,59 +525,29 @@ int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable)
 
 out:
 	kfree(pta);
 	return ret;
 }
 
-int wl1271_acx_sta_sg_cfg(struct wl1271 *wl)
+int wl12xx_acx_sg_cfg(struct wl1271 *wl)
 {
-	struct acx_sta_bt_wlan_coex_param *param;
+	struct acx_bt_wlan_coex_param *param;
 	struct conf_sg_settings *c = &wl->conf.sg;
 	int i, ret;
 
-	wl1271_debug(DEBUG_ACX, "acx sg sta cfg");
+	wl1271_debug(DEBUG_ACX, "acx sg cfg");
 
 	param = kzalloc(sizeof(*param), GFP_KERNEL);
 	if (!param) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
 	/* BT-WLAN coext parameters */
-	for (i = 0; i < CONF_SG_STA_PARAMS_MAX; i++)
-		param->params[i] = cpu_to_le32(c->sta_params[i]);
-	param->param_idx = CONF_SG_PARAMS_ALL;
-
-	ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
-	if (ret < 0) {
-		wl1271_warning("failed to set sg config: %d", ret);
-		goto out;
-	}
-
-out:
-	kfree(param);
-	return ret;
-}
-
-int wl1271_acx_ap_sg_cfg(struct wl1271 *wl)
-{
-	struct acx_ap_bt_wlan_coex_param *param;
-	struct conf_sg_settings *c = &wl->conf.sg;
-	int i, ret;
-
-	wl1271_debug(DEBUG_ACX, "acx sg ap cfg");
-
-	param = kzalloc(sizeof(*param), GFP_KERNEL);
-	if (!param) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	/* BT-WLAN coext parameters */
-	for (i = 0; i < CONF_SG_AP_PARAMS_MAX; i++)
-		param->params[i] = cpu_to_le32(c->ap_params[i]);
+	for (i = 0; i < CONF_SG_PARAMS_MAX; i++)
+		param->params[i] = cpu_to_le32(c->params[i]);
 	param->param_idx = CONF_SG_PARAMS_ALL;
 
 	ret = wl1271_cmd_configure(wl, ACX_SG_CFG, param, sizeof(*param));
 	if (ret < 0) {
 		wl1271_warning("failed to set sg config: %d", ret);
 		goto out;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 6909bc5..5b3fabd 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -299,29 +299,20 @@ struct acx_bt_wlan_coex {
 	struct acx_header header;
 
 	u8 enable;
 	u8 pad[3];
 } __packed;
 
-struct acx_sta_bt_wlan_coex_param {
+struct acx_bt_wlan_coex_param {
 	struct acx_header header;
 
-	__le32 params[CONF_SG_STA_PARAMS_MAX];
+	__le32 params[CONF_SG_PARAMS_MAX];
 	u8 param_idx;
 	u8 padding[3];
 } __packed;
 
-struct acx_ap_bt_wlan_coex_param {
-	struct acx_header header;
-
-	__le32 params[CONF_SG_AP_PARAMS_MAX];
-	u8 param_idx;
-	u8 padding[3];
-} __packed;
-
-
 struct acx_dco_itrim_params {
 	struct acx_header header;
 
 	u8 enable;
 	u8 padding[3];
 	__le32 timeout;
@@ -1266,14 +1257,13 @@ int wl1271_acx_service_period_timeout(struct wl1271 *wl);
 int wl1271_acx_rts_threshold(struct wl1271 *wl, u32 rts_threshold);
 int wl1271_acx_dco_itrim_params(struct wl1271 *wl);
 int wl1271_acx_beacon_filter_opt(struct wl1271 *wl, bool enable_filter);
 int wl1271_acx_beacon_filter_table(struct wl1271 *wl);
 int wl1271_acx_conn_monit_params(struct wl1271 *wl, bool enable);
 int wl1271_acx_sg_enable(struct wl1271 *wl, bool enable);
-int wl1271_acx_sta_sg_cfg(struct wl1271 *wl);
-int wl1271_acx_ap_sg_cfg(struct wl1271 *wl);
+int wl12xx_acx_sg_cfg(struct wl1271 *wl);
 int wl1271_acx_cca_threshold(struct wl1271 *wl);
 int wl1271_acx_bcn_dtim_options(struct wl1271 *wl);
 int wl1271_acx_aid(struct wl1271 *wl, u16 aid);
 int wl1271_acx_event_mbox_mask(struct wl1271 *wl, u32 event_mask);
 int wl1271_acx_set_preamble(struct wl1271 *wl, enum acx_preamble_type preamble);
 int wl1271_acx_cts_protect(struct wl1271 *wl,
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 30ee7d3..a7c1478 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -96,46 +96,81 @@ enum {
 	CONF_SG_PROTECTIVE,
 	CONF_SG_OPPORTUNISTIC
 };
 
 enum {
 	/*
-	 * PER threshold in PPM of the BT voice
+	 * Configure the min and max time BT gains the antenna
+	 * in WLAN / BT master basic rate
 	 *
-	 * Range: 0 - 10000000
+	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_BT_PER_THRESHOLD = 0,
+	CONF_SG_ACL_BT_MASTER_MIN_BR = 0,
+	CONF_SG_ACL_BT_MASTER_MAX_BR,
 
 	/*
-	 * Number of consequent RX_ACTIVE activities to override BT voice
-	 * frames to ensure WLAN connection
+	 * Configure the min and max time BT gains the antenna
+	 * in WLAN / BT slave basic rate
 	 *
-	 * Range: 0 - 100
+	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_HV3_MAX_OVERRIDE,
+	CONF_SG_ACL_BT_SLAVE_MIN_BR,
+	CONF_SG_ACL_BT_SLAVE_MAX_BR,
 
 	/*
-	 * Defines the PER threshold of the BT voice
+	 * Configure the min and max time BT gains the antenna
+	 * in WLAN / BT master EDR
 	 *
-	 * Range: 0 - 65000
+	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_BT_NFS_SAMPLE_INTERVAL,
+	CONF_SG_ACL_BT_MASTER_MIN_EDR,
+	CONF_SG_ACL_BT_MASTER_MAX_EDR,
 
 	/*
-	 * Defines the load ratio of BT
+	 * Configure the min and max time BT gains the antenna
+	 * in WLAN / BT slave EDR
 	 *
-	 * Range: 0 - 100 (%)
+	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_BT_LOAD_RATIO,
+	CONF_SG_ACL_BT_SLAVE_MIN_EDR,
+	CONF_SG_ACL_BT_SLAVE_MAX_EDR,
 
 	/*
-	 * Defines whether the SG will force WLAN host to enter/exit PSM
+	 * The maximum time WLAN can gain the antenna
+	 * in WLAN PSM / BT master/slave BR
 	 *
-	 * Range: 1 - SG can force, 0 - host handles PSM
+	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_AUTO_PS_MODE,
+	CONF_SG_ACL_WLAN_PS_MASTER_BR,
+	CONF_SG_ACL_WLAN_PS_SLAVE_BR,
+
+	/*
+	 * The maximum time WLAN can gain the antenna
+	 * in WLAN PSM / BT master/slave EDR
+	 *
+	 * Range: 0 - 255 (ms)
+	 */
+	CONF_SG_ACL_WLAN_PS_MASTER_EDR,
+	CONF_SG_ACL_WLAN_PS_SLAVE_EDR,
+
+	/* TODO: explain these values */
+	CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR,
+	CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR,
+	CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR,
+	CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR,
+	CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR,
+	CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR,
+	CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR,
+	CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR,
+
+	CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR,
+	CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR,
+	CONF_SG_ACL_PASSIVE_SCAN_BT_BR,
+	CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR,
+	CONF_SG_ACL_PASSIVE_SCAN_BT_EDR,
+	CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR,
 
 	/*
 	 * Compensation percentage of probe requests when scan initiated
 	 * during BT voice/ACL link.
 	 *
 	 * Range: 0 - 255 (%)
@@ -148,108 +183,76 @@ enum {
 	 *
 	 * Range: 0 - 255 (%)
 	 */
 	CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3,
 
 	/*
-	 * Defines antenna configuration (single/dual antenna)
-	 *
-	 * Range: 0 - single antenna, 1 - dual antenna
-	 */
-	CONF_SG_ANTENNA_CONFIGURATION,
-
-	/*
-	 * The threshold (percent) of max consequtive beacon misses before
-	 * increasing priority of beacon reception.
-	 *
-	 * Range: 0 - 100 (%)
-	 */
-	CONF_SG_BEACON_MISS_PERCENT,
-
-	/*
-	 * The rate threshold below which receiving a data frame from the AP
-	 * will increase the priority of the data frame above BT traffic.
-	 *
-	 * Range: 0,2, 5(=5.5), 6, 9, 11, 12, 18, 24, 36, 48, 54
-	 */
-	CONF_SG_RATE_ADAPT_THRESH,
-
-	/*
-	 * Not used currently.
+	 * Compensation percentage of WLAN active scan window if initiated
+	 * during BT A2DP
 	 *
-	 * Range: 0
+	 * Range: 0 - 1000 (%)
 	 */
-	CONF_SG_RATE_ADAPT_SNR,
+	CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
 
 	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN PSM / BT master basic rate
+	 * Compensation percentage of WLAN passive scan window if initiated
+	 * during BT A2DP BR
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - 1000 (%)
 	 */
-	CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR,
-	CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR,
+	CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR,
 
 	/*
-	 * The time after it expires no new WLAN trigger frame is trasmitted
-	 * in WLAN PSM / BT master basic rate
+	 * Compensation percentage of WLAN passive scan window if initiated
+	 * during BT A2DP EDR
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - 1000 (%)
 	 */
-	CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR,
+	CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR,
 
 	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN PSM / BT slave basic rate
+	 * Compensation percentage of WLAN passive scan window if initiated
+	 * during BT voice
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - 1000 (%)
 	 */
-	CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR,
-	CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR,
+	CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
 
-	/*
-	 * The time after it expires no new WLAN trigger frame is trasmitted
-	 * in WLAN PSM / BT slave basic rate
-	 *
-	 * Range: 0 - 255 (ms)
-	 */
-	CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR,
+	/* TODO: explain these values */
+	CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN,
+	CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN,
+	CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN,
 
 	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN PSM / BT master EDR
+	 * Defines whether the SG will force WLAN host to enter/exit PSM
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 1 - SG can force, 0 - host handles PSM
 	 */
-	CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR,
-	CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR,
+	CONF_SG_STA_FORCE_PS_IN_BT_SCO,
 
 	/*
-	 * The time after it expires no new WLAN trigger frame is trasmitted
-	 * in WLAN PSM / BT master EDR
+	 * Defines antenna configuration (single/dual antenna)
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - single antenna, 1 - dual antenna
 	 */
-	CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR,
+	CONF_SG_ANTENNA_CONFIGURATION,
 
 	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN PSM / BT slave EDR
+	 * The threshold (percent) of max consecutive beacon misses before
+	 * increasing priority of beacon reception.
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - 100 (%)
 	 */
-	CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR,
-	CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR,
+	CONF_SG_BEACON_MISS_PERCENT,
 
 	/*
-	 * The time after it expires no new WLAN trigger frame is trasmitted
-	 * in WLAN PSM / BT slave EDR
+	 * Protection time of the DHCP procedure.
 	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - 100000 (ms)
 	 */
-	CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR,
+	CONF_SG_DHCP_TIME,
 
 	/*
 	 * RX guard time before the beginning of a new BT voice frame during
 	 * which no new WLAN trigger frame is transmitted.
 	 *
 	 * Range: 0 - 100000 (us)
@@ -270,172 +273,65 @@ enum {
 	 * will be utilized.
 	 *
 	 * Range: 0 - disable, 1 - enable
 	 */
 	CONF_SG_ADAPTIVE_RXT_TXT,
 
-	/*
-	 * The used WLAN legacy service period during active BT ACL link
-	 *
-	 * Range: 0 - 255 (ms)
-	 */
-	CONF_SG_PS_POLL_TIMEOUT,
-
-	/*
-	 * The used WLAN UPSD service period during active BT ACL link
-	 *
-	 * Range: 0 - 255 (ms)
-	 */
-	CONF_SG_UPSD_TIMEOUT,
-
-	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN Active / BT master EDR
-	 *
-	 * Range: 0 - 255 (ms)
-	 */
-	CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR,
-	CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR,
-
-	/*
-	 * The maximum time WLAN can gain the antenna for
-	 * in WLAN Active / BT master EDR
-	 *
-	 * Range: 0 - 255 (ms)
-	 */
-	CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR,
+	/* TODO: explain this value */
+	CONF_SG_GENERAL_USAGE_BIT_MAP,
 
 	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN Active / BT slave EDR
+	 * Number of consecutive BT voice frames not interrupted by WLAN
 	 *
-	 * Range: 0 - 255 (ms)
-	 */
-	CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR,
-	CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR,
-
-	/*
-	 * The maximum time WLAN can gain the antenna for
-	 * in WLAN Active / BT slave EDR
-	 *
-	 * Range: 0 - 255 (ms)
+	 * Range: 0 - 100
 	 */
-	CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR,
+	CONF_SG_HV3_MAX_SERVED,
 
 	/*
-	 * Configure the min and max time BT gains the antenna
-	 * in WLAN Active / BT basic rate
+	 * The used WLAN legacy service period during active BT ACL link
 	 *
 	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR,
-	CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR,
+	CONF_SG_PS_POLL_TIMEOUT,
 
 	/*
-	 * The maximum time WLAN can gain the antenna for
-	 * in WLAN Active / BT basic rate
+	 * The used WLAN UPSD service period during active BT ACL link
 	 *
 	 * Range: 0 - 255 (ms)
 	 */
-	CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR,
-
-	/*
-	 * Compensation percentage of WLAN passive scan window if initiated
-	 * during BT voice
-	 *
-	 * Range: 0 - 1000 (%)
-	 */
-	CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3,
-
-	/*
-	 * Compensation percentage of WLAN passive scan window if initiated
-	 * during BT A2DP
-	 *
-	 * Range: 0 - 1000 (%)
-	 */
-	CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP,
+	CONF_SG_UPSD_TIMEOUT,
 
-	/*
-	 * Fixed time ensured for BT traffic to gain the antenna during WLAN
-	 * passive scan.
-	 *
-	 * Range: 0 - 1000 ms
-	 */
-	CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME,
+	CONF_SG_CONSECUTIVE_CTS_THRESHOLD,
+	CONF_SG_STA_RX_WINDOW_AFTER_DTIM,
+	CONF_SG_STA_CONNECTION_PROTECTION_TIME,
 
-	/*
-	 * Fixed time ensured for WLAN traffic to gain the antenna during WLAN
-	 * passive scan.
-	 *
-	 * Range: 0 - 1000 ms
-	 */
-	CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME,
+	/* AP params */
+	CONF_AP_BEACON_MISS_TX,
+	CONF_AP_RX_WINDOW_AFTER_BEACON,
+	CONF_AP_BEACON_WINDOW_INTERVAL,
+	CONF_AP_CONNECTION_PROTECTION_TIME,
+	CONF_AP_BT_ACL_VAL_BT_SERVE_TIME,
+	CONF_AP_BT_ACL_VAL_WL_SERVE_TIME,
 
-	/*
-	 * Number of consequent BT voice frames not interrupted by WLAN
-	 *
-	 * Range: 0 - 100
-	 */
-	CONF_SG_HV3_MAX_SERVED,
-
-	/*
-	 * Protection time of the DHCP procedure.
-	 *
-	 * Range: 0 - 100000 (ms)
-	 */
-	CONF_SG_DHCP_TIME,
-
-	/*
-	 * Compensation percentage of WLAN active scan window if initiated
-	 * during BT A2DP
-	 *
-	 * Range: 0 - 1000 (%)
-	 */
-	CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP,
 	CONF_SG_TEMP_PARAM_1,
 	CONF_SG_TEMP_PARAM_2,
 	CONF_SG_TEMP_PARAM_3,
 	CONF_SG_TEMP_PARAM_4,
 	CONF_SG_TEMP_PARAM_5,
-
-	/*
-	 * AP beacon miss
-	 *
-	 * Range: 0 - 255
-	 */
-	CONF_SG_AP_BEACON_MISS_TX,
-
-	/*
-	 * AP RX window length
-	 *
-	 * Range: 0 - 50
-	 */
-	CONF_SG_RX_WINDOW_LENGTH,
-
-	/*
-	 * AP connection protection time
-	 *
-	 * Range: 0 - 5000
-	 */
-	CONF_SG_AP_CONNECTION_PROTECTION_TIME,
-
 	CONF_SG_TEMP_PARAM_6,
 	CONF_SG_TEMP_PARAM_7,
 	CONF_SG_TEMP_PARAM_8,
 	CONF_SG_TEMP_PARAM_9,
 	CONF_SG_TEMP_PARAM_10,
 
-	CONF_SG_STA_PARAMS_MAX = CONF_SG_TEMP_PARAM_5 + 1,
-	CONF_SG_AP_PARAMS_MAX = CONF_SG_TEMP_PARAM_10 + 1,
-
+	CONF_SG_PARAMS_MAX,
 	CONF_SG_PARAMS_ALL = 0xff
 };
 
 struct conf_sg_settings {
-	u32 sta_params[CONF_SG_STA_PARAMS_MAX];
-	u32 ap_params[CONF_SG_AP_PARAMS_MAX];
+	u32 params[CONF_SG_PARAMS_MAX];
 	u8 state;
 };
 
 enum conf_rx_queue_type {
 	CONF_RX_QUEUE_TYPE_LOW_PRIORITY,  /* All except the high priority */
 	CONF_RX_QUEUE_TYPE_HIGH_PRIORITY, /* Management and voice packets */
@@ -910,13 +806,13 @@ struct conf_conn_settings {
 	 * Configure Beacon filter pass-thru rules.
 	 */
 	u8 bcn_filt_ie_count;
 	struct conf_bcn_filt_rule bcn_filt_ie[CONF_MAX_BCN_FILT_IE_COUNT];
 
 	/*
-	 * The number of consequtive beacons to lose, before the firmware
+	 * The number of consecutive beacons to lose, before the firmware
 	 * becomes out of synch.
 	 *
 	 * Range: u32
 	 */
 	u32 synch_fail_thold;
 
@@ -948,13 +844,13 @@ struct conf_conn_settings {
 	 *
 	 * Range: 1 - enable, 0 - disable
 	 */
 	u8 rx_broadcast_in_ps;
 
 	/*
-	 * Consequtive PS Poll failures before sending event to driver
+	 * Consecutive PS Poll failures before sending event to driver
 	 *
 	 * Range: u8
 	 */
 	u8 ps_poll_threshold;
 
 	/*
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 1bc246f..47d87aa 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -274,16 +274,13 @@ static int wl1271_init_beacon_filter(struct wl1271 *wl)
 }
 
 int wl1271_init_pta(struct wl1271 *wl)
 {
 	int ret;
 
-	if (wl->bss_type == BSS_TYPE_AP_BSS)
-		ret = wl1271_acx_ap_sg_cfg(wl);
-	else
-		ret = wl1271_acx_sta_sg_cfg(wl);
+	ret = wl12xx_acx_sg_cfg(wl);
 	if (ret < 0)
 		return ret;
 
 	ret = wl1271_acx_sg_enable(wl, wl->sg_enabled);
 	if (ret < 0)
 		return ret;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 57b10e9..1774a66 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -49,116 +49,73 @@
 #include "scan.h"
 
 #define WL1271_BOOT_RETRIES 3
 
 static struct conf_drv_settings default_conf = {
 	.sg = {
-		.sta_params = {
-			[CONF_SG_BT_PER_THRESHOLD]                  = 7500,
-			[CONF_SG_HV3_MAX_OVERRIDE]                  = 0,
-			[CONF_SG_BT_NFS_SAMPLE_INTERVAL]            = 400,
-			[CONF_SG_BT_LOAD_RATIO]                     = 200,
-			[CONF_SG_AUTO_PS_MODE]                      = 1,
-			[CONF_SG_AUTO_SCAN_PROBE_REQ]               = 170,
-			[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3]   = 50,
-			[CONF_SG_ANTENNA_CONFIGURATION]             = 0,
-			[CONF_SG_BEACON_MISS_PERCENT]               = 60,
-			[CONF_SG_RATE_ADAPT_THRESH]                 = 12,
-			[CONF_SG_RATE_ADAPT_SNR]                    = 0,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR]      = 10,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR]      = 30,
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR]      = 8,
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR]       = 20,
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR]       = 50,
-			/* Note: with UPSD, this should be 4 */
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR]       = 8,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR]     = 7,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR]     = 25,
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR]     = 20,
-			/* Note: with UPDS, this should be 15 */
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR]      = 8,
-			/* Note: with UPDS, this should be 50 */
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR]      = 40,
-			/* Note: with UPDS, this should be 10 */
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR]      = 20,
-			[CONF_SG_RXT]                               = 1200,
-			[CONF_SG_TXT]                               = 1000,
-			[CONF_SG_ADAPTIVE_RXT_TXT]                  = 1,
-			[CONF_SG_PS_POLL_TIMEOUT]                   = 10,
-			[CONF_SG_UPSD_TIMEOUT]                      = 10,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
-			[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR]  = 8,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR]  = 20,
-			[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR]  = 15,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR]         = 20,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR]         = 50,
-			[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR]         = 10,
-			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3]  = 200,
-			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
-			[CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME]         = 75,
-			[CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME]       = 15,
-			[CONF_SG_HV3_MAX_SERVED]                    = 6,
-			[CONF_SG_DHCP_TIME]                         = 5000,
-			[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP]  = 100,
-		},
-		.ap_params = {
-			[CONF_SG_BT_PER_THRESHOLD]                  = 7500,
-			[CONF_SG_HV3_MAX_OVERRIDE]                  = 0,
-			[CONF_SG_BT_NFS_SAMPLE_INTERVAL]            = 400,
-			[CONF_SG_BT_LOAD_RATIO]                     = 50,
-			[CONF_SG_AUTO_PS_MODE]                      = 1,
-			[CONF_SG_AUTO_SCAN_PROBE_REQ]               = 170,
-			[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3]   = 50,
-			[CONF_SG_ANTENNA_CONFIGURATION]             = 0,
-			[CONF_SG_BEACON_MISS_PERCENT]               = 60,
-			[CONF_SG_RATE_ADAPT_THRESH]                 = 64,
-			[CONF_SG_RATE_ADAPT_SNR]                    = 1,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_BR]      = 10,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_BR]      = 25,
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_BR]      = 25,
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_BR]       = 20,
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_BR]       = 25,
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_BR]       = 25,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MIN_EDR]     = 7,
-			[CONF_SG_WLAN_PS_BT_ACL_MASTER_MAX_EDR]     = 25,
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_MASTER_EDR]     = 25,
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MIN_EDR]      = 8,
-			[CONF_SG_WLAN_PS_BT_ACL_SLAVE_MAX_EDR]      = 25,
-			[CONF_SG_WLAN_PS_MAX_BT_ACL_SLAVE_EDR]      = 25,
-			[CONF_SG_RXT]                               = 1200,
-			[CONF_SG_TXT]                               = 1000,
-			[CONF_SG_ADAPTIVE_RXT_TXT]                  = 1,
-			[CONF_SG_PS_POLL_TIMEOUT]                   = 10,
-			[CONF_SG_UPSD_TIMEOUT]                      = 10,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MIN_EDR] = 7,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MASTER_MAX_EDR] = 15,
-			[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_MASTER_EDR] = 15,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MIN_EDR]  = 8,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_SLAVE_MAX_EDR]  = 20,
-			[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_SLAVE_EDR]  = 15,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MIN_BR]         = 20,
-			[CONF_SG_WLAN_ACTIVE_BT_ACL_MAX_BR]         = 50,
-			[CONF_SG_WLAN_ACTIVE_MAX_BT_ACL_BR]         = 10,
-			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3]  = 200,
-			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP] = 800,
-			[CONF_SG_PASSIVE_SCAN_A2DP_BT_TIME]         = 75,
-			[CONF_SG_PASSIVE_SCAN_A2DP_WLAN_TIME]       = 15,
-			[CONF_SG_HV3_MAX_SERVED]                    = 6,
-			[CONF_SG_DHCP_TIME]                         = 5000,
-			[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP]  = 100,
-			[CONF_SG_TEMP_PARAM_1]                      = 0,
-			[CONF_SG_TEMP_PARAM_2]                      = 0,
-			[CONF_SG_TEMP_PARAM_3]                      = 0,
-			[CONF_SG_TEMP_PARAM_4]                      = 0,
-			[CONF_SG_TEMP_PARAM_5]                      = 0,
-			[CONF_SG_AP_BEACON_MISS_TX]                 = 3,
-			[CONF_SG_RX_WINDOW_LENGTH]                  = 6,
-			[CONF_SG_AP_CONNECTION_PROTECTION_TIME]     = 50,
-			[CONF_SG_TEMP_PARAM_6]                      = 1,
+		.params = {
+			[CONF_SG_ACL_BT_MASTER_MIN_BR] = 10,
+			[CONF_SG_ACL_BT_MASTER_MAX_BR] = 180,
+			[CONF_SG_ACL_BT_SLAVE_MIN_BR] = 10,
+			[CONF_SG_ACL_BT_SLAVE_MAX_BR] = 180,
+			[CONF_SG_ACL_BT_MASTER_MIN_EDR] = 10,
+			[CONF_SG_ACL_BT_MASTER_MAX_EDR] = 80,
+			[CONF_SG_ACL_BT_SLAVE_MIN_EDR] = 10,
+			[CONF_SG_ACL_BT_SLAVE_MAX_EDR] = 80,
+			[CONF_SG_ACL_WLAN_PS_MASTER_BR] = 8,
+			[CONF_SG_ACL_WLAN_PS_SLAVE_BR] = 8,
+			[CONF_SG_ACL_WLAN_PS_MASTER_EDR] = 20,
+			[CONF_SG_ACL_WLAN_PS_SLAVE_EDR] = 20,
+			[CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_BR] = 20,
+			[CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_BR] = 35,
+			[CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_BR] = 16,
+			[CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_BR] = 35,
+			[CONF_SG_ACL_WLAN_ACTIVE_MASTER_MIN_EDR] = 32,
+			[CONF_SG_ACL_WLAN_ACTIVE_MASTER_MAX_EDR] = 50,
+			[CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MIN_EDR] = 28,
+			[CONF_SG_ACL_WLAN_ACTIVE_SLAVE_MAX_EDR] = 50,
+			[CONF_SG_ACL_ACTIVE_SCAN_WLAN_BR] = 10,
+			[CONF_SG_ACL_ACTIVE_SCAN_WLAN_EDR] = 20,
+			[CONF_SG_ACL_PASSIVE_SCAN_BT_BR] = 75,
+			[CONF_SG_ACL_PASSIVE_SCAN_WLAN_BR] = 15,
+			[CONF_SG_ACL_PASSIVE_SCAN_BT_EDR] = 27,
+			[CONF_SG_ACL_PASSIVE_SCAN_WLAN_EDR] = 17,
+			/* active scan params */
+			[CONF_SG_AUTO_SCAN_PROBE_REQ] = 170,
+			[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_HV3] = 50,
+			[CONF_SG_ACTIVE_SCAN_DURATION_FACTOR_A2DP] = 100,
+			/* passive scan params */
+			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_BR] = 800,
+			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_A2DP_EDR] = 200,
+			[CONF_SG_PASSIVE_SCAN_DURATION_FACTOR_HV3] = 200,
+			/* passive scan in dual antenna params */
+			[CONF_SG_CONSECUTIVE_HV3_IN_PASSIVE_SCAN] = 0,
+			[CONF_SG_BCN_HV3_COLLISION_THRESH_IN_PASSIVE_SCAN] = 0,
+			[CONF_SG_TX_RX_PROTECTION_BWIDTH_IN_PASSIVE_SCAN] = 0,
+			/* general params */
+			[CONF_SG_STA_FORCE_PS_IN_BT_SCO] = 1,
+			[CONF_SG_ANTENNA_CONFIGURATION] = 0,
+			[CONF_SG_BEACON_MISS_PERCENT] = 60,
+			[CONF_SG_DHCP_TIME] = 5000,
+			[CONF_SG_RXT] = 1200,
+			[CONF_SG_TXT] = 1000,
+			[CONF_SG_ADAPTIVE_RXT_TXT] = 1,
+			[CONF_SG_GENERAL_USAGE_BIT_MAP] = 3,
+			[CONF_SG_HV3_MAX_SERVED] = 6,
+			[CONF_SG_PS_POLL_TIMEOUT] = 10,
+			[CONF_SG_UPSD_TIMEOUT] = 10,
+			[CONF_SG_CONSECUTIVE_CTS_THRESHOLD] = 2,
+			[CONF_SG_STA_RX_WINDOW_AFTER_DTIM] = 5,
+			[CONF_SG_STA_CONNECTION_PROTECTION_TIME] = 30,
+			/* AP params */
+			[CONF_AP_BEACON_MISS_TX] = 3,
+			[CONF_AP_RX_WINDOW_AFTER_BEACON] = 10,
+			[CONF_AP_BEACON_WINDOW_INTERVAL] = 2,
+			[CONF_AP_CONNECTION_PROTECTION_TIME] = 0,
+			[CONF_AP_BT_ACL_VAL_BT_SERVE_TIME] = 25,
+			[CONF_AP_BT_ACL_VAL_WL_SERVE_TIME] = 25,
 		},
 		.state = CONF_SG_PROTECTIVE,
 	},
 	.rx = {
 		.rx_msdu_life_time           = 512000,
 		.packet_detection_threshold  = 0,
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 21/40] wl12xx: fix session counter
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (19 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 20/40] wl12xx: update BT coex configuration params Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 22/40] wl12xx: use dynamic hlids for AP-mode Eliad Peller
                   ` (19 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Increment the session counter on every
wl12xx_cmd_role_start_sta() command.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: fix commit msg

 drivers/net/wireless/wl12xx/cmd.c  |   12 +++++++++++-
 drivers/net/wireless/wl12xx/main.c |    6 +-----
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index c620a9d..7c5d738 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -455,12 +455,22 @@ static void wl12xx_free_link(struct wl1271 *wl, u8 *hlid)
 		return;
 
 	__clear_bit(*hlid, wl->links_map);
 	*hlid = WL12XX_INVALID_LINK_ID;
 }
 
+static int wl12xx_get_new_session_id(struct wl1271 *wl)
+{
+	if (wl->session_counter >= SESSION_COUNTER_MAX)
+		wl->session_counter = 0;
+
+	wl->session_counter++;
+
+	return wl->session_counter;
+}
+
 int wl12xx_cmd_role_start_dev(struct wl1271 *wl)
 {
 	struct wl12xx_cmd_role_start *cmd;
 	int ret;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -577,13 +587,13 @@ int wl12xx_cmd_role_start_sta(struct wl1271 *wl)
 	if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
 		ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
 		if (ret)
 			goto out_free;
 	}
 	cmd->sta.hlid = wl->sta_hlid;
-	cmd->sta.session = wl->session_counter;
+	cmd->sta.session = wl12xx_get_new_session_id(wl);
 	cmd->sta.remote_rates = cpu_to_le32(wl->rate_set);
 
 	wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
 		     "basic_rate_set: 0x%x, remote_rates: 0x%x",
 		     wl->role_id, cmd->sta.hlid, cmd->sta.session,
 		     wl->basic_rate_set, wl->rate_set);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 1774a66..157c462 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2184,17 +2184,12 @@ static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
 			wl, CMD_TEMPL_KLV_IDX_NULL_DATA,
 			ACX_KEEP_ALIVE_TPL_INVALID);
 		if (ret < 0)
 			goto out;
 		set_bit(WL1271_FLAG_IDLE, &wl->flags);
 	} else {
-		/* increment the session counter */
-		wl->session_counter++;
-		if (wl->session_counter >= SESSION_COUNTER_MAX)
-			wl->session_counter = 0;
-
 		/* The current firmware only supports sched_scan in idle */
 		if (wl->sched_scanning) {
 			wl1271_scan_sched_scan_stop(wl);
 			ieee80211_sched_scan_stopped(wl->hw);
 		}
 
@@ -4450,12 +4445,13 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->tx_security_last_seq_lsb = 0;
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
 	wl->system_hlid = WL12XX_SYSTEM_HLID;
 	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
 	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
 	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+	wl->session_counter = 0;
 	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
 		    (unsigned long) wl);
 	wl->fwlog_size = 0;
 	init_waitqueue_head(&wl->fwlog_waitq);
 
 	/* The system link is always allocated */
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 22/40] wl12xx: use dynamic hlids for AP-mode
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (20 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 21/40] wl12xx: fix session counter Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 23/40] wl12xx: re-enable block ack session support Eliad Peller
                   ` (18 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Using hlid=0 in AP mode is a bug. Dynamically allocate HLIDs.

Set the "first sta hlid" as 3. This will have to be changed
when multiple vifs will be supported.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: remove whitespace

 drivers/net/wireless/wl12xx/cmd.c    |   27 +++++++++++++++++++++++----
 drivers/net/wireless/wl12xx/main.c   |    9 +++++++--
 drivers/net/wireless/wl12xx/tx.c     |   17 ++++++-----------
 drivers/net/wireless/wl12xx/wl12xx.h |   13 ++++++++++---
 4 files changed, 46 insertions(+), 20 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 7c5d738..025fb14 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -679,17 +679,25 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
+	ret = wl12xx_allocate_link(wl, &wl->ap_global_hlid);
+	if (ret < 0)
+		goto out_free;
+
+	ret = wl12xx_allocate_link(wl, &wl->ap_bcast_hlid);
+	if (ret < 0)
+		goto out_free_global;
+
 	cmd->role_id = wl->role_id;
 	cmd->ap.aging_period = cpu_to_le16(wl->conf.tx.ap_aging_period);
 	cmd->ap.bss_index = WL1271_AP_BSS_INDEX;
-	cmd->ap.global_hlid = WL1271_AP_GLOBAL_HLID;
-	cmd->ap.broadcast_hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->ap.global_hlid = wl->ap_global_hlid;
+	cmd->ap.broadcast_hlid = wl->ap_bcast_hlid;
 	cmd->ap.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
 	cmd->ap.beacon_interval = cpu_to_le16(wl->beacon_int);
 	cmd->ap.dtim_interval = bss_conf->dtim_period;
 	cmd->ap.beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
 	cmd->channel = wl->channel;
 	cmd->ap.ssid_len = wl->ssid_len;
@@ -710,15 +718,23 @@ int wl12xx_cmd_role_start_ap(struct wl1271 *wl)
 		break;
 	}
 
 	ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd role start ap");
-		goto out_free;
+		goto out_free_bcast;
 	}
 
+	goto out_free;
+
+out_free_bcast:
+	wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+
+out_free_global:
+	wl12xx_free_link(wl, &wl->ap_global_hlid);
+
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
@@ -741,12 +757,15 @@ int wl12xx_cmd_role_stop_ap(struct wl1271 *wl)
 	ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd role stop ap");
 		goto out_free;
 	}
 
+	wl12xx_free_link(wl, &wl->ap_bcast_hlid);
+	wl12xx_free_link(wl, &wl->ap_global_hlid);
+
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
@@ -1250,13 +1269,13 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 	u8 lid_type;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd)
 		return -ENOMEM;
 
-	if (hlid == WL1271_AP_BROADCAST_HLID) {
+	if (hlid == wl->ap_bcast_hlid) {
 		if (key_type == KEY_WEP)
 			lid_type = WEP_DEFAULT_LID_TYPE;
 		else
 			lid_type = BROADCAST_LID_TYPE;
 	} else {
 		lid_type = UNICAST_LID_TYPE;
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 157c462..ea150b5 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1969,14 +1969,17 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
 		if (ret < 0)
 			goto deinit;
 
 		wl1271_ps_elp_sleep(wl);
 	}
 deinit:
+	/* clear all hlids (except system_hlid) */
 	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
 	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
+	wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+	wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
 
 	/*
 	 * this must be before the cancel_work calls below, so that the work
 	 * functions don't perform further work.
 	 */
 	wl->state = WL1271_STATE_OFF;
@@ -2535,13 +2538,13 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
 		if (key->key_type == KEY_WEP)
 			wep_key_added = true;
 	}
 
 	if (wep_key_added) {
 		ret = wl12xx_cmd_set_default_wep_key(wl, wl->default_key,
-						     WL1271_AP_BROADCAST_HLID);
+						     wl->ap_bcast_hlid);
 		if (ret < 0)
 			goto out;
 	}
 
 out:
 	wl1271_free_ap_keys(wl);
@@ -2560,13 +2563,13 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		u8 hlid;
 
 		if (sta) {
 			wl_sta = (struct wl1271_station *)sta->drv_priv;
 			hlid = wl_sta->hlid;
 		} else {
-			hlid = WL1271_AP_BROADCAST_HLID;
+			hlid = wl->ap_bcast_hlid;
 		}
 
 		if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
 			/*
 			 * We do not support removing keys after AP shutdown.
 			 * Pretend we do to make mac80211 happy.
@@ -4446,12 +4449,14 @@ struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->role_id = WL12XX_INVALID_ROLE_ID;
 	wl->system_hlid = WL12XX_SYSTEM_HLID;
 	wl->sta_hlid = WL12XX_INVALID_LINK_ID;
 	wl->dev_role_id = WL12XX_INVALID_ROLE_ID;
 	wl->dev_hlid = WL12XX_INVALID_LINK_ID;
 	wl->session_counter = 0;
+	wl->ap_bcast_hlid = WL12XX_INVALID_LINK_ID;
+	wl->ap_global_hlid = WL12XX_INVALID_LINK_ID;
 	setup_timer(&wl->rx_streaming_timer, wl1271_rx_streaming_timer,
 		    (unsigned long) wl);
 	wl->fwlog_size = 0;
 	init_waitqueue_head(&wl->fwlog_waitq);
 
 	/* The system link is always allocated */
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 057db6f..1240f40 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -35,13 +35,13 @@ static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
 {
 	int ret;
 	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
 	if (is_ap)
 		ret = wl12xx_cmd_set_default_wep_key(wl, id,
-						     WL1271_AP_BROADCAST_HLID);
+						     wl->ap_bcast_hlid);
 	else
 		ret = wl12xx_cmd_set_default_wep_key(wl, id, wl->sta_hlid);
 
 	if (ret < 0)
 		return ret;
 
@@ -165,15 +165,15 @@ u8 wl12xx_tx_get_hlid_ap(struct wl1271 *wl, struct sk_buff *skb)
 
 		if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags))
 			return wl->system_hlid;
 
 		hdr = (struct ieee80211_hdr *)skb->data;
 		if (ieee80211_is_mgmt(hdr->frame_control))
-			return WL1271_AP_GLOBAL_HLID;
+			return wl->ap_global_hlid;
 		else
-			return WL1271_AP_BROADCAST_HLID;
+			return wl->ap_bcast_hlid;
 	}
 }
 
 static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
 {
 	if (wl12xx_is_dummy_packet(wl, skb))
@@ -314,23 +314,18 @@ static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
 		   basic rates */
 		if (control->control.sta)
 			rate_idx = ACX_TX_AP_FULL_RATE;
 		else
 			rate_idx = ACX_TX_BASIC_RATE;
 	} else {
-		switch (hlid) {
-		case WL1271_AP_GLOBAL_HLID:
+		if (hlid == wl->ap_global_hlid)
 			rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
-			break;
-		case WL1271_AP_BROADCAST_HLID:
+		else if (hlid == wl->ap_bcast_hlid)
 			rate_idx = ACX_TX_AP_MODE_BCST_RATE;
-			break;
-		default:
+		else
 			rate_idx = ac;
-			break;
-		}
 	}
 
 	tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
 	desc->reserved = 0;
 
 	aligned_len = wl12xx_calc_packet_alignment(wl, skb->len);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index a136795..1313dc5 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -138,16 +138,21 @@ extern u32 wl12xx_debug_level;
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
 #define WL12XX_MAX_ROLES           4
 #define WL12XX_MAX_LINKS           8
 #define WL12XX_INVALID_ROLE_ID     0xff
 #define WL12XX_INVALID_LINK_ID     0xff
+
+/* Defined by FW as 0. Will not be freed or allocated. */
 #define WL12XX_SYSTEM_HLID         0
-#define WL1271_AP_GLOBAL_HLID      0
-#define WL1271_AP_BROADCAST_HLID   1
-#define WL1271_AP_STA_HLID_START   2
+
+/*
+ * TODO: we currently don't support multirole. remove
+ * this constant from the code when we do.
+ */
+#define WL1271_AP_STA_HLID_START   3
 
 /*
  * When in AP-mode, we allow (at least) this number of mem-blocks
  * to be transmitted to FW for a STA in PS-mode. Only when packets are
  * present in the FW buffers it will wake the sleeping STA. We want to put
  * enough packets for the driver to transmit all of its buffered data before
@@ -395,12 +400,14 @@ struct wl1271 {
 	int channel;
 	u8 role_id;
 	u8 dev_role_id;
 	u8 system_hlid;
 	u8 sta_hlid;
 	u8 dev_hlid;
+	u8 ap_global_hlid;
+	u8 ap_bcast_hlid;
 
 	unsigned long links_map[BITS_TO_LONGS(WL12XX_MAX_LINKS)];
 	unsigned long roles_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 	unsigned long roc_map[BITS_TO_LONGS(WL12XX_MAX_ROLES)];
 
 	struct wl1271_acx_mem_map *target_mem_map;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 23/40] wl12xx: re-enable block ack session support
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (21 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 22/40] wl12xx: use dynamic hlids for AP-mode Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 24/40] wl12xx: call wl12xx_cmd_set_peer_state() in AP mode Eliad Peller
                   ` (17 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Incorporate interface changes for HT support.

Add ba_bitmap field to the wl1271_link struct, to indicate
activate RX BA sessions (for AP mode).

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: fix typos, use conf struct

 drivers/net/wireless/wl12xx/acx.c    |   66 +++++----------
 drivers/net/wireless/wl12xx/acx.h    |   82 ++++++-------------
 drivers/net/wireless/wl12xx/cmd.h    |    1 +
 drivers/net/wireless/wl12xx/conf.h   |    9 ++-
 drivers/net/wireless/wl12xx/init.c   |   37 +++------
 drivers/net/wireless/wl12xx/main.c   |  148 ++++++++++++++++++++++++----------
 drivers/net/wireless/wl12xx/wl12xx.h |    6 ++
 7 files changed, 178 insertions(+), 171 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index d783fce..ecbceb6 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1320,25 +1320,21 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	/* Allow HT Operation ? */
 	if (allow_ht_operation) {
-		ht_capabilites =
-			WL1271_ACX_FW_CAP_HT_OPERATION;
-		if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
-			ht_capabilites |=
-				WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
-		if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
-			ht_capabilites |=
-				WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
-		if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
-			ht_capabilites |=
-				WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
+		/* no need to translate capabilities - use the spec values */
+		ht_capabilites = ht_cap->cap;
+
+		/*
+		 * this bit is not employed by the spec but only by FW to
+		 * indicate peer HT support
+		 */
+		ht_capabilites |= WL12XX_HT_CAP_HT_OPERATION;
 
 		/* get data from A-MPDU parameters field */
 		acx->ampdu_max_length = ht_cap->ampdu_factor;
 		acx->ampdu_min_spacing = ht_cap->ampdu_density;
 	}
 
@@ -1389,82 +1385,64 @@ int wl1271_acx_set_ht_information(struct wl1271 *wl,
 out:
 	kfree(acx);
 	return ret;
 }
 
 /* Configure BA session initiator/receiver parameters setting in the FW. */
-int wl1271_acx_set_ba_session(struct wl1271 *wl,
-			       enum ieee80211_back_parties direction,
-			       u8 tid_index, u8 policy)
+int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl)
 {
-	struct wl1271_acx_ba_session_policy *acx;
+	struct wl1271_acx_ba_initiator_policy *acx;
 	int ret;
 
-	wl1271_debug(DEBUG_ACX, "acx ba session setting");
+	wl1271_debug(DEBUG_ACX, "acx ba initiator policy");
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	/* ANY role */
-	acx->role_id = 0xff;
-	acx->tid = tid_index;
-	acx->enable = policy;
-	acx->ba_direction = direction;
-
-	switch (direction) {
-	case WLAN_BACK_INITIATOR:
-		acx->win_size = wl->conf.ht.tx_ba_win_size;
-		acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
-		break;
-	case WLAN_BACK_RECIPIENT:
-		acx->win_size = RX_BA_WIN_SIZE;
-		acx->inactivity_timeout = 0;
-		break;
-	default:
-		wl1271_error("Incorrect acx command id=%x\n", direction);
-		ret = -EINVAL;
-		goto out;
-	}
+	/* set for the current role */
+	acx->role_id = wl->role_id;
+	acx->tid_bitmap = wl->conf.ht.tx_ba_tid_bitmap;
+	acx->win_size = wl->conf.ht.tx_ba_win_size;
+	acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
 
 	ret = wl1271_cmd_configure(wl,
-				   ACX_BA_SESSION_POLICY_CFG,
+				   ACX_BA_SESSION_INIT_POLICY,
 				   acx,
 				   sizeof(*acx));
 	if (ret < 0) {
-		wl1271_warning("acx ba session setting failed: %d", ret);
+		wl1271_warning("acx ba initiator policy failed: %d", ret);
 		goto out;
 	}
 
 out:
 	kfree(acx);
 	return ret;
 }
 
 /* setup BA session receiver setting in the FW. */
-int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
-					bool enable)
+int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
+				       u16 ssn, bool enable, u8 peer_hlid)
 {
 	struct wl1271_acx_ba_receiver_setup *acx;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "acx ba receiver session setting");
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	/* Single link for now */
-	acx->link_id = 1;
+	acx->hlid = peer_hlid;
 	acx->tid = tid_index;
 	acx->enable = enable;
-	acx->win_size = 0;
+	acx->win_size = wl->conf.ht.rx_ba_win_size;
 	acx->ssn = ssn;
 
 	ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
 				   sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx ba receiver session failed: %d", ret);
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 5b3fabd..82c9271 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -896,33 +896,25 @@ struct wl1271_acx_rssi_snr_avg_weights {
 	u8 rssi_beacon;
 	u8 rssi_data;
 	u8 snr_beacon;
 	u8 snr_data;
 };
 
+
+/* special capability bit (not employed by the 802.11n spec) */
+#define WL12XX_HT_CAP_HT_OPERATION BIT(16)
+
 /*
  * ACX_PEER_HT_CAP
  * Configure HT capabilities - declare the capabilities of the peer
  * we are connected to.
  */
 struct wl1271_acx_ht_capabilities {
 	struct acx_header header;
 
-	/*
-	 * bit 0 - Allow HT Operation
-	 * bit 1 - Allow Greenfield format in TX
-	 * bit 2 - Allow Short GI in TX
-	 * bit 3 - Allow L-SIG TXOP Protection in TX
-	 * bit 4 - Allow HT Control fields in TX.
-	 *         Note, driver will still leave space for HT control in packets
-	 *         regardless of the value of this field. FW will be responsible
-	 *         to drop the HT field from any frame when this Bit set to 0.
-	 * bit 5 - Allow RD initiation in TXOP. FW is allowed to initate RD.
-	 *         Exact policy setting for this feature is TBD.
-	 *         Note, this bit can only be set to 1 if bit 3 is set to 1.
-	 */
+	/* bitmask of capability bits supported by the peer */
 	__le32 ht_capabilites;
 
 	/* Indicates to which link these capabilities apply. */
 	u8 hlid;
 
 	/*
@@ -934,21 +926,12 @@ struct wl1271_acx_ht_capabilities {
 	/* This is the minimal spacing required when sending A-MPDUs to the AP*/
 	u8 ampdu_min_spacing;
 
 	u8 padding;
 } __packed;
 
-/* HT Capabilites Fw Bit Mask Mapping */
-#define WL1271_ACX_FW_CAP_HT_OPERATION                 BIT(0)
-#define WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT      BIT(1)
-#define WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS   BIT(2)
-#define WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION         BIT(3)
-#define WL1271_ACX_FW_CAP_HT_CONTROL_FIELDS            BIT(4)
-#define WL1271_ACX_FW_CAP_RD_INITIATION                BIT(5)
-
-
 /*
  * ACX_HT_BSS_OPERATION
  * Configure HT capabilities - AP rules for behavior in the BSS.
  */
 struct wl1271_acx_ht_information {
 	struct acx_header header;
@@ -976,63 +959,54 @@ struct wl1271_acx_ht_information {
 	 */
 	u8 dual_cts_protection;
 
 	u8 padding[2];
 } __packed;
 
-#define RX_BA_WIN_SIZE 8
+#define RX_BA_MAX_SESSIONS 2
 
-struct wl1271_acx_ba_session_policy {
+struct wl1271_acx_ba_initiator_policy {
 	struct acx_header header;
-	/*
-	 * Specifies role Id, Range 0-7, 0xFF means ANY role.
-	 * Future use. For now this field is irrelevant
-	 */
+
+	/* Specifies role Id, Range 0-7, 0xFF means ANY role. */
 	u8 role_id;
+
 	/*
-	 * Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id.
-	 * Not applicable if Role Id is set to ANY.
+	 * Per TID setting for allowing TX BA. Set a bit to 1 to allow
+	 * TX BA sessions for the corresponding TID.
 	 */
-	u8 link_id;
-
-	u8 tid;
-
-	u8 enable;
+	u8 tid_bitmap;
 
 	/* Windows size in number of packets */
-	u16 win_size;
+	u8 win_size;
 
-	/*
-	 * As initiator inactivity timeout in time units(TU) of 1024us.
-	 * As receiver reserved
-	 */
-	u16 inactivity_timeout;
+	u8 padding1[1];
 
-	/* Initiator = 1/Receiver = 0 */
-	u8 ba_direction;
+	/* As initiator inactivity timeout in time units(TU) of 1024us */
+	u16 inactivity_timeout;
 
-	u8 padding[3];
+	u8 padding[2];
 } __packed;
 
 struct wl1271_acx_ba_receiver_setup {
 	struct acx_header header;
 
-	/* Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id */
-	u8 link_id;
+	/* Specifies link id, range 0-31 */
+	u8 hlid;
 
 	u8 tid;
 
 	u8 enable;
 
-	u8 padding[1];
-
 	/* Windows size in number of packets */
-	u16 win_size;
+	u8 win_size;
 
 	/* BA session starting sequence number.  RANGE 0-FFF */
 	u16 ssn;
+
+	u8 padding[2];
 } __packed;
 
 struct wl1271_acx_fw_tsf_information {
 	struct acx_header header;
 
 	__le32 current_tsf_high;
@@ -1215,13 +1189,13 @@ enum {
 	ACX_FRAG_CFG                = 0x004F,
 	ACX_BET_ENABLE              = 0x0050,
 	ACX_RSSI_SNR_TRIGGER        = 0x0051,
 	ACX_RSSI_SNR_WEIGHTS        = 0x0052,
 	ACX_KEEP_ALIVE_MODE         = 0x0053,
 	ACX_SET_KEEP_ALIVE_CONFIG   = 0x0054,
-	ACX_BA_SESSION_POLICY_CFG   = 0x0055,
+	ACX_BA_SESSION_INIT_POLICY  = 0x0055,
 	ACX_BA_SESSION_RX_SETUP     = 0x0056,
 	ACX_PEER_HT_CAP             = 0x0057,
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
 	ACX_BURST_MODE              = 0x005C,
 	ACX_SET_RATE_MGMT_PARAMS    = 0x005D,
@@ -1294,17 +1268,15 @@ int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
 int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl);
 int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 				    struct ieee80211_sta_ht_cap *ht_cap,
 				    bool allow_ht_operation);
 int wl1271_acx_set_ht_information(struct wl1271 *wl,
 				   u16 ht_operation_mode);
-int wl1271_acx_set_ba_session(struct wl1271 *wl,
-			      enum ieee80211_back_parties direction,
-			      u8 tid_index, u8 policy);
-int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
-				       bool enable);
+int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl);
+int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
+				       u16 ssn, bool enable, u8 peer_hlid);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
 int wl1271_acx_ps_rx_streaming(struct wl1271 *wl, bool enable);
 int wl1271_acx_ap_max_tx_retry(struct wl1271 *wl);
 int wl1271_acx_config_ps(struct wl1271 *wl);
 int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 int wl1271_acx_fm_coex(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 5cf92e2..8b32a57 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -205,12 +205,13 @@ enum {
 	CMD_STATUS_STA_TABLE_FULL		= 17,
 	CMD_STATUS_RADIO_ERROR		= 18,
 	CMD_STATUS_WRONG_NESTING		= 19,
 	CMD_STATUS_TIMEOUT		= 21, /* Driver internal use.*/
 	CMD_STATUS_FW_RESET		= 22, /* Driver internal use.*/
 	CMD_STATUS_TEMPLATE_OOM		= 23,
+	CMD_STATUS_NO_RX_BA_SESSION	= 24,
 	MAX_COMMAND_STATUS		= 0xff
 };
 
 #define CMDMBOX_HEADER_LEN 4
 #define CMDMBOX_INFO_ELEM_HEADER_LEN 4
 
diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index a7c1478..76b5c62 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -554,12 +554,15 @@ struct conf_tx_ac_category {
 	 */
 	u16 tx_op_limit;
 };
 
 #define CONF_TX_MAX_TID_COUNT 8
 
+/* Allow TX BA on all TIDs but 6,7. These are currently reserved in the FW */
+#define CONF_TX_BA_ENABLED_TID_BITMAP 0x3F
+
 enum {
 	CONF_CHANNEL_TYPE_DCF = 0,   /* DC/LEGACY*/
 	CONF_CHANNEL_TYPE_EDCF = 1,  /* EDCA*/
 	CONF_CHANNEL_TYPE_HCCA = 2,  /* HCCA*/
 };
 
@@ -1092,14 +1095,18 @@ struct conf_rf_settings {
 	 * Range: s8
 	 */
 	u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
 };
 
 struct conf_ht_setting {
-	u16 tx_ba_win_size;
+	u8 rx_ba_win_size;
+	u8 tx_ba_win_size;
 	u16 inactivity_timeout;
+
+	/* bitmap of enabled TIDs for TX BA sessions */
+	u8 tx_ba_tid_bitmap;
 };
 
 struct conf_memory_settings {
 	/* Number of stations supported in IBSS mode */
 	u8 num_stations;
 
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index 47d87aa..a374c21 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -526,47 +526,30 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
 			return ret;
 	}
 
 	return 0;
 }
 
-static void wl1271_check_ba_support(struct wl1271 *wl)
-{
-	/* validate FW cose ver x.x.x.50-60.x */
-	if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
-	    (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
-		wl->ba_support = true;
-		return;
-	}
-
-	wl->ba_support = false;
-}
-
 static int wl1271_set_ba_policies(struct wl1271 *wl)
 {
-	u8 tid_index;
-	int ret = 0;
-
 	/* Reset the BA RX indicators */
 	wl->ba_rx_bitmap = 0;
 	wl->ba_allowed = true;
+	wl->ba_rx_session_count = 0;
 
-	/* validate that FW support BA */
-	wl1271_check_ba_support(wl);
+	/* BA is supported in STA/AP modes */
+	if (wl->bss_type != BSS_TYPE_AP_BSS &&
+	    wl->bss_type != BSS_TYPE_STA_BSS) {
+		wl->ba_support = false;
+		return 0;
+	}
 
-	if (wl->ba_support)
-		/* 802.11n initiator BA session setting */
-		for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
-		     ++tid_index) {
-			ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
-							tid_index, true);
-			if (ret < 0)
-				break;
-		}
+	wl->ba_support = true;
 
-	return ret;
+	/* 802.11n initiator BA session setting */
+	return wl12xx_acx_set_ba_initiator_policy(wl);
 }
 
 int wl1271_chip_specific_init(struct wl1271 *wl)
 {
 	int ret = 0;
 
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index ea150b5..bf9b27d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -283,14 +283,16 @@ static struct conf_drv_settings default_conf = {
 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		},
 	},
 	.ht = {
-		.tx_ba_win_size = 64,
+		.rx_ba_win_size = 8,
+		.tx_ba_win_size = 8,
 		.inactivity_timeout = 10000,
+		.tx_ba_tid_bitmap = CONF_TX_BA_ENABLED_TID_BITMAP,
 	},
 	.mem_wl127x = {
 		.num_stations                 = 1,
 		.ssid_profiles                = 1,
 		.rx_block_num                 = 70,
 		.tx_min_block_num             = 40,
@@ -3188,54 +3190,28 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 
 			/* Need to update the BSSID (for filtering etc) */
 			do_join = true;
 		}
 	}
 
-	rcu_read_lock();
-	sta = ieee80211_find_sta(vif, bss_conf->bssid);
-	if (sta)  {
+	if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_HT)) {
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (!sta)
+			goto sta_not_found;
+
 		/* save the supp_rates of the ap */
 		sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
 		if (sta->ht_cap.ht_supported)
 			sta_rate_set |=
 			    (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
 		sta_ht_cap = sta->ht_cap;
 		sta_exists = true;
-	}
-	rcu_read_unlock();
 
-	if (sta_exists) {
-		/* handle new association with HT and HT information change */
-		if ((changed & BSS_CHANGED_HT) &&
-		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
-			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
-							     true);
-			if (ret < 0) {
-				wl1271_warning("Set ht cap true failed %d",
-					       ret);
-				goto out;
-			}
-			ret = wl1271_acx_set_ht_information(wl,
-						bss_conf->ht_operation_mode);
-			if (ret < 0) {
-				wl1271_warning("Set ht information failed %d",
-					       ret);
-				goto out;
-			}
-		}
-		/* handle new association without HT and disassociation */
-		else if (changed & BSS_CHANGED_ASSOC) {
-			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
-							     false);
-			if (ret < 0) {
-				wl1271_warning("Set ht cap false failed %d",
-					       ret);
-				goto out;
-			}
-		}
+sta_not_found:
+		rcu_read_unlock();
 	}
 
 	if ((changed & BSS_CHANGED_ASSOC)) {
 		if (bss_conf->assoc) {
 			u32 rates;
 			int ieoffset;
@@ -3437,12 +3413,47 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 			ret = wl12xx_cmd_role_stop_dev(wl);
 			if (ret < 0)
 				goto out;
 		}
 	}
 
+	/* Handle new association with HT. Do this only after join. */
+	if (sta_exists) {
+		if ((changed & BSS_CHANGED_HT) &&
+		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
+							     true);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap true failed %d",
+					       ret);
+				goto out;
+			}
+		}
+		/* handle new association without HT and disassociation */
+		else if (changed & BSS_CHANGED_ASSOC) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
+							     false);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap false failed %d",
+					       ret);
+				goto out;
+			}
+		}
+	}
+
+	/* Handle HT information change. Only after join. */
+	if (sta_exists && (changed & BSS_CHANGED_HT) &&
+	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+		ret = wl1271_acx_set_ht_information(wl,
+					bss_conf->ht_operation_mode);
+		if (ret < 0) {
+			wl1271_warning("Set ht information failed %d", ret);
+			goto out;
+		}
+	}
+
 out:
 	return;
 }
 
 static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
@@ -3620,12 +3631,13 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
 
 	if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
 		return;
 
 	__clear_bit(id, wl->ap_hlid_map);
 	memset(wl->links[hlid].addr, 0, ETH_ALEN);
+	wl->links[hlid].ba_bitmap = 0;
 	wl1271_tx_reset_link_queues(wl, hlid);
 	__clear_bit(hlid, &wl->ap_ps_map);
 	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 }
 
 bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
@@ -3722,43 +3734,91 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
 				  enum ieee80211_ampdu_mlme_action action,
 				  struct ieee80211_sta *sta, u16 tid, u16 *ssn,
 				  u8 buf_size)
 {
 	struct wl1271 *wl = hw->priv;
 	int ret;
+	u8 hlid, *ba_bitmap;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu action %d tid %d", action,
+		     tid);
+
+	/* sanity check - the fields in FW are only 8bits wide */
+	if (WARN_ON(tid > 0xFF))
+		return -ENOTSUPP;
 
 	mutex_lock(&wl->mutex);
 
 	if (unlikely(wl->state == WL1271_STATE_OFF)) {
 		ret = -EAGAIN;
 		goto out;
 	}
 
+	if (wl->bss_type == BSS_TYPE_STA_BSS) {
+		hlid = wl->sta_hlid;
+		ba_bitmap = &wl->ba_rx_bitmap;
+	} else if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		struct wl1271_station *wl_sta;
+
+		wl_sta = (struct wl1271_station *)sta->drv_priv;
+		hlid = wl_sta->hlid;
+		ba_bitmap = &wl->links[hlid].ba_bitmap;
+	} else {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 ampdu: Rx tid %d action %d",
 		     tid, action);
 
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
-		if ((wl->ba_support) && (wl->ba_allowed)) {
-			ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
-								 true);
-			if (!ret)
-				wl->ba_rx_bitmap |= BIT(tid);
-		} else {
+		if (!wl->ba_support || !wl->ba_allowed) {
 			ret = -ENOTSUPP;
+			break;
+		}
+
+		if (wl->ba_rx_session_count >= RX_BA_MAX_SESSIONS) {
+			ret = -EBUSY;
+			wl1271_error("exceeded max RX BA sessions");
+			break;
+		}
+
+		if (*ba_bitmap & BIT(tid)) {
+			ret = -EINVAL;
+			wl1271_error("cannot enable RX BA session on active "
+				     "tid: %d", tid);
+			break;
+		}
+
+		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, *ssn, true,
+							 hlid);
+		if (!ret) {
+			*ba_bitmap |= BIT(tid);
+			wl->ba_rx_session_count++;
 		}
 		break;
 
 	case IEEE80211_AMPDU_RX_STOP:
-		ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
-		if (!ret)
-			wl->ba_rx_bitmap &= ~BIT(tid);
+		if (!(*ba_bitmap & BIT(tid))) {
+			ret = -EINVAL;
+			wl1271_error("no active RX BA session on tid: %d",
+				     tid);
+			break;
+		}
+
+		ret = wl12xx_acx_set_ba_receiver_session(wl, tid, 0, false,
+							 hlid);
+		if (!ret) {
+			*ba_bitmap &= ~BIT(tid);
+			wl->ba_rx_session_count--;
+		}
 		break;
 
 	/*
 	 * The BA initiator session management in FW independently.
 	 * Falling break here on purpose for all TX APDU commands.
 	 */
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 1313dc5..487c3c7 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -352,12 +352,15 @@ struct wl1271_link {
 
 	/* accounting for allocated / available TX blocks in FW */
 	u8 allocated_blks;
 	u8 prev_freed_blks;
 
 	u8 addr[ETH_ALEN];
+
+	/* bitmap of TIDs where RX BA sessions are active for this link */
+	u8 ba_bitmap;
 };
 
 struct wl1271 {
 	struct platform_device *plat_dev;
 	struct ieee80211_hw *hw;
 	bool mac80211_registered;
@@ -606,12 +609,15 @@ struct wl1271 {
 
 	/* Quirks of specific hardware revisions */
 	unsigned int quirks;
 
 	/* Platform limitations */
 	unsigned int platform_quirks;
+
+	/* number of currently active RX BA sessions */
+	int ba_rx_session_count;
 };
 
 struct wl1271_station {
 	u8 hlid;
 };
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 24/40] wl12xx: call wl12xx_cmd_set_peer_state() in AP mode
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (22 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 23/40] wl12xx: re-enable block ack session support Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 25/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
                   ` (16 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

After adding a station, call wl12xx_cmd_set_peer_state().
This is required for 11n support.

Change wl12xx_cmd_set_peer_state() prototype to get hlid
as param.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/cmd.c  |    6 +++---
 drivers/net/wireless/wl12xx/cmd.h  |    2 +-
 drivers/net/wireless/wl12xx/main.c |    6 +++++-
 3 files changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 025fb14..d655e62 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1318,26 +1318,26 @@ int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 
 out:
 	kfree(cmd);
 	return ret;
 }
 
-int wl12xx_cmd_set_peer_state(struct wl1271 *wl)
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
 {
 	struct wl12xx_cmd_set_peer_state *cmd;
 	int ret = 0;
 
-	wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", wl->sta_hlid);
+	wl1271_debug(DEBUG_CMD, "cmd set peer state (hlid=%d)", hlid);
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	cmd->hlid = wl->sta_hlid;
+	cmd->hlid = hlid;
 	cmd->state = WL1271_CMD_STA_STATE_CONNECTED;
 
 	ret = wl1271_cmd_send(wl, CMD_SET_PEER_STATE, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
 		wl1271_error("failed to send set peer state command");
 		goto out_free;
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 8b32a57..740d27e 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -67,13 +67,13 @@ int wl12xx_cmd_set_default_wep_key(struct wl1271 *wl, u8 id, u8 hlid);
 int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			   u8 key_size, const u8 *key, const u8 *addr,
 			   u32 tx_seq_32, u16 tx_seq_16);
 int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 			  u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
 			  u16 tx_seq_16);
-int wl12xx_cmd_set_peer_state(struct wl1271 *wl);
+int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid);
 int wl12xx_roc(struct wl1271 *wl, u8 role_id);
 int wl12xx_croc(struct wl1271 *wl, u8 role_id);
 int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
 int wl12xx_cmd_remove_peer(struct wl1271 *wl, u8 hlid);
 int wl12xx_cmd_config_fwlog(struct wl1271 *wl);
 int wl12xx_cmd_start_fwlog(struct wl1271 *wl);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index bf9b27d..9b0df66 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -392,13 +392,13 @@ static int wl1271_check_operstate(struct wl1271 *wl, unsigned char operstate)
 	if (operstate != IF_OPER_UP)
 		return 0;
 
 	if (test_and_set_bit(WL1271_FLAG_STA_STATE_SENT, &wl->flags))
 		return 0;
 
-	ret = wl12xx_cmd_set_peer_state(wl);
+	ret = wl12xx_cmd_set_peer_state(wl, wl->sta_hlid);
 	if (ret < 0)
 		return ret;
 
 	wl12xx_croc(wl, wl->role_id);
 
 	wl1271_info("Association completed.");
@@ -3673,12 +3673,16 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
 		goto out_free_sta;
 
 	ret = wl12xx_cmd_add_peer(wl, sta, hlid);
 	if (ret < 0)
 		goto out_sleep;
 
+	ret = wl12xx_cmd_set_peer_state(wl, hlid);
+	if (ret < 0)
+		goto out_sleep;
+
 out_sleep:
 	wl1271_ps_elp_sleep(wl);
 
 out_free_sta:
 	if (ret < 0)
 		wl1271_free_sta(wl, hlid);
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 25/40] wl12xx: don't remove key if hlid was already deleted
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (23 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 24/40] wl12xx: call wl12xx_cmd_set_peer_state() in AP mode Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 26/40] wl12xx: add wl12xx_cmd_role_start_ibss() Eliad Peller
                   ` (15 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

If hlid was already removed, there is no need to remove
its key (it might cause a fw crash, as the key is invalid).

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/cmd.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index d655e62..261807b 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1200,12 +1200,16 @@ int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		       u8 key_size, const u8 *key, const u8 *addr,
 		       u32 tx_seq_32, u16 tx_seq_16)
 {
 	struct wl1271_cmd_set_keys *cmd;
 	int ret = 0;
 
+	/* hlid might have already been deleted */
+	if (wl->sta_hlid == WL12XX_INVALID_LINK_ID)
+		return 0;
+
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 26/40] wl12xx: add wl12xx_cmd_role_start_ibss()
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (24 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 25/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 27/40] wl12xx: support IBSS vif type Eliad Peller
                   ` (14 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Add wl12xx_cmd_role_start_ibss() implementation and defintion.
This function is used in order to start the IBSS role.

Stopping the IBSS is done by using the same api as stop STA,
so there is no need for a separate function.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: set cmd->band instead of bitwise-OR-ing it.

 drivers/net/wireless/wl12xx/cmd.c |   62 +++++++++++++++++++++++++++++++++++++
 drivers/net/wireless/wl12xx/cmd.h |    1 +
 2 files changed, 63 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index 261807b..d8c3916 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -614,12 +614,13 @@ out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
 
+/* use this function to stop ibss as well */
 int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
 {
 	struct wl12xx_cmd_role_stop *cmd;
 	int ret;
 
 	if (WARN_ON(wl->sta_hlid == WL12XX_INVALID_LINK_ID))
@@ -767,12 +768,73 @@ out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
 
+int wl12xx_cmd_role_start_ibss(struct wl1271 *wl)
+{
+	struct wl12xx_cmd_role_start *cmd;
+	struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+	int ret;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	wl1271_debug(DEBUG_CMD, "cmd role start ibss %d", wl->role_id);
+
+	cmd->role_id = wl->role_id;
+	if (wl->band == IEEE80211_BAND_5GHZ)
+		cmd->band = WL12XX_BAND_5GHZ;
+	cmd->channel = wl->channel;
+	cmd->ibss.basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	cmd->ibss.beacon_interval = cpu_to_le16(wl->beacon_int);
+	cmd->ibss.dtim_interval = bss_conf->dtim_period;
+	cmd->ibss.ssid_type = WL12XX_SSID_TYPE_ANY;
+	cmd->ibss.ssid_len = wl->ssid_len;
+	memcpy(cmd->ibss.ssid, wl->ssid, wl->ssid_len);
+	memcpy(cmd->ibss.bssid, wl->bssid, ETH_ALEN);
+	cmd->sta.local_rates = cpu_to_le32(wl->rate_set);
+
+	if (wl->sta_hlid == WL12XX_INVALID_LINK_ID) {
+		ret = wl12xx_allocate_link(wl, &wl->sta_hlid);
+		if (ret)
+			goto out_free;
+	}
+	cmd->ibss.hlid = wl->sta_hlid;
+	cmd->ibss.remote_rates = cpu_to_le32(wl->rate_set);
+
+	wl1271_debug(DEBUG_CMD, "role start: roleid=%d, hlid=%d, session=%d "
+		     "basic_rate_set: 0x%x, remote_rates: 0x%x",
+		     wl->role_id, cmd->sta.hlid, cmd->sta.session,
+		     wl->basic_rate_set, wl->rate_set);
+
+	wl1271_debug(DEBUG_CMD, "wl->bssid = %pM", wl->bssid);
+
+	ret = wl1271_cmd_send(wl, CMD_ROLE_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd role enable");
+		goto err_hlid;
+	}
+
+	goto out_free;
+
+err_hlid:
+	/* clear links on error. */
+	wl12xx_free_link(wl, &wl->sta_hlid);
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
 
 /**
  * send test command to firmware
  *
  * @wl: wl struct
  * @buf: buffer containing the command, with all headers, must work with dma
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 740d27e..22c2f37 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -41,12 +41,13 @@ int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id);
 int wl12xx_cmd_role_start_dev(struct wl1271 *wl);
 int wl12xx_cmd_role_stop_dev(struct wl1271 *wl);
 int wl12xx_cmd_role_start_sta(struct wl1271 *wl);
 int wl12xx_cmd_role_stop_sta(struct wl1271 *wl);
 int wl12xx_cmd_role_start_ap(struct wl1271 *wl);
 int wl12xx_cmd_role_stop_ap(struct wl1271 *wl);
+int wl12xx_cmd_role_start_ibss(struct wl1271 *wl);
 int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
 int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 27/40] wl12xx: support IBSS vif type
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (25 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 26/40] wl12xx: add wl12xx_cmd_role_start_ibss() Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 28/40] wl12xx: AP-mode - set STA HT capabilities when adding a STA Eliad Peller
                   ` (13 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Start IBSS role when the interface type is IBSS.
As with sta role, use the dev role until the role
is started.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c   |   33 ++++++++++++++++++++++++++++-----
 drivers/net/wireless/wl12xx/scan.c   |    9 ++++++++-
 drivers/net/wireless/wl12xx/tx.c     |    3 ++-
 drivers/net/wireless/wl12xx/wl12xx.h |    1 +
 4 files changed, 39 insertions(+), 7 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 9b0df66..de4b6c2 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1767,12 +1767,15 @@ static u8 wl12xx_get_role_type(struct wl1271 *wl)
 	case BSS_TYPE_AP_BSS:
 		return WL1271_ROLE_AP;
 
 	case BSS_TYPE_STA_BSS:
 		return WL1271_ROLE_STA;
 
+	case BSS_TYPE_IBSS:
+		return WL1271_ROLE_IBSS;
+
 	default:
 		wl1271_error("invalid bss_type: %d", wl->bss_type);
 	}
 	return WL12XX_INVALID_ROLE_TYPE;
 }
 
@@ -1845,13 +1848,14 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
 			goto power_off;
 
 		ret = wl1271_boot(wl);
 		if (ret < 0)
 			goto power_off;
 
-		if (wl->bss_type == BSS_TYPE_STA_BSS) {
+		if (wl->bss_type == BSS_TYPE_STA_BSS ||
+		    wl->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)
 			 */
@@ -2075,12 +2079,13 @@ static void wl1271_op_remove_interface(struct ieee80211_hw *hw,
 	cancel_work_sync(&wl->recovery_work);
 }
 
 static int wl1271_join(struct wl1271 *wl, bool set_assoc)
 {
 	int ret;
+	bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
 
 	/*
 	 * One of the side effects of the JOIN command is that is clears
 	 * WPA/WPA2 keys from the chipset. Performing a JOIN while associated
 	 * to a WPA/WPA2 access point will therefore kill the data-path.
 	 * Currently the only valid scenario for JOIN during association
@@ -2091,13 +2096,16 @@ static int wl1271_join(struct wl1271 *wl, bool set_assoc)
 	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		wl1271_info("JOIN while associated.");
 
 	if (set_assoc)
 		set_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags);
 
-	ret = wl12xx_cmd_role_start_sta(wl);
+	if (is_ibss)
+		ret = wl12xx_cmd_role_start_ibss(wl);
+	else
+		ret = wl12xx_cmd_role_start_sta(wl);
 	if (ret < 0)
 		goto out;
 
 	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		goto out;
 
@@ -3125,12 +3133,13 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 					struct ieee80211_vif *vif,
 					struct ieee80211_bss_conf *bss_conf,
 					u32 changed)
 {
 	bool do_join = false, set_assoc = false;
 	bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+	bool ibss_joined = false;
 	u32 sta_rate_set = 0;
 	int ret;
 	struct ieee80211_sta *sta;
 	bool sta_exists = false;
 	struct ieee80211_sta_ht_cap sta_ht_cap;
 
@@ -3138,20 +3147,34 @@ static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
 		ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf,
 						     changed);
 		if (ret < 0)
 			goto out;
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_INT)  && is_ibss)
+	if (changed & BSS_CHANGED_IBSS) {
+		if (bss_conf->ibss_joined) {
+			set_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags);
+			ibss_joined = true;
+		} else {
+			if (test_and_clear_bit(WL1271_FLAG_IBSS_JOINED,
+					       &wl->flags)) {
+				wl1271_unjoin(wl);
+				wl12xx_cmd_role_start_dev(wl);
+				wl12xx_roc(wl, wl->dev_role_id);
+			}
+		}
+	}
+
+	if ((changed & BSS_CHANGED_BEACON_INT) && ibss_joined)
 		do_join = true;
 
 	/* Need to update the SSID (for filtering etc) */
-	if ((changed & BSS_CHANGED_BEACON) && is_ibss)
+	if ((changed & BSS_CHANGED_BEACON) && ibss_joined)
 		do_join = true;
 
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) {
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && ibss_joined) {
 		wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s",
 			     bss_conf->enable_beacon ? "enabled" : "disabled");
 
 		if (bss_conf->enable_beacon)
 			wl->set_bss_type = BSS_TYPE_IBSS;
 		else
diff --git a/drivers/net/wireless/wl12xx/scan.c b/drivers/net/wireless/wl12xx/scan.c
index 653091a..7229eaa 100644
--- a/drivers/net/wireless/wl12xx/scan.c
+++ b/drivers/net/wireless/wl12xx/scan.c
@@ -31,12 +31,13 @@
 
 void wl1271_scan_complete_work(struct work_struct *work)
 {
 	struct delayed_work *dwork;
 	struct wl1271 *wl;
 	int ret;
+	bool is_sta, is_ibss;
 
 	dwork = container_of(work, struct delayed_work, work);
 	wl = container_of(dwork, struct wl1271, scan_complete_work);
 
 	wl1271_debug(DEBUG_SCAN, "Scanning complete");
 
@@ -56,13 +57,19 @@ void wl1271_scan_complete_work(struct work_struct *work)
 	if (ret < 0)
 		goto out;
 
 	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
 		/* restore hardware connection monitoring template */
 		wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
-	} else {
+	}
+
+	/* return to ROC if needed */
+	is_sta = (wl->bss_type == BSS_TYPE_STA_BSS);
+	is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+	if ((is_sta && !test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) ||
+	    (is_ibss && !test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))) {
 		/* restore remain on channel */
 		wl12xx_cmd_role_start_dev(wl);
 		wl12xx_roc(wl, wl->dev_role_id);
 	}
 	wl1271_ps_elp_sleep(wl);
 
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 1240f40..8fdffd0 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -179,13 +179,14 @@ static u8 wl1271_tx_get_hlid(struct wl1271 *wl, struct sk_buff *skb)
 	if (wl12xx_is_dummy_packet(wl, skb))
 		return wl->system_hlid;
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS)
 		return wl12xx_tx_get_hlid_ap(wl, skb);
 
-	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags) ||
+	    test_bit(WL1271_FLAG_IBSS_JOINED, &wl->flags))
 		return wl->sta_hlid;
 	else
 		return wl->dev_hlid;
 }
 
 static unsigned int wl12xx_calc_packet_alignment(struct wl1271 *wl,
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 487c3c7..416d68e 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -321,12 +321,13 @@ struct wl1271_ap_key {
 	u32 tx_seq_32;
 	u16 tx_seq_16;
 };
 
 enum wl12xx_flags {
 	WL1271_FLAG_STA_ASSOCIATED,
+	WL1271_FLAG_IBSS_JOINED,
 	WL1271_FLAG_GPIO_POWER,
 	WL1271_FLAG_TX_QUEUE_STOPPED,
 	WL1271_FLAG_TX_PENDING,
 	WL1271_FLAG_IN_ELP,
 	WL1271_FLAG_ELP_REQUESTED,
 	WL1271_FLAG_PSM,
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 28/40] wl12xx: AP-mode - set STA HT capabilities when adding a STA
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (26 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 27/40] wl12xx: support IBSS vif type Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 29/40] wl12xx: AP-mode - configure STA HT rates on join Eliad Peller
                   ` (12 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

In addition, set global HT operation mode via ACX_HT_BSS_OPERATION when
a change is detected by usermode

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/acx.c  |   10 ++++++----
 drivers/net/wireless/wl12xx/acx.h  |    2 +-
 drivers/net/wireless/wl12xx/main.c |   34 +++++++++++++++++++++++++++-------
 3 files changed, 34 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/acx.c b/drivers/net/wireless/wl12xx/acx.c
index ecbceb6..e047594 100644
--- a/drivers/net/wireless/wl12xx/acx.c
+++ b/drivers/net/wireless/wl12xx/acx.c
@@ -1306,27 +1306,29 @@ out:
 	kfree(acx);
 	return ret;
 }
 
 int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 				    struct ieee80211_sta_ht_cap *ht_cap,
-				    bool allow_ht_operation)
+				    bool allow_ht_operation, u8 hlid)
 {
 	struct wl1271_acx_ht_capabilities *acx;
 	int ret = 0;
 	u32 ht_capabilites = 0;
 
-	wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
+	wl1271_debug(DEBUG_ACX, "acx ht capabilities setting "
+		     "sta supp: %d sta cap: %d", ht_cap->ht_supported,
+		     ht_cap->cap);
 
 	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
 	if (!acx) {
 		ret = -ENOMEM;
 		goto out;
 	}
 
-	if (allow_ht_operation) {
+	if (allow_ht_operation && ht_cap->ht_supported) {
 		/* no need to translate capabilities - use the spec values */
 		ht_capabilites = ht_cap->cap;
 
 		/*
 		 * this bit is not employed by the spec but only by FW to
 		 * indicate peer HT support
@@ -1335,13 +1337,13 @@ int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 
 		/* get data from A-MPDU parameters field */
 		acx->ampdu_max_length = ht_cap->ampdu_factor;
 		acx->ampdu_min_spacing = ht_cap->ampdu_density;
 	}
 
-	acx->hlid = wl->sta_hlid;
+	acx->hlid = hlid;
 	acx->ht_capabilites = cpu_to_le32(ht_capabilites);
 
 	ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx ht capabilities setting failed: %d", ret);
 		goto out;
diff --git a/drivers/net/wireless/wl12xx/acx.h b/drivers/net/wireless/wl12xx/acx.h
index 82c9271..758c596 100644
--- a/drivers/net/wireless/wl12xx/acx.h
+++ b/drivers/net/wireless/wl12xx/acx.h
@@ -1265,13 +1265,13 @@ int wl1271_acx_keep_alive_mode(struct wl1271 *wl, bool enable);
 int wl1271_acx_keep_alive_config(struct wl1271 *wl, u8 index, u8 tpl_valid);
 int wl1271_acx_rssi_snr_trigger(struct wl1271 *wl, bool enable,
 				s16 thold, u8 hyst);
 int wl1271_acx_rssi_snr_avg_weights(struct wl1271 *wl);
 int wl1271_acx_set_ht_capabilities(struct wl1271 *wl,
 				    struct ieee80211_sta_ht_cap *ht_cap,
-				    bool allow_ht_operation);
+				    bool allow_ht_operation, u8 hlid);
 int wl1271_acx_set_ht_information(struct wl1271 *wl,
 				   u16 ht_operation_mode);
 int wl12xx_acx_set_ba_initiator_policy(struct wl1271 *wl);
 int wl12xx_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index,
 				       u16 ssn, bool enable, u8 peer_hlid);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index de4b6c2..053751e 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3121,12 +3121,24 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
 		}
 	}
 
 	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
 	if (ret < 0)
 		goto out;
+
+	/* Handle HT information change */
+	if ((changed & BSS_CHANGED_HT) &&
+	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+		ret = wl1271_acx_set_ht_information(wl,
+					bss_conf->ht_operation_mode);
+		if (ret < 0) {
+			wl1271_warning("Set ht information failed %d", ret);
+			goto out;
+		}
+	}
+
 out:
 	return;
 }
 
 /* STA/IBSS mode changes */
 static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
@@ -3436,38 +3448,42 @@ sta_not_found:
 			ret = wl12xx_cmd_role_stop_dev(wl);
 			if (ret < 0)
 				goto out;
 		}
 	}
 
-	/* Handle new association with HT. Do this only after join. */
+	/* Handle new association with HT. Do this after join. */
 	if (sta_exists) {
 		if ((changed & BSS_CHANGED_HT) &&
 		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
-			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
-							     true);
+			ret = wl1271_acx_set_ht_capabilities(wl,
+							     &sta_ht_cap,
+							     true,
+							     wl->sta_hlid);
 			if (ret < 0) {
 				wl1271_warning("Set ht cap true failed %d",
 					       ret);
 				goto out;
 			}
 		}
 		/* handle new association without HT and disassociation */
 		else if (changed & BSS_CHANGED_ASSOC) {
-			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
-							     false);
+			ret = wl1271_acx_set_ht_capabilities(wl,
+							     &sta_ht_cap,
+							     false,
+							     wl->sta_hlid);
 			if (ret < 0) {
 				wl1271_warning("Set ht cap false failed %d",
 					       ret);
 				goto out;
 			}
 		}
 	}
 
-	/* Handle HT information change. Only after join. */
-	if (sta_exists && (changed & BSS_CHANGED_HT) &&
+	/* Handle HT information change. Done after join. */
+	if ((changed & BSS_CHANGED_HT) &&
 	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
 		ret = wl1271_acx_set_ht_information(wl,
 					bss_conf->ht_operation_mode);
 		if (ret < 0) {
 			wl1271_warning("Set ht information failed %d", ret);
 			goto out;
@@ -3700,12 +3716,16 @@ static int wl1271_op_sta_add(struct ieee80211_hw *hw,
 		goto out_sleep;
 
 	ret = wl12xx_cmd_set_peer_state(wl, hlid);
 	if (ret < 0)
 		goto out_sleep;
 
+	ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true, hlid);
+	if (ret < 0)
+		goto out_sleep;
+
 out_sleep:
 	wl1271_ps_elp_sleep(wl);
 
 out_free_sta:
 	if (ret < 0)
 		wl1271_free_sta(wl, hlid);
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 29/40] wl12xx: AP-mode - configure STA HT rates on join
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (27 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 28/40] wl12xx: AP-mode - set STA HT capabilities when adding a STA Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 30/40] wl12xx: AP-mode - configure HT rate support to the FW Eliad Peller
                   ` (11 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

When a new STA joins the BSS, configure the HT rates it supports to the
FW.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/cmd.c |   10 ++++++++--
 1 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index d8c3916..d3e9380 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -1412,16 +1412,18 @@ int wl12xx_cmd_set_peer_state(struct wl1271 *wl, u8 hlid)
 out_free:
 	kfree(cmd);
 
 out:
 	return ret;
 }
+
 int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
 {
 	struct wl12xx_cmd_add_peer *cmd;
 	int ret;
+	u32 sta_rates;
 
 	wl1271_debug(DEBUG_CMD, "cmd add peer %d", (int)hlid);
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
 	if (!cmd) {
 		ret = -ENOMEM;
@@ -1434,14 +1436,18 @@ int wl12xx_cmd_add_peer(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
 	memcpy(cmd->addr, sta->addr, ETH_ALEN);
 	cmd->bss_index = WL1271_AP_BSS_INDEX;
 	cmd->aid = sta->aid;
 	cmd->hlid = hlid;
 	cmd->wmm = sta->wme ? 1 : 0;
 
-	cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
-						sta->supp_rates[wl->band]));
+	sta_rates = sta->supp_rates[wl->band];
+	if (sta->ht_cap.ht_supported)
+		sta_rates |= sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET;
+
+	cmd->supported_rates =
+		cpu_to_le32(wl1271_tx_enabled_rates_get(wl, sta_rates));
 
 	wl1271_debug(DEBUG_CMD, "new peer rates: 0x%x", cmd->supported_rates);
 
 	ret = wl1271_cmd_send(wl, CMD_ADD_PEER, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd add peer");
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 30/40] wl12xx: AP-mode - configure HT rate support to the FW
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (28 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 29/40] wl12xx: AP-mode - configure STA HT rates on join Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 31/40] wl12xx: use ap_bcast_hlid for recorded keys Eliad Peller
                   ` (10 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Unconditionally configure HT rate support to the FW on all ACs
when starting the AP.

When 11n support is disabled by usermode (hostapd), each STA joining
the AP will appear as a non-HT STA. This will stop us from accidentally
transmitting using MCS rates.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/conf.h |    5 +++++
 drivers/net/wireless/wl12xx/init.c |    3 +++
 2 files changed, 8 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/conf.h b/drivers/net/wireless/wl12xx/conf.h
index 76b5c62..82f205c 100644
--- a/drivers/net/wireless/wl12xx/conf.h
+++ b/drivers/net/wireless/wl12xx/conf.h
@@ -438,12 +438,17 @@ struct conf_rx_settings {
 
 #define CONF_TX_OFDM_RATES (CONF_HW_BIT_RATE_6MBPS |             \
 	CONF_HW_BIT_RATE_12MBPS | CONF_HW_BIT_RATE_24MBPS |      \
 	CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS |      \
 	CONF_HW_BIT_RATE_54MBPS)
 
+#define CONF_TX_MCS_RATES (CONF_HW_BIT_RATE_MCS_0 |              \
+	CONF_HW_BIT_RATE_MCS_1 | CONF_HW_BIT_RATE_MCS_2 |        \
+	CONF_HW_BIT_RATE_MCS_3 | CONF_HW_BIT_RATE_MCS_4 |        \
+	CONF_HW_BIT_RATE_MCS_5 | CONF_HW_BIT_RATE_MCS_6 |        \
+	CONF_HW_BIT_RATE_MCS_7)
 
 /*
  * Default rates for management traffic when operating in AP mode. This
  * should be configured according to the basic rate set of the AP
  */
 #define CONF_TX_AP_DEFAULT_MGMT_RATES  (CONF_HW_BIT_RATE_1MBPS | \
diff --git a/drivers/net/wireless/wl12xx/init.c b/drivers/net/wireless/wl12xx/init.c
index a374c21..b13bebe 100644
--- a/drivers/net/wireless/wl12xx/init.c
+++ b/drivers/net/wireless/wl12xx/init.c
@@ -512,12 +512,15 @@ int wl1271_init_ap_rates(struct wl1271 *wl)
 	 */
 	if ((wl->basic_rate_set & CONF_TX_OFDM_RATES))
 		supported_rates = CONF_TX_OFDM_RATES;
 	else
 		supported_rates = CONF_TX_AP_ENABLED_RATES;
 
+	/* unconditionally enable HT rates */
+	supported_rates |= CONF_TX_MCS_RATES;
+
 	/* configure unicast TX rate classes */
 	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
 		rc.enabled_rates = supported_rates;
 		rc.short_retry_limit = 10;
 		rc.long_retry_limit = 10;
 		rc.aflags = 0;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 31/40] wl12xx: use ap_bcast_hlid for recorded keys
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (29 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 30/40] wl12xx: AP-mode - configure HT rate support to the FW Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 32/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
                   ` (9 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

when the key was recorded, wl->ap_bcast_hlid was invalid
(since the role wasn't started), so when configuring the
key we need to use the current ap_bcast_hlid.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c |    7 ++++++-
 1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 053751e..f4f0011 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2530,20 +2530,25 @@ static int wl1271_ap_init_hwenc(struct wl1271 *wl)
 {
 	int i, ret = 0;
 	struct wl1271_ap_key *key;
 	bool wep_key_added = false;
 
 	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		u8 hlid;
 		if (wl->recorded_ap_keys[i] == NULL)
 			break;
 
 		key = wl->recorded_ap_keys[i];
+		hlid = key->hlid;
+		if (hlid == WL12XX_INVALID_LINK_ID)
+			hlid = wl->ap_bcast_hlid;
+
 		ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE,
 					    key->id, key->key_type,
 					    key->key_size, key->key,
-					    key->hlid, key->tx_seq_32,
+					    hlid, key->tx_seq_32,
 					    key->tx_seq_16);
 		if (ret < 0)
 			goto out;
 
 		if (key->key_type == KEY_WEP)
 			wep_key_added = true;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 32/40] wl12xx: don't remove key if hlid was already deleted
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (30 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 31/40] wl12xx: use ap_bcast_hlid for recorded keys Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 33/40] wl12xx: track freed packets in FW by AC Eliad Peller
                   ` (8 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

When wep key was removed after disconnection, sta_hlid was invalid,
and it resulted in a fw crash.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index f4f0011..0ef63b5 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -2622,12 +2622,17 @@ static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		   will be cleared automatically on next CMD_JOIN. Ignore the
 		   request silently, as we dont want the mac80211 to emit
 		   an error message. */
 		if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr))
 			return 0;
 
+		/* don't remove key if hlid was already deleted */
+		if (action == KEY_REMOVE &&
+		    wl->sta_hlid == WL12XX_INVALID_LINK_ID)
+			return 0;
+
 		ret = wl1271_cmd_set_sta_key(wl, action,
 					     id, key_type, key_size,
 					     key, addr, tx_seq_32,
 					     tx_seq_16);
 		if (ret < 0)
 			return ret;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 33/40] wl12xx: track freed packets in FW by AC
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (31 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 32/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 34/40] wl12xx: schedule TX packets according to FW packet occupancy Eliad Peller
                   ` (7 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Track the number of freed packets in each AC when receiving an interrupt
from the FW. This paves the way for tracking allocated packets per AC.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: use bitwise-and instead of modulus

 drivers/net/wireless/wl12xx/main.c   |   16 +++++++++++++++-
 drivers/net/wireless/wl12xx/tx.c     |    2 ++
 drivers/net/wireless/wl12xx/wl12xx.h |    8 ++++++--
 3 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 0ef63b5..479977d 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -811,22 +811,32 @@ static void wl1271_irq_update_links_status(struct wl1271 *wl,
 static void wl12xx_fw_status(struct wl1271 *wl,
 			     struct wl12xx_fw_status *status)
 {
 	struct timespec ts;
 	u32 old_tx_blk_count = wl->tx_blocks_available;
 	int avail, freed_blocks;
+	int i;
 
 	wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
 		     status->intr,
 		     status->fw_rx_counter,
 		     status->drv_rx_counter,
 		     status->tx_results_counter);
 
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		/* prevent wrap-around in freed-packets counter */
+		wl->tx_allocated_pkts -=
+				(status->tx_released_pkts[i] -
+				wl->tx_pkts_freed[i]) & 0xff;
+
+		wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
+	}
+
 	freed_blocks = le32_to_cpu(status->total_released_blks) -
 		       wl->tx_blocks_freed;
 	wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks);
 
 	wl->tx_allocated_blocks -= freed_blocks;
 
@@ -1931,13 +1941,13 @@ out:
 	return ret;
 }
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl,
 					 bool reset_tx_queues)
 {
-	int ret;
+	int ret, i;
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
 
 	/* because of hardware recovery, we may get here twice */
 	if (wl->state != WL1271_STATE_ON)
 		return;
@@ -2047,12 +2057,16 @@ deinit:
 	 * get executed before all these vars have been reset.
 	 */
 	wl->flags = 0;
 
 	wl->tx_blocks_freed = 0;
 
+	wl->tx_allocated_pkts = 0;
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		wl->tx_pkts_freed[i] = 0;
+
 	wl1271_debugfs_reset(wl);
 
 	kfree(wl->fw_status);
 	wl->fw_status = NULL;
 	kfree(wl->tx_res_if);
 	wl->tx_res_if = NULL;
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 8fdffd0..7dd6d8b 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -239,12 +239,14 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 
 		desc->id = id;
 
 		wl->tx_blocks_available -= total_blocks;
 		wl->tx_allocated_blocks += total_blocks;
 
+		wl->tx_allocated_pkts++;
+
 		if (wl->bss_type == BSS_TYPE_AP_BSS)
 			wl->links[hlid].allocated_blks += total_blocks;
 
 		ret = 0;
 
 		wl1271_debug(DEBUG_TX,
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 416d68e..24b4025 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -265,14 +265,14 @@ struct wl12xx_fw_status {
 	/* Cumulative counter of total released mem blocks since FW-reset */
 	__le32 total_released_blks;
 
 	/* Size (in Memory Blocks) of TX pool */
 	__le32 tx_total;
 
-	/* Cumulative counter of released mem-blocks per AC */
-	u8 tx_released_blks[NUM_TX_QUEUES];
+	/* Cumulative counter of released packets per AC */
+	u8 tx_released_pkts[NUM_TX_QUEUES];
 
 	/* Cumulative counter of freed MBs per HLID */
 	u8 tx_lnk_free_blks[WL12XX_MAX_LINKS];
 
 	/* Cumulative counter of released Voice memory blocks */
 	u8 tx_voice_released_blks;
@@ -419,12 +419,16 @@ struct wl1271 {
 	/* Accounting for allocated / available TX blocks on HW */
 	u32 tx_blocks_freed;
 	u32 tx_blocks_available;
 	u32 tx_allocated_blocks;
 	u32 tx_results_count;
 
+	/* Accounting for allocated / available Tx packets in HW */
+	u32 tx_pkts_freed[NUM_TX_QUEUES];
+	u32 tx_allocated_pkts;
+
 	/* Transmitted TX packets counter for chipset interface */
 	u32 tx_packets_count;
 
 	/* Time-offset between host and chipset clocks */
 	s64 time_offset;
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 34/40] wl12xx: schedule TX packets according to FW packet occupancy
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (32 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 33/40] wl12xx: track freed packets in FW by AC Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 35/40] wl12xx: handle wrap-around overflow in released Tx blocks FW counter Eliad Peller
                   ` (6 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

When selecting packets for transmission, prefer the ACs that are least
occupied in the FW. When packets for multiple ACs are present in the FW,
it decides which to transmit according to WMM QoS parameters.

With these changes, lower priority ACs should not be starved when higher
priority traffic is present.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
v2: consider the priority of the queues

 drivers/net/wireless/wl12xx/debugfs.c |    4 ++
 drivers/net/wireless/wl12xx/main.c    |    7 ++-
 drivers/net/wireless/wl12xx/tx.c      |   71 ++++++++++++++++++++++-----------
 drivers/net/wireless/wl12xx/wl12xx.h  |    2 +-
 4 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/debugfs.c b/drivers/net/wireless/wl12xx/debugfs.c
index 3102652..d59354f 100644
--- a/drivers/net/wireless/wl12xx/debugfs.c
+++ b/drivers/net/wireless/wl12xx/debugfs.c
@@ -337,12 +337,16 @@ static ssize_t driver_state_read(struct file *file, char __user *user_buf,
 #define DRIVER_STATE_PRINT_STR(x)  DRIVER_STATE_PRINT(x, "%s")
 #define DRIVER_STATE_PRINT_LHEX(x) DRIVER_STATE_PRINT(x, "0x%lx")
 #define DRIVER_STATE_PRINT_HEX(x)  DRIVER_STATE_PRINT(x, "0x%x")
 
 	DRIVER_STATE_PRINT_INT(tx_blocks_available);
 	DRIVER_STATE_PRINT_INT(tx_allocated_blocks);
+	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[0]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[1]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[2]);
+	DRIVER_STATE_PRINT_INT(tx_allocated_pkts[3]);
 	DRIVER_STATE_PRINT_INT(tx_frames_cnt);
 	DRIVER_STATE_PRINT_LHEX(tx_frames_map[0]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[0]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[1]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[2]);
 	DRIVER_STATE_PRINT_INT(tx_queue_count[3]);
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 479977d..869b8c3 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -824,13 +824,13 @@ static void wl12xx_fw_status(struct wl1271 *wl,
 		     status->fw_rx_counter,
 		     status->drv_rx_counter,
 		     status->tx_results_counter);
 
 	for (i = 0; i < NUM_TX_QUEUES; i++) {
 		/* prevent wrap-around in freed-packets counter */
-		wl->tx_allocated_pkts -=
+		wl->tx_allocated_pkts[i] -=
 				(status->tx_released_pkts[i] -
 				wl->tx_pkts_freed[i]) & 0xff;
 
 		wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
 	}
 
@@ -2057,15 +2057,16 @@ deinit:
 	 * get executed before all these vars have been reset.
 	 */
 	wl->flags = 0;
 
 	wl->tx_blocks_freed = 0;
 
-	wl->tx_allocated_pkts = 0;
-	for (i = 0; i < NUM_TX_QUEUES; i++)
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
 		wl->tx_pkts_freed[i] = 0;
+		wl->tx_allocated_pkts[i] = 0;
+	}
 
 	wl1271_debugfs_reset(wl);
 
 	kfree(wl->fw_status);
 	wl->fw_status = NULL;
 	kfree(wl->tx_res_if);
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index 7dd6d8b..ccbcd0a 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -202,13 +202,13 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 				u32 buf_offset, u8 hlid)
 {
 	struct wl1271_tx_hw_descr *desc;
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
 	u32 len;
 	u32 total_blocks;
-	int id, ret = -EBUSY;
+	int id, ret = -EBUSY, ac;
 
 	/* we use 1 spare block */
 	u32 spare_blocks = 1;
 
 	if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
 		return -EAGAIN;
@@ -239,13 +239,14 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 
 		desc->id = id;
 
 		wl->tx_blocks_available -= total_blocks;
 		wl->tx_allocated_blocks += total_blocks;
 
-		wl->tx_allocated_pkts++;
+		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
+		wl->tx_allocated_pkts[ac]++;
 
 		if (wl->bss_type == BSS_TYPE_AP_BSS)
 			wl->links[hlid].allocated_blks += total_blocks;
 
 		ret = 0;
 
@@ -482,27 +483,51 @@ void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
 			clear_bit(i, &wl->stopped_queues_map);
 			spin_unlock_irqrestore(&wl->wl_lock, flags);
 		}
 	}
 }
 
+static struct sk_buff_head *wl1271_select_queue(struct wl1271 *wl,
+						struct sk_buff_head *queues)
+{
+	int i, q = -1, ac;
+	u32 min_pkts = 0xffffffff;
+
+	/*
+	 * Find a non-empty ac where:
+	 * 1. There are packets to transmit
+	 * 2. The FW has the least allocated blocks
+	 *
+	 * We prioritize the ACs according to VO>VI>BE>BK
+	 */
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		ac = wl1271_tx_get_queue(i);
+		if (!skb_queue_empty(&queues[ac]) &&
+		    (wl->tx_allocated_pkts[ac] < min_pkts)) {
+			q = ac;
+			min_pkts = wl->tx_allocated_pkts[q];
+		}
+	}
+
+	if (q == -1)
+		return NULL;
+
+	return &queues[q];
+}
+
 static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
+	struct sk_buff_head *queue;
 
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VO]);
-	if (skb)
+	queue = wl1271_select_queue(wl, wl->tx_queue);
+	if (!queue)
 		goto out;
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_VI]);
-	if (skb)
-		goto out;
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BE]);
-	if (skb)
-		goto out;
-	skb = skb_dequeue(&wl->tx_queue[CONF_TX_AC_BK]);
+
+	skb = skb_dequeue(queue);
 
 out:
 	if (skb) {
 		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		spin_lock_irqsave(&wl->wl_lock, flags);
 		wl->tx_queue_count[q]--;
@@ -514,35 +539,35 @@ out:
 
 static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
 	int i, h, start_hlid;
+	struct sk_buff_head *queue;
 
 	/* start from the link after the last one */
 	start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
 
 	/* dequeue according to AC, round robin on each link */
 	for (i = 0; i < AP_MAX_LINKS; i++) {
 		h = (start_hlid + i) % AP_MAX_LINKS;
 
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
-		if (skb)
-			goto out;
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
-		if (skb)
-			goto out;
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
-		if (skb)
-			goto out;
-		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+		/* only consider connected stations */
+		if (h >= WL1271_AP_STA_HLID_START &&
+		    !test_bit(h - WL1271_AP_STA_HLID_START, wl->ap_hlid_map))
+			continue;
+
+		queue = wl1271_select_queue(wl, wl->links[h].tx_queue);
+		if (!queue)
+			continue;
+
+		skb = skb_dequeue(queue);
 		if (skb)
-			goto out;
+			break;
 	}
 
-out:
 	if (skb) {
 		int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		wl->last_tx_hlid = h;
 		spin_lock_irqsave(&wl->wl_lock, flags);
 		wl->tx_queue_count[q]--;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 24b4025..6118df5 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -421,13 +421,13 @@ struct wl1271 {
 	u32 tx_blocks_available;
 	u32 tx_allocated_blocks;
 	u32 tx_results_count;
 
 	/* Accounting for allocated / available Tx packets in HW */
 	u32 tx_pkts_freed[NUM_TX_QUEUES];
-	u32 tx_allocated_pkts;
+	u32 tx_allocated_pkts[NUM_TX_QUEUES];
 
 	/* Transmitted TX packets counter for chipset interface */
 	u32 tx_packets_count;
 
 	/* Time-offset between host and chipset clocks */
 	s64 time_offset;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 35/40] wl12xx: handle wrap-around overflow in released Tx blocks FW counter
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (33 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 34/40] wl12xx: schedule TX packets according to FW packet occupancy Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 36/40] wl12xx: enable AP advanced functionality Eliad Peller
                   ` (5 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

When the FW Tx released blocks counter wraps around, we should correct
our calculation of released blocks. Otherwise we add a large negative
figure to our driver freed blocks counter

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 869b8c3..7be7fc6 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -831,14 +831,21 @@ static void wl12xx_fw_status(struct wl1271 *wl,
 				(status->tx_released_pkts[i] -
 				wl->tx_pkts_freed[i]) & 0xff;
 
 		wl->tx_pkts_freed[i] = status->tx_released_pkts[i];
 	}
 
-	freed_blocks = le32_to_cpu(status->total_released_blks) -
-		       wl->tx_blocks_freed;
+	/* prevent wrap-around in total blocks counter */
+	if (likely(wl->tx_blocks_freed <=
+		   le32_to_cpu(status->total_released_blks)))
+		freed_blocks = le32_to_cpu(status->total_released_blks) -
+			       wl->tx_blocks_freed;
+	else
+		freed_blocks = 0x100000000LL - wl->tx_blocks_freed +
+			       le32_to_cpu(status->total_released_blks);
+
 	wl->tx_blocks_freed = le32_to_cpu(status->total_released_blks);
 
 	wl->tx_allocated_blocks -= freed_blocks;
 
 	avail = le32_to_cpu(status->tx_total) - wl->tx_allocated_blocks;
 
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 36/40] wl12xx: enable AP advanced functionality
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (34 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 35/40] wl12xx: handle wrap-around overflow in released Tx blocks FW counter Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 37/40] wl12xx: don't wait for disconnection event Eliad Peller
                   ` (4 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

This adjusts FW TX block allocation for connected stations in PS.
Firmware congestion is measured in allocated packets instead of blocks.

Allow a link in PS to queue up to 2 packets to the FW.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c   |   54 +++++++++++++++++-----------------
 drivers/net/wireless/wl12xx/ps.c     |    4 +-
 drivers/net/wireless/wl12xx/tx.c     |   19 +++++-------
 drivers/net/wireless/wl12xx/wl12xx.h |   25 +++++++++-------
 4 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 7be7fc6..3d323b8 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -752,64 +752,73 @@ static int wl1271_plt_init(struct wl1271 *wl)
 	kfree(wl->target_mem_map);
 	wl->target_mem_map = NULL;
 
 	return ret;
 }
 
-#if 0
-static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
+static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
 {
 	bool fw_ps;
 
 	/* only regulate station links */
 	if (hlid < WL1271_AP_STA_HLID_START)
 		return;
 
 	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 
 	/*
 	 * Wake up from high level PS if the STA is asleep with too little
-	 * blocks in FW or if the STA is awake.
+	 * packets in FW or if the STA is awake.
 	 */
-	if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
+	if (!fw_ps || tx_pkts < WL1271_PS_STA_MAX_PACKETS)
 		wl1271_ps_link_end(wl, hlid);
 
 	/* Start high-level PS if the STA is asleep with enough blocks in FW */
-	else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+	else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl1271_ps_link_start(wl, hlid, true);
 }
 
-static void wl1271_irq_update_links_status(struct wl1271 *wl,
-				       struct wl1271_fw_ap_status *status)
+bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
+{
+	int id = hlid - WL1271_AP_STA_HLID_START;
+	return test_bit(id, wl->ap_hlid_map);
+}
+
+static void wl12xx_irq_update_links_status(struct wl1271 *wl,
+					   struct wl12xx_fw_status *status)
 {
 	u32 cur_fw_ps_map;
-	u8 hlid;
+	u8 hlid, cnt;
+
+	/* TODO: also use link_fast_bitmap here */
 
 	cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
 	if (wl->ap_fw_ps_map != cur_fw_ps_map) {
 		wl1271_debug(DEBUG_PSM,
 			     "link ps prev 0x%x cur 0x%x changed 0x%x",
 			     wl->ap_fw_ps_map, cur_fw_ps_map,
 			     wl->ap_fw_ps_map ^ cur_fw_ps_map);
 
 		wl->ap_fw_ps_map = cur_fw_ps_map;
 	}
 
 	for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
-		u8 cnt = status->tx_lnk_free_blks[hlid] -
-			wl->links[hlid].prev_freed_blks;
+		if (!wl1271_is_active_sta(wl, hlid))
+			continue;
 
-		wl->links[hlid].prev_freed_blks =
-			status->tx_lnk_free_blks[hlid];
-		wl->links[hlid].allocated_blks -= cnt;
+		cnt = status->tx_lnk_free_pkts[hlid] -
+		      wl->links[hlid].prev_freed_pkts;
 
-		wl1271_irq_ps_regulate_link(wl, hlid,
-					    wl->links[hlid].allocated_blks);
+		wl->links[hlid].prev_freed_pkts =
+			status->tx_lnk_free_pkts[hlid];
+		wl->links[hlid].allocated_pkts -= cnt;
+
+		wl12xx_irq_ps_regulate_link(wl, hlid,
+					    wl->links[hlid].allocated_pkts);
 	}
 }
-#endif
 
 static void wl12xx_fw_status(struct wl1271 *wl,
 			     struct wl12xx_fw_status *status)
 {
 	struct timespec ts;
 	u32 old_tx_blk_count = wl->tx_blocks_available;
@@ -862,17 +871,14 @@ static void wl12xx_fw_status(struct wl1271 *wl,
 
 	/* if more blocks are available now, tx work can be scheduled */
 	if (wl->tx_blocks_available > old_tx_blk_count)
 		clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
 
 	/* for AP update num of allocated TX blocks per link and ps status */
-	if (wl->bss_type == BSS_TYPE_AP_BSS) {
-#if 0
-		wl1271_irq_update_links_status(wl, status);
-#endif
-	}
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl12xx_irq_update_links_status(wl, status);
 
 	/* update the host-chipset time offset */
 	getnstimeofday(&ts);
 	wl->time_offset = (timespec_to_ns(&ts) >> 10) -
 		(s64)le32_to_cpu(status->fw_localtime);
 }
@@ -3708,18 +3714,12 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
 	wl->links[hlid].ba_bitmap = 0;
 	wl1271_tx_reset_link_queues(wl, hlid);
 	__clear_bit(hlid, &wl->ap_ps_map);
 	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 }
 
-bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
-{
-	int id = hlid - WL1271_AP_STA_HLID_START;
-	return test_bit(id, wl->ap_hlid_map);
-}
-
 static int wl1271_op_sta_add(struct ieee80211_hw *hw,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_sta *sta)
 {
 	struct wl1271 *wl = hw->priv;
 	int ret = 0;
diff --git a/drivers/net/wireless/wl12xx/ps.c b/drivers/net/wireless/wl12xx/ps.c
index 3548377..4b720b1 100644
--- a/drivers/net/wireless/wl12xx/ps.c
+++ b/drivers/net/wireless/wl12xx/ps.c
@@ -223,14 +223,14 @@ void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
 {
 	struct ieee80211_sta *sta;
 
 	if (test_bit(hlid, &wl->ap_ps_map))
 		return;
 
-	wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
-		     "clean_queues %d", hlid, wl->links[hlid].allocated_blks,
+	wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d pkts %d "
+		     "clean_queues %d", hlid, wl->links[hlid].allocated_pkts,
 		     clean_queues);
 
 	rcu_read_lock();
 	sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
 	if (!sta) {
 		wl1271_error("could not find sta %pM for starting ps",
diff --git a/drivers/net/wireless/wl12xx/tx.c b/drivers/net/wireless/wl12xx/tx.c
index ccbcd0a..0f15785 100644
--- a/drivers/net/wireless/wl12xx/tx.c
+++ b/drivers/net/wireless/wl12xx/tx.c
@@ -120,33 +120,31 @@ static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
 	hdr = (struct ieee80211_hdr *)(skb->data +
 				       sizeof(struct wl1271_tx_hw_descr));
 	if (ieee80211_is_auth(hdr->frame_control))
 		wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
 }
 
-#if 0
 static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
 {
 	bool fw_ps;
-	u8 tx_blks;
+	u8 tx_pkts;
 
 	/* only regulate station links */
 	if (hlid < WL1271_AP_STA_HLID_START)
 		return;
 
 	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
-	tx_blks = wl->links[hlid].allocated_blks;
+	tx_pkts = wl->links[hlid].allocated_pkts;
 
 	/*
 	 * if in FW PS and there is enough data in FW we can put the link
 	 * into high-level PS and clean out its TX queues.
 	 */
-	if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+	if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl1271_ps_link_start(wl, hlid, true);
 }
-#endif
 
 static bool wl12xx_is_dummy_packet(struct wl1271 *wl, struct sk_buff *skb)
 {
 	return wl->dummy_packet == skb;
 }
 
@@ -242,14 +240,15 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
 		wl->tx_blocks_available -= total_blocks;
 		wl->tx_allocated_blocks += total_blocks;
 
 		ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 		wl->tx_allocated_pkts[ac]++;
 
-		if (wl->bss_type == BSS_TYPE_AP_BSS)
-			wl->links[hlid].allocated_blks += total_blocks;
+		if (wl->bss_type == BSS_TYPE_AP_BSS &&
+		    hlid >= WL1271_AP_STA_HLID_START)
+			wl->links[hlid].allocated_pkts++;
 
 		ret = 0;
 
 		wl1271_debug(DEBUG_TX,
 			     "tx_allocate: size: %d, blocks: %d, id: %d",
 			     total_len, total_blocks, id);
@@ -411,15 +410,13 @@ static int wl1271_prepare_tx_frame(struct wl1271 *wl, struct sk_buff *skb,
 		return ret;
 
 	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		wl1271_tx_ap_update_inconnection_sta(wl, skb);
-#if 0
 		wl1271_tx_regulate_link(wl, hlid);
-#endif
 	} else {
 		wl1271_tx_update_filters(wl, skb);
 	}
 
 	/*
 	 * The length of each packet is stored in terms of
@@ -885,14 +882,14 @@ void wl1271_tx_reset(struct wl1271 *wl, bool reset_tx_queues)
 	struct ieee80211_tx_info *info;
 
 	/* TX failure */
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		for (i = 0; i < AP_MAX_LINKS; i++) {
 			wl1271_tx_reset_link_queues(wl, i);
-			wl->links[i].allocated_blks = 0;
-			wl->links[i].prev_freed_blks = 0;
+			wl->links[i].allocated_pkts = 0;
+			wl->links[i].prev_freed_pkts = 0;
 		}
 
 		wl->last_tx_hlid = 0;
 	} else {
 		for (i = 0; i < NUM_TX_QUEUES; i++) {
 			while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 6118df5..61a7c21 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -149,21 +149,20 @@ extern u32 wl12xx_debug_level;
  * TODO: we currently don't support multirole. remove
  * this constant from the code when we do.
  */
 #define WL1271_AP_STA_HLID_START   3
 
 /*
- * When in AP-mode, we allow (at least) this number of mem-blocks
+ * When in AP-mode, we allow (at least) this number of packets
  * to be transmitted to FW for a STA in PS-mode. Only when packets are
  * present in the FW buffers it will wake the sleeping STA. We want to put
  * enough packets for the driver to transmit all of its buffered data before
- * the STA goes to sleep again. But we don't want to take too much mem-blocks
+ * the STA goes to sleep again. But we don't want to take too much memory
  * as it might hurt the throughput of active STAs.
- * The number of blocks (18) is enough for 2 large packets.
  */
-#define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)
+#define WL1271_PS_STA_MAX_PACKETS  2
 
 #define WL1271_AP_BSS_INDEX        0
 #define WL1271_AP_DEF_BEACON_EXP   20
 
 #define ACX_TX_DESCRIPTORS         16
 
@@ -234,14 +233,18 @@ struct wl1271_stats {
 
 #define NUM_TX_QUEUES              4
 #define NUM_RX_PKT_DESC            8
 
 #define AP_MAX_STATIONS            5
 
-/* Broadcast and Global links + links to stations */
-#define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
+/* Broadcast and Global links + system link + links to stations */
+/*
+ * TODO: when WL1271_AP_STA_HLID_START is no longer constant, change all
+ * the places that use this.
+ */
+#define AP_MAX_LINKS               (AP_MAX_STATIONS + 3)
 
 /* FW status registers */
 struct wl12xx_fw_status {
 	__le32 intr;
 	u8  fw_rx_counter;
 	u8  drv_rx_counter;
@@ -268,14 +271,14 @@ struct wl12xx_fw_status {
 	/* Size (in Memory Blocks) of TX pool */
 	__le32 tx_total;
 
 	/* Cumulative counter of released packets per AC */
 	u8 tx_released_pkts[NUM_TX_QUEUES];
 
-	/* Cumulative counter of freed MBs per HLID */
-	u8 tx_lnk_free_blks[WL12XX_MAX_LINKS];
+	/* Cumulative counter of freed packets per HLID */
+	u8 tx_lnk_free_pkts[WL12XX_MAX_LINKS];
 
 	/* Cumulative counter of released Voice memory blocks */
 	u8 tx_voice_released_blks;
 	u8 padding_1[7];
 	__le32 log_start_addr;
 } __packed;
@@ -348,15 +351,15 @@ enum wl12xx_flags {
 };
 
 struct wl1271_link {
 	/* AP-mode - TX queue per AC in link */
 	struct sk_buff_head tx_queue[NUM_TX_QUEUES];
 
-	/* accounting for allocated / available TX blocks in FW */
-	u8 allocated_blks;
-	u8 prev_freed_blks;
+	/* accounting for allocated / freed packets in FW */
+	u8 allocated_pkts;
+	u8 prev_freed_pkts;
 
 	u8 addr[ETH_ALEN];
 
 	/* bitmap of TIDs where RX BA sessions are active for this link */
 	u8 ba_bitmap;
 };
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 37/40] wl12xx: don't wait for disconnection event
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (35 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 36/40] wl12xx: enable AP advanced functionality Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 38/40] wl12xx: set the AP-started flag only after setting keys Eliad Peller
                   ` (3 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

Sometimes the fw doesn't send the DISCONNECT_EVENT_COMPLETE_ID
on station role stop, so don't wait for it.

Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/cmd.c |    6 ------
 1 files changed, 0 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/cmd.c b/drivers/net/wireless/wl12xx/cmd.c
index d3e9380..817bc18 100644
--- a/drivers/net/wireless/wl12xx/cmd.c
+++ b/drivers/net/wireless/wl12xx/cmd.c
@@ -641,18 +641,12 @@ int wl12xx_cmd_role_stop_sta(struct wl1271 *wl)
 	ret = wl1271_cmd_send(wl, CMD_ROLE_STOP, cmd, sizeof(*cmd), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd role stop sta");
 		goto out_free;
 	}
 
-	ret = wl1271_cmd_wait_for_event(wl, DISCONNECT_EVENT_COMPLETE_ID);
-	if (ret < 0) {
-		wl1271_error("cmd role stop sta event completion error");
-		goto out_free;
-	}
-
 	wl12xx_free_link(wl, &wl->sta_hlid);
 
 out_free:
 	kfree(cmd);
 
 out:
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 38/40] wl12xx: set the AP-started flag only after setting keys
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (36 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 37/40] wl12xx: don't wait for disconnection event Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 39/40] wl12xx: AP-mode - prevent Tx to stale/invalid stations Eliad Peller
                   ` (2 subsequent siblings)
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

This fix eliminates a potential race between starting the AP role
and setting encryption keys.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 3d323b8..cf5835b 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -3137,18 +3137,18 @@ static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
 		if (bss_conf->enable_beacon) {
 			if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
 				ret = wl12xx_cmd_role_start_ap(wl);
 				if (ret < 0)
 					goto out;
 
-				set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
-				wl1271_debug(DEBUG_AP, "started AP");
-
 				ret = wl1271_ap_init_hwenc(wl);
 				if (ret < 0)
 					goto out;
+
+				set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+				wl1271_debug(DEBUG_AP, "started AP");
 			}
 		} else {
 			if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
 				ret = wl12xx_cmd_role_stop_ap(wl);
 				if (ret < 0)
 					goto out;
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 39/40] wl12xx: AP-mode - prevent Tx to stale/invalid stations
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (37 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 38/40] wl12xx: set the AP-started flag only after setting keys Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-14 10:17 ` [PATCH v2 40/40] wl12xx: fix tx_queue_count spurious increment Eliad Peller
  2011-08-22 11:11 ` [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Luciano Coelho
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Don't pollute the queues with Tx directed to invalid stations. This
can happen during recovery.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c |   20 +++++++++++++++++---
 1 files changed, 17 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index cf5835b..6c56bef 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -776,13 +776,19 @@ static void wl12xx_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_pkts)
 	else if (fw_ps && tx_pkts >= WL1271_PS_STA_MAX_PACKETS)
 		wl1271_ps_link_start(wl, hlid, true);
 }
 
 bool wl1271_is_active_sta(struct wl1271 *wl, u8 hlid)
 {
-	int id = hlid - WL1271_AP_STA_HLID_START;
+	int id;
+
+	/* global/broadcast "stations" are always active */
+	if (hlid < WL1271_AP_STA_HLID_START)
+		return true;
+
+	id = hlid - WL1271_AP_STA_HLID_START;
 	return test_bit(id, wl->ap_hlid_map);
 }
 
 static void wl12xx_irq_update_links_status(struct wl1271 *wl,
 					   struct wl12xx_fw_status *status)
 {
@@ -1490,12 +1496,19 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		ieee80211_stop_queue(wl->hw, mapping);
 		set_bit(q, &wl->stopped_queues_map);
 	}
 
 	/* queue the packet */
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		if (!wl1271_is_active_sta(wl, hlid)) {
+			wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d",
+				     hlid, q);
+			dev_kfree_skb(skb);
+			goto out;
+		}
+
 		wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
 		skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
 	} else {
 		skb_queue_tail(&wl->tx_queue[q], skb);
 	}
 
@@ -1505,12 +1518,13 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 */
 
 	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
 	    !test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
 		ieee80211_queue_work(wl->hw, &wl->tx_work);
 
+out:
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 }
 
 int wl1271_tx_dummy_packet(struct wl1271 *wl)
 {
 	unsigned long flags;
@@ -3692,13 +3706,13 @@ static int wl1271_allocate_sta(struct wl1271 *wl,
 	if (id >= AP_MAX_STATIONS) {
 		wl1271_warning("could not allocate HLID - too much stations");
 		return -EBUSY;
 	}
 
 	wl_sta = (struct wl1271_station *)sta->drv_priv;
-	__set_bit(id, wl->ap_hlid_map);
+	set_bit(id, wl->ap_hlid_map);
 	wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
 	*hlid = wl_sta->hlid;
 	memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
 	return 0;
 }
 
@@ -3706,13 +3720,13 @@ static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
 {
 	int id = hlid - WL1271_AP_STA_HLID_START;
 
 	if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
 		return;
 
-	__clear_bit(id, wl->ap_hlid_map);
+	clear_bit(id, wl->ap_hlid_map);
 	memset(wl->links[hlid].addr, 0, ETH_ALEN);
 	wl->links[hlid].ba_bitmap = 0;
 	wl1271_tx_reset_link_queues(wl, hlid);
 	__clear_bit(hlid, &wl->ap_ps_map);
 	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
 }
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* [PATCH v2 40/40] wl12xx: fix tx_queue_count spurious increment
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (38 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 39/40] wl12xx: AP-mode - prevent Tx to stale/invalid stations Eliad Peller
@ 2011-08-14 10:17 ` Eliad Peller
  2011-08-22 11:11 ` [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Luciano Coelho
  40 siblings, 0 replies; 42+ messages in thread
From: Eliad Peller @ 2011-08-14 10:17 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless

From: Arik Nemtsov <arik@wizery.com>

Only increment the queue count after actually queuing the skb. This
avoids a spurious increment is case of dropped packets.

Also move the Tx-watermark checking code after the packet is enqueued.
This makes the count more accurate - it includes the just-queued
packet.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Signed-off-by: Eliad Peller <eliad@wizery.com>
---
 drivers/net/wireless/wl12xx/main.c |   24 ++++++++++++------------
 1 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index 6c56bef..5001766 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1482,24 +1482,12 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 
 	if (wl->bss_type == BSS_TYPE_AP_BSS)
 		hlid = wl12xx_tx_get_hlid_ap(wl, skb);
 
 	spin_lock_irqsave(&wl->wl_lock, flags);
 
-	wl->tx_queue_count[q]++;
-
-	/*
-	 * The workqueue is slow to process the tx_queue and we need stop
-	 * the queue here, otherwise the queue will get too long.
-	 */
-	if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
-		wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
-		ieee80211_stop_queue(wl->hw, mapping);
-		set_bit(q, &wl->stopped_queues_map);
-	}
-
 	/* queue the packet */
 	if (wl->bss_type == BSS_TYPE_AP_BSS) {
 		if (!wl1271_is_active_sta(wl, hlid)) {
 			wl1271_debug(DEBUG_TX, "DROP skb hlid %d q %d",
 				     hlid, q);
 			dev_kfree_skb(skb);
@@ -1509,12 +1497,24 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 		wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
 		skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
 	} else {
 		skb_queue_tail(&wl->tx_queue[q], skb);
 	}
 
+	wl->tx_queue_count[q]++;
+
+	/*
+	 * The workqueue is slow to process the tx_queue and we need stop
+	 * the queue here, otherwise the queue will get too long.
+	 */
+	if (wl->tx_queue_count[q] >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
+		wl1271_debug(DEBUG_TX, "op_tx: stopping queues for q %d", q);
+		ieee80211_stop_queue(wl->hw, mapping);
+		set_bit(q, &wl->stopped_queues_map);
+	}
+
 	/*
 	 * The chip specific setup must run before the first TX packet -
 	 * before that, the tx_work will not be initialized!
 	 */
 
 	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
-- 
1.7.6.401.g6a319


^ permalink raw reply related	[flat|nested] 42+ messages in thread

* Re: [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3
  2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
                   ` (39 preceding siblings ...)
  2011-08-14 10:17 ` [PATCH v2 40/40] wl12xx: fix tx_queue_count spurious increment Eliad Peller
@ 2011-08-22 11:11 ` Luciano Coelho
  40 siblings, 0 replies; 42+ messages in thread
From: Luciano Coelho @ 2011-08-22 11:11 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless

On Sun, 2011-08-14 at 13:16 +0300, Eliad Peller wrote: 
> The new wl12xx fw (ver 7.3.0.0.75) had some major api changes.
> The main change was the addition of multi-role concept, which
> will later allow using multiple vifs concurrently.
> 
> Consequently, this design change caused api changes for most
> of the api commands, as a new role_id had to be added.
> 
> This patchset migrates the fw to use the new fw api (a new
> fw filename is used, as there is no backward compatability
> with older firmwares).
> 
> Additional patchsets will follow, with further bugfixes
> and new features (e.g. p2p support).
> 
> v2: apply Luca's comments, rebase.

Applied and pushed the series, including v3 of patch 02/40 and 23/40.

Thanks a lot for all the work!

-- 
Cheers,
Luca.


^ permalink raw reply	[flat|nested] 42+ messages in thread

end of thread, other threads:[~2011-08-22 11:11 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2011-08-14 10:16 [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Eliad Peller
2011-08-14 10:17 ` [PATCH v2 01/40] wl12xx: Revert "wl12xx: schedule TX packets according to FW occupancy" Eliad Peller
2011-08-14 10:17 ` [PATCH v2 02/40] wl12xx: Use a single fw for both STA and AP roles Eliad Peller
2011-08-14 10:17 ` [PATCH v2 03/40] wl12xx: use 1 spare block in all cases Eliad Peller
2011-08-14 10:17 ` [PATCH v2 04/40] wl12xx: temporarily disable advanced ap functions Eliad Peller
2011-08-14 10:17 ` [PATCH v2 05/40] wl12xx: remove rx filtering stuff Eliad Peller
2011-08-14 10:17 ` [PATCH v2 06/40] wl12xx: update fw status struct Eliad Peller
2011-08-14 10:17 ` [PATCH v2 07/40] wl12xx: update acx commands Eliad Peller
2011-08-14 10:17 ` [PATCH v2 08/40] wl12xx: update commands & events Eliad Peller
2011-08-14 10:17 ` [PATCH v2 09/40] wl12xx: enable/disable role on interface add/remove Eliad Peller
2011-08-14 10:17 ` [PATCH v2 10/40] wl12xx: add device role commands Eliad Peller
2011-08-14 10:17 ` [PATCH v2 11/40] wl12xx: update scan cmd api Eliad Peller
2011-08-14 10:17 ` [PATCH v2 12/40] wl12xx: update rx/tx Eliad Peller
2011-08-14 10:17 ` [PATCH v2 13/40] wl12xx: change max/default template size Eliad Peller
2011-08-14 10:17 ` [PATCH v2 14/40] wl12xx: use wl1271_acx_beacon_filter_opt for both sta and ap Eliad Peller
2011-08-14 10:17 ` [PATCH v2 15/40] wl12xx: add set_rate_mgmt_params acx Eliad Peller
2011-08-14 10:17 ` [PATCH v2 16/40] wl12xx: add system_hlid Eliad Peller
2011-08-14 10:17 ` [PATCH v2 17/40] wl12xx: add ROC/CROC commands Eliad Peller
2011-08-14 10:17 ` [PATCH v2 18/40] wl12xx: replace dummy_join with " Eliad Peller
2011-08-14 10:17 ` [PATCH v2 19/40] wl12xx: handle dummy packet event also in ap mode Eliad Peller
2011-08-14 10:17 ` [PATCH v2 20/40] wl12xx: update BT coex configuration params Eliad Peller
2011-08-14 10:17 ` [PATCH v2 21/40] wl12xx: fix session counter Eliad Peller
2011-08-14 10:17 ` [PATCH v2 22/40] wl12xx: use dynamic hlids for AP-mode Eliad Peller
2011-08-14 10:17 ` [PATCH v2 23/40] wl12xx: re-enable block ack session support Eliad Peller
2011-08-14 10:17 ` [PATCH v2 24/40] wl12xx: call wl12xx_cmd_set_peer_state() in AP mode Eliad Peller
2011-08-14 10:17 ` [PATCH v2 25/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
2011-08-14 10:17 ` [PATCH v2 26/40] wl12xx: add wl12xx_cmd_role_start_ibss() Eliad Peller
2011-08-14 10:17 ` [PATCH v2 27/40] wl12xx: support IBSS vif type Eliad Peller
2011-08-14 10:17 ` [PATCH v2 28/40] wl12xx: AP-mode - set STA HT capabilities when adding a STA Eliad Peller
2011-08-14 10:17 ` [PATCH v2 29/40] wl12xx: AP-mode - configure STA HT rates on join Eliad Peller
2011-08-14 10:17 ` [PATCH v2 30/40] wl12xx: AP-mode - configure HT rate support to the FW Eliad Peller
2011-08-14 10:17 ` [PATCH v2 31/40] wl12xx: use ap_bcast_hlid for recorded keys Eliad Peller
2011-08-14 10:17 ` [PATCH v2 32/40] wl12xx: don't remove key if hlid was already deleted Eliad Peller
2011-08-14 10:17 ` [PATCH v2 33/40] wl12xx: track freed packets in FW by AC Eliad Peller
2011-08-14 10:17 ` [PATCH v2 34/40] wl12xx: schedule TX packets according to FW packet occupancy Eliad Peller
2011-08-14 10:17 ` [PATCH v2 35/40] wl12xx: handle wrap-around overflow in released Tx blocks FW counter Eliad Peller
2011-08-14 10:17 ` [PATCH v2 36/40] wl12xx: enable AP advanced functionality Eliad Peller
2011-08-14 10:17 ` [PATCH v2 37/40] wl12xx: don't wait for disconnection event Eliad Peller
2011-08-14 10:17 ` [PATCH v2 38/40] wl12xx: set the AP-started flag only after setting keys Eliad Peller
2011-08-14 10:17 ` [PATCH v2 39/40] wl12xx: AP-mode - prevent Tx to stale/invalid stations Eliad Peller
2011-08-14 10:17 ` [PATCH v2 40/40] wl12xx: fix tx_queue_count spurious increment Eliad Peller
2011-08-22 11:11 ` [PATCH v2 00/40] wl12xx: move to wl12xx-fw-3 Luciano Coelho

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.