linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 00/16] mwifiex: patches for 3.7
@ 2012-08-04  1:05 Bing Zhao
  2012-08-04  1:05 ` [PATCH 01/16] mwifiex: copy MSDU subframes correctly Bing Zhao
                   ` (15 more replies)
  0 siblings, 16 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:05 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

1st patch series intended for 3.7:

01~03: fix A-MSDU subframe buffer overwitten issue (Yogesh Ashok Powar)
04:    fix RxPD issue for big endian platforms (Amitkumar Karwar)
05~06: enhance scan logic while tx traffic is ongoing (Amitkumar Karwar)
07~13: add 11n support & STA-STA forwarding for AP mode (Avinash Patil)
14~16: support AES_CMAC (Ying Luo)

---
Amitkumar Karwar (3):
  mwifiex: do le_to_cpu conversion for Rx packet header elements
  mwifiex: update max_chan_per_scan correctly for SSID scan
  mwifiex: improve scan delay logic during Tx traffic

Avinash Patil (7):
  mwifiex: update 11n status as per start_ap IE
  mwifiex: separate file for handling AP events
  mwifiex: create list for associated stations in AP mode
  mwifiex: improve uAP RX handling
  mwifiex: support RX AMSDU aggregation for uAP
  mwifiex: add 11n Block Ack support for uAP
  mwifiex: cleanup TX/RX BA tables for uAP

Ying Luo (3):
  mwifiex: rename wapi_rxpn to pn
  mwifiex: pass key_params pointer in mwifiex_set_encode
  mwifiex: add AES_CMAC support in key_material cmd

Yogesh Ashok Powar (3):
  mwifiex: copy MSDU subframes correctly
  mwifiex: remove extra padding to AMSDU
  mwifiex: correction in MSDU padding logic

 drivers/net/wireless/mwifiex/11n.c           |   26 +++
 drivers/net/wireless/mwifiex/11n.h           |   15 ++
 drivers/net/wireless/mwifiex/11n_aggr.c      |   14 +-
 drivers/net/wireless/mwifiex/11n_rxreorder.c |   66 +++++-
 drivers/net/wireless/mwifiex/11n_rxreorder.h |    5 +
 drivers/net/wireless/mwifiex/Makefile        |    2 +
 drivers/net/wireless/mwifiex/cfg80211.c      |   17 +-
 drivers/net/wireless/mwifiex/cmdevt.c        |    5 +-
 drivers/net/wireless/mwifiex/decl.h          |    3 +
 drivers/net/wireless/mwifiex/fw.h            |   42 ++++-
 drivers/net/wireless/mwifiex/init.c          |  107 ++++++----
 drivers/net/wireless/mwifiex/ioctl.h         |    5 +-
 drivers/net/wireless/mwifiex/main.c          |    3 +
 drivers/net/wireless/mwifiex/main.h          |   38 +++-
 drivers/net/wireless/mwifiex/scan.c          |    2 +
 drivers/net/wireless/mwifiex/sta_cmd.c       |   55 ++++-
 drivers/net/wireless/mwifiex/sta_event.c     |   49 +-----
 drivers/net/wireless/mwifiex/sta_ioctl.c     |   12 +-
 drivers/net/wireless/mwifiex/sta_rx.c        |   38 ++--
 drivers/net/wireless/mwifiex/txrx.c          |    5 +
 drivers/net/wireless/mwifiex/uap_cmd.c       |    1 +
 drivers/net/wireless/mwifiex/uap_event.c     |  291 ++++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/uap_txrx.c      |  255 ++++++++++++++++++++++
 drivers/net/wireless/mwifiex/wmm.c           |   59 +++++-
 24 files changed, 948 insertions(+), 167 deletions(-)
 create mode 100644 drivers/net/wireless/mwifiex/uap_event.c
 create mode 100644 drivers/net/wireless/mwifiex/uap_txrx.c


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

* [PATCH 01/16] mwifiex: copy MSDU subframes correctly
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
@ 2012-08-04  1:05 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 02/16] mwifiex: remove extra padding to AMSDU Bing Zhao
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:05 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Yogesh Ashok Powar <yogeshp@marvell.com>

All MSDU subframes, except the first one in AMSDU, were being written
wrongly at the location of first MSDU frame. Fixing that by copying
the MSDU at skb->tail of AMSDU.

Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/11n_aggr.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index ab84eb9..c631c7c 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -62,9 +62,7 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
 	};
 	struct tx_packet_hdr *tx_header;
 
-	skb_put(skb_aggr, sizeof(*tx_header));
-
-	tx_header = (struct tx_packet_hdr *) skb_aggr->data;
+	tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header));
 
 	/* Copy DA and SA */
 	dt_offset = 2 * ETH_ALEN;
@@ -82,9 +80,8 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
 	tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN);
 
 	/* Add payload */
-	skb_put(skb_aggr, skb_src->len);
-	memcpy(skb_aggr->data + sizeof(*tx_header), skb_src->data,
-	       skb_src->len);
+	memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
+
 	*pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len +
 						      LLC_SNAP_LEN)) & 3)) : 0;
 	skb_put(skb_aggr, *pad);
-- 
1.7.0.2


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

* [PATCH 02/16] mwifiex: remove extra padding to AMSDU
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
  2012-08-04  1:05 ` [PATCH 01/16] mwifiex: copy MSDU subframes correctly Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 03/16] mwifiex: correction in MSDU padding logic Bing Zhao
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Yogesh Ashok Powar <yogeshp@marvell.com>

Since commit: fb3c19bc9687d972b83faf366b38ac807eca8f25, adding
extra padding to AMSDU is redundant since same is being performed at
mwifiex_11n_aggregate_pkt after forming the AMSDU packet. Fixing it
by removing it.

Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/11n_aggr.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index c631c7c..04222f2 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -84,7 +84,6 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
 
 	*pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len +
 						      LLC_SNAP_LEN)) & 3)) : 0;
-	skb_put(skb_aggr, *pad);
 
 	return skb_aggr->len + *pad;
 }
-- 
1.7.0.2


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

* [PATCH 03/16] mwifiex: correction in MSDU padding logic
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
  2012-08-04  1:05 ` [PATCH 01/16] mwifiex: copy MSDU subframes correctly Bing Zhao
  2012-08-04  1:06 ` [PATCH 02/16] mwifiex: remove extra padding to AMSDU Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 04/16] mwifiex: do le_to_cpu conversion for Rx packet header elements Bing Zhao
                   ` (12 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Yogesh Ashok Powar <yogeshp@marvell.com>

Padding arithmetic will always work for MSDUs provided first MSDU
ends on 4-byte boundary. Fixing it by making sure that all MSDU ends
on 4-byte boundary.

Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/11n_aggr.c |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 04222f2..395f1bf 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -82,8 +82,8 @@ mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr,
 	/* Add payload */
 	memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len);
 
-	*pad = (((skb_src->len + LLC_SNAP_LEN) & 3)) ? (4 - (((skb_src->len +
-						      LLC_SNAP_LEN)) & 3)) : 0;
+	/* Add padding for new MSDU to start from 4 byte boundary */
+	*pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4;
 
 	return skb_aggr->len + *pad;
 }
-- 
1.7.0.2


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

* [PATCH 04/16] mwifiex: do le_to_cpu conversion for Rx packet header elements
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (2 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 03/16] mwifiex: correction in MSDU padding logic Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 05/16] mwifiex: update max_chan_per_scan correctly for SSID scan Bing Zhao
                   ` (11 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Amitkumar Karwar <akarwar@marvell.com>

We do similar conversion for Tx packet header but it was missing
for Rx packet header. Without this fix, Rx packet header won't
be correctly parsed on big endian platform.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/fw.h     |    8 +++---
 drivers/net/wireless/mwifiex/sta_rx.c |   38 +++++++++++++++-----------------
 2 files changed, 22 insertions(+), 24 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index e831b44..a0222ec 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -424,10 +424,10 @@ struct txpd {
 struct rxpd {
 	u8 bss_type;
 	u8 bss_num;
-	u16 rx_pkt_length;
-	u16 rx_pkt_offset;
-	u16 rx_pkt_type;
-	u16 seq_num;
+	__le16 rx_pkt_length;
+	__le16 rx_pkt_offset;
+	__le16 rx_pkt_type;
+	__le16 seq_num;
 	u8 priority;
 	u8 rx_rate;
 	s8 snr;
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index 02ce3b7..d91d5c0 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -54,8 +54,8 @@ int mwifiex_process_rx_packet(struct mwifiex_adapter *adapter,
 
 	local_rx_pd = (struct rxpd *) (skb->data);
 
-	rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd +
-				local_rx_pd->rx_pkt_offset);
+	rx_pkt_hdr = (void *)local_rx_pd +
+		     le16_to_cpu(local_rx_pd->rx_pkt_offset);
 
 	if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
 		    rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr))) {
@@ -125,7 +125,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u8 ta[ETH_ALEN];
-	u16 rx_pkt_type;
+	u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num;
 	struct mwifiex_private *priv =
 			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
 					       rx_info->bss_type);
@@ -134,16 +134,17 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 		return -1;
 
 	local_rx_pd = (struct rxpd *) (skb->data);
-	rx_pkt_type = local_rx_pd->rx_pkt_type;
+	rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type);
+	rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset);
+	rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length);
+	seq_num = le16_to_cpu(local_rx_pd->seq_num);
 
-	rx_pkt_hdr = (struct rx_packet_hdr *) ((u8 *) local_rx_pd +
-					local_rx_pd->rx_pkt_offset);
+	rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset;
 
-	if ((local_rx_pd->rx_pkt_offset + local_rx_pd->rx_pkt_length) >
-	    (u16) skb->len) {
-		dev_err(adapter->dev, "wrong rx packet: len=%d,"
-			" rx_pkt_offset=%d, rx_pkt_length=%d\n", skb->len,
-		       local_rx_pd->rx_pkt_offset, local_rx_pd->rx_pkt_length);
+	if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) {
+		dev_err(adapter->dev,
+			"wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n",
+			skb->len, rx_pkt_offset, rx_pkt_length);
 		priv->stats.rx_dropped++;
 
 		if (adapter->if_ops.data_complete)
@@ -154,14 +155,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 		return ret;
 	}
 
-	if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
+	if (rx_pkt_type == PKT_TYPE_AMSDU) {
 		struct sk_buff_head list;
 		struct sk_buff *rx_skb;
 
 		__skb_queue_head_init(&list);
 
-		skb_pull(skb, local_rx_pd->rx_pkt_offset);
-		skb_trim(skb, local_rx_pd->rx_pkt_length);
+		skb_pull(skb, rx_pkt_offset);
+		skb_trim(skb, rx_pkt_length);
 
 		ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
 					 priv->wdev->iftype, 0, false);
@@ -189,17 +190,14 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 		memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
 	} else {
 		if (rx_pkt_type != PKT_TYPE_BAR)
-			priv->rx_seq[local_rx_pd->priority] =
-						local_rx_pd->seq_num;
+			priv->rx_seq[local_rx_pd->priority] = seq_num;
 		memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address,
 		       ETH_ALEN);
 	}
 
 	/* Reorder and send to OS */
-	ret = mwifiex_11n_rx_reorder_pkt(priv, local_rx_pd->seq_num,
-					     local_rx_pd->priority, ta,
-					     (u8) local_rx_pd->rx_pkt_type,
-					     skb);
+	ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority,
+					 ta, (u8) rx_pkt_type, skb);
 
 	if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
 		if (adapter->if_ops.data_complete)
-- 
1.7.0.2


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

* [PATCH 05/16] mwifiex: update max_chan_per_scan correctly for SSID scan
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (3 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 04/16] mwifiex: do le_to_cpu conversion for Rx packet header elements Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 06/16] mwifiex: improve scan delay logic during Tx traffic Bing Zhao
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Amitkumar Karwar <akarwar@marvell.com>

As per recent patch "658f37b mwifiex: scan less channels..."
less channels are scanned per scan command in associated state.

Default number of channels per scan command for normal scan are
already 4, but those are 14 for SSID specific scan operation.

This code change in this patch is required for SSID specific scan.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/scan.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 04dc7ca..3035412 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -989,6 +989,8 @@ mwifiex_config_scan(struct mwifiex_private *priv,
 			*max_chan_per_scan = 2;
 		else if (chan_num < MWIFIEX_LIMIT_3_CHANNELS_PER_SCAN_CMD)
 			*max_chan_per_scan = 3;
+		else
+			*max_chan_per_scan = 4;
 	}
 }
 
-- 
1.7.0.2


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

* [PATCH 06/16] mwifiex: improve scan delay logic during Tx traffic
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (4 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 05/16] mwifiex: update max_chan_per_scan correctly for SSID scan Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 07/16] mwifiex: update 11n status as per start_ap IE Bing Zhao
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Amitkumar Karwar <akarwar@marvell.com>

Earlier scan command was postponed by 20msec multiple times to give
preference to Tx traffic until we find empty wmm queue.

There is a corner case in which wmm queue becomes empty immediately
after processing the packet(before 20msec) and there may be next
packet coming after some time. In this case we should not resume scan
operation.

We will use new flag to check Tx traffic and resume scan operation
only if there is no traffic for 200msec.

Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/init.c |  103 ++++++++++++++++++++---------------
 drivers/net/wireless/mwifiex/main.c |    3 +
 drivers/net/wireless/mwifiex/main.h |    3 +
 3 files changed, 64 insertions(+), 45 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 21fdc6c..81fc8ed 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -64,60 +64,72 @@ static void scan_delay_timer_fn(unsigned long data)
 	struct cmd_ctrl_node *cmd_node, *tmp_node;
 	unsigned long flags;
 
-	if (!mwifiex_wmm_lists_empty(adapter)) {
-		if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
+	if (adapter->scan_delay_cnt == MWIFIEX_MAX_SCAN_DELAY_CNT) {
+		/*
+		 * Abort scan operation by cancelling all pending scan
+		 * commands
+		 */
+		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
+		list_for_each_entry_safe(cmd_node, tmp_node,
+					 &adapter->scan_pending_q, list) {
+			list_del(&cmd_node->list);
+			cmd_node->wait_q_enabled = false;
+			mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
+		}
+		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
+
+		spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
+		adapter->scan_processing = false;
+		adapter->scan_delay_cnt = 0;
+		adapter->empty_tx_q_cnt = 0;
+		spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
+
+		if (priv->user_scan_cfg) {
+			dev_dbg(priv->adapter->dev,
+				"info: %s: scan aborted\n", __func__);
+			cfg80211_scan_done(priv->scan_request, 1);
+			priv->scan_request = NULL;
+			kfree(priv->user_scan_cfg);
+			priv->user_scan_cfg = NULL;
+		}
+		goto done;
+	}
+
+	if (!atomic_read(&priv->adapter->is_tx_received)) {
+		adapter->empty_tx_q_cnt++;
+		if (adapter->empty_tx_q_cnt == MWIFIEX_MAX_EMPTY_TX_Q_CNT) {
 			/*
-			 * Abort scan operation by cancelling all pending scan
-			 * command
+			 * No Tx traffic for 200msec. Get scan command from
+			 * scan pending queue and put to cmd pending queue to
+			 * resume scan operation
 			 */
+			adapter->scan_delay_cnt = 0;
+			adapter->empty_tx_q_cnt = 0;
 			spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-			list_for_each_entry_safe(cmd_node, tmp_node,
-						 &adapter->scan_pending_q,
-						 list) {
-				list_del(&cmd_node->list);
-				cmd_node->wait_q_enabled = false;
-				mwifiex_insert_cmd_to_free_q(adapter, cmd_node);
-			}
+			cmd_node = list_first_entry(&adapter->scan_pending_q,
+						    struct cmd_ctrl_node, list);
+			list_del(&cmd_node->list);
 			spin_unlock_irqrestore(&adapter->scan_pending_q_lock,
 					       flags);
 
-			spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
-			adapter->scan_processing = false;
-			spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock,
-					       flags);
-
-			if (priv->user_scan_cfg) {
-				dev_dbg(priv->adapter->dev,
-					"info: %s: scan aborted\n", __func__);
-				cfg80211_scan_done(priv->scan_request, 1);
-				priv->scan_request = NULL;
-				kfree(priv->user_scan_cfg);
-				priv->user_scan_cfg = NULL;
-			}
-		} else {
-			/*
-			 * Tx data queue is still not empty, delay scan
-			 * operation further by 20msec.
-			 */
-			mod_timer(&priv->scan_delay_timer, jiffies +
-				  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
-			adapter->scan_delay_cnt++;
+			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node,
+							true);
+			goto done;
 		}
-		queue_work(priv->adapter->workqueue, &priv->adapter->main_work);
 	} else {
-		/*
-		 * Tx data queue is empty. Get scan command from scan_pending_q
-		 * and put to cmd_pending_q to resume scan operation
-		 */
-		adapter->scan_delay_cnt = 0;
-		spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
-		cmd_node = list_first_entry(&adapter->scan_pending_q,
-					    struct cmd_ctrl_node, list);
-		list_del(&cmd_node->list);
-		spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags);
-
-		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
+		adapter->empty_tx_q_cnt = 0;
 	}
+
+	/* Delay scan operation further by 20msec */
+	mod_timer(&priv->scan_delay_timer, jiffies +
+		  msecs_to_jiffies(MWIFIEX_SCAN_DELAY_MSEC));
+	adapter->scan_delay_cnt++;
+
+done:
+	if (atomic_read(&priv->adapter->is_tx_received))
+		atomic_set(&priv->adapter->is_tx_received, false);
+
+	return;
 }
 
 /*
@@ -345,6 +357,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
 	memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter));
 	adapter->arp_filter_size = 0;
 	adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
+	adapter->empty_tx_q_cnt = 0;
 }
 
 /*
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 4680362..cb11552 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -520,6 +520,9 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
 	mwifiex_wmm_add_buf_txqueue(priv, skb);
 	atomic_inc(&priv->adapter->tx_pending);
 
+	if (priv->adapter->scan_delay_cnt)
+		atomic_set(&priv->adapter->is_tx_received, true);
+
 	if (atomic_read(&priv->adapter->tx_pending) >= MAX_TX_PENDING) {
 		mwifiex_set_trans_start(dev);
 		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index e7c2a82..16f046a 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -88,6 +88,7 @@ enum {
 #define MWIFIEX_MAX_TOTAL_SCAN_TIME	(MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S)
 
 #define MWIFIEX_MAX_SCAN_DELAY_CNT			50
+#define MWIFIEX_MAX_EMPTY_TX_Q_CNT			10
 #define MWIFIEX_SCAN_DELAY_MSEC				20
 
 #define RSN_GTK_OUI_OFFSET				2
@@ -690,6 +691,8 @@ struct mwifiex_adapter {
 	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
 	u16 max_mgmt_ie_index;
 	u8 scan_delay_cnt;
+	u8 empty_tx_q_cnt;
+	atomic_t is_tx_received;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
-- 
1.7.0.2


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

* [PATCH 07/16] mwifiex: update 11n status as per start_ap IE
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (5 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 06/16] mwifiex: improve scan delay logic during Tx traffic Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 08/16] mwifiex: separate file for handling AP events Bing Zhao
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

If HT IE is present in beacon_data of start_ap cfg80211 handler,
enable 11n flag in AP. Disable 11n flag when stop_ap handler is
called.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/cfg80211.c |    2 ++
 drivers/net/wireless/mwifiex/init.c     |    1 +
 drivers/net/wireless/mwifiex/main.h     |    1 +
 drivers/net/wireless/mwifiex/uap_cmd.c  |    1 +
 4 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index fe42137..1f80f7e 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -906,6 +906,8 @@ static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
 	if (mwifiex_del_mgmt_ies(priv))
 		wiphy_err(wiphy, "Failed to delete mgmt IEs!\n");
 
+	priv->ap_11n_enabled = 0;
+
 	if (mwifiex_send_cmd_sync(priv, HostCmd_CMD_UAP_BSS_STOP,
 				  HostCmd_ACT_GEN_SET, 0, NULL)) {
 		wiphy_err(wiphy, "Failed to stop the BSS\n");
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 81fc8ed..118a29f 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -208,6 +208,7 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
 	priv->curr_bcn_size = 0;
 	priv->wps_ie = NULL;
 	priv->wps_ie_len = 0;
+	priv->ap_11n_enabled = 0;
 
 	priv->scan_block = false;
 
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 16f046a..5eeb17c 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -487,6 +487,7 @@ struct mwifiex_private {
 	u16 assocresp_idx;
 	u16 rsn_idx;
 	struct timer_list scan_delay_timer;
+	u8 ap_11n_enabled;
 };
 
 enum mwifiex_ba_status {
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c
index f40e93f..c10aac0 100644
--- a/drivers/net/wireless/mwifiex/uap_cmd.c
+++ b/drivers/net/wireless/mwifiex/uap_cmd.c
@@ -167,6 +167,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv,
 	if (ht_ie) {
 		memcpy(&bss_cfg->ht_cap, ht_ie + 2,
 		       sizeof(struct ieee80211_ht_cap));
+		priv->ap_11n_enabled = 1;
 	} else {
 		memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap));
 		bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP);
-- 
1.7.0.2


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

* [PATCH 08/16] mwifiex: separate file for handling AP events
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (6 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 07/16] mwifiex: update 11n status as per start_ap IE Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 09/16] mwifiex: create list for associated stations in AP mode Bing Zhao
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

Route AP events handling to separate function defined in
uap_event.c.
AP specific event handling is removed from sta_event.c.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/Makefile    |    1 +
 drivers/net/wireless/mwifiex/cmdevt.c    |    5 +-
 drivers/net/wireless/mwifiex/main.h      |    1 +
 drivers/net/wireless/mwifiex/sta_event.c |   49 +--------------
 drivers/net/wireless/mwifiex/uap_event.c |  100 ++++++++++++++++++++++++++++++
 5 files changed, 107 insertions(+), 49 deletions(-)
 create mode 100644 drivers/net/wireless/mwifiex/uap_event.c

diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 3f66ebb..20932f2 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -33,6 +33,7 @@ mwifiex-y += uap_cmd.o
 mwifiex-y += ie.o
 mwifiex-y += sta_cmdresp.o
 mwifiex-y += sta_event.o
+mwifiex-y += uap_event.o
 mwifiex-y += sta_tx.o
 mwifiex-y += sta_rx.o
 mwifiex-y += cfg80211.o
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index c68adec..c229ddd 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -447,7 +447,10 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
 			priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY);
 	}
 
-	ret = mwifiex_process_sta_event(priv);
+	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+		ret = mwifiex_process_uap_event(priv);
+	else
+		ret = mwifiex_process_sta_event(priv);
 
 	adapter->event_cause = 0;
 	adapter->event_skb = NULL;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 5eeb17c..cac0c2d 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -785,6 +785,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
 int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
 				  struct sk_buff *skb);
 int mwifiex_process_sta_event(struct mwifiex_private *);
+int mwifiex_process_uap_event(struct mwifiex_private *);
 void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
 int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index b8614a8..2aad148 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -184,10 +184,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
 int mwifiex_process_sta_event(struct mwifiex_private *priv)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
-	int len, ret = 0;
+	int ret = 0;
 	u32 eventcause = adapter->event_cause;
-	struct station_info sinfo;
-	struct mwifiex_assoc_event *event;
 
 	switch (eventcause) {
 	case EVENT_DUMMY_HOST_WAKEUP_SIGNAL:
@@ -405,51 +403,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
 		dev_dbg(adapter->dev, "event: HOSTWAKE_STAIE %d\n", eventcause);
 		break;
 
-	case EVENT_UAP_STA_ASSOC:
-		memset(&sinfo, 0, sizeof(sinfo));
-		event = (struct mwifiex_assoc_event *)
-			(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
-		if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
-			len = -1;
-
-			if (ieee80211_is_assoc_req(event->frame_control))
-				len = 0;
-			else if (ieee80211_is_reassoc_req(event->frame_control))
-				/* There will be ETH_ALEN bytes of
-				 * current_ap_addr before the re-assoc ies.
-				 */
-				len = ETH_ALEN;
-
-			if (len != -1) {
-				sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
-				sinfo.assoc_req_ies = &event->data[len];
-				len = (u8 *)sinfo.assoc_req_ies -
-				      (u8 *)&event->frame_control;
-				sinfo.assoc_req_ies_len =
-					le16_to_cpu(event->len) - (u16)len;
-			}
-		}
-		cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
-				 GFP_KERNEL);
-		break;
-	case EVENT_UAP_STA_DEAUTH:
-		cfg80211_del_sta(priv->netdev, adapter->event_body +
-				 MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL);
-		break;
-	case EVENT_UAP_BSS_IDLE:
-		priv->media_connected = false;
-		break;
-	case EVENT_UAP_BSS_ACTIVE:
-		priv->media_connected = true;
-		break;
-	case EVENT_UAP_BSS_START:
-		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
-		memcpy(priv->netdev->dev_addr, adapter->event_body+2, ETH_ALEN);
-		break;
-	case EVENT_UAP_MIC_COUNTERMEASURES:
-		/* For future development */
-		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
-		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
new file mode 100644
index 0000000..5af60d8
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -0,0 +1,100 @@
+/*
+ * Marvell Wireless LAN device driver: AP event handling
+ *
+ * Copyright (C) 2012, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "main.h"
+
+/*
+ * This function handles AP interface specific events generated by firmware.
+ *
+ * Event specific routines are called by this function based
+ * upon the generated event cause.
+ *
+ *
+ * Events supported for AP -
+ *      - EVENT_UAP_STA_ASSOC
+ *      - EVENT_UAP_STA_DEAUTH
+ *      - EVENT_UAP_BSS_ACTIVE
+ *      - EVENT_UAP_BSS_START
+ *      - EVENT_UAP_BSS_IDLE
+ *      - EVENT_UAP_MIC_COUNTERMEASURES:
+ */
+int mwifiex_process_uap_event(struct mwifiex_private *priv)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	int len;
+	u32 eventcause = adapter->event_cause;
+	struct station_info sinfo;
+	struct mwifiex_assoc_event *event;
+
+	switch (eventcause) {
+	case EVENT_UAP_STA_ASSOC:
+		memset(&sinfo, 0, sizeof(sinfo));
+		event = (struct mwifiex_assoc_event *)
+			(adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER);
+		if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) {
+			len = -1;
+
+			if (ieee80211_is_assoc_req(event->frame_control))
+				len = 0;
+			else if (ieee80211_is_reassoc_req(event->frame_control))
+				/* There will be ETH_ALEN bytes of
+				 * current_ap_addr before the re-assoc ies.
+				 */
+				len = ETH_ALEN;
+
+			if (len != -1) {
+				sinfo.filled = STATION_INFO_ASSOC_REQ_IES;
+				sinfo.assoc_req_ies = &event->data[len];
+				len = (u8 *)sinfo.assoc_req_ies -
+				      (u8 *)&event->frame_control;
+				sinfo.assoc_req_ies_len =
+					le16_to_cpu(event->len) - (u16)len;
+			}
+		}
+		cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
+				 GFP_KERNEL);
+		break;
+	case EVENT_UAP_STA_DEAUTH:
+		cfg80211_del_sta(priv->netdev, adapter->event_body +
+				 MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL);
+		break;
+	case EVENT_UAP_BSS_IDLE:
+		priv->media_connected = false;
+		break;
+	case EVENT_UAP_BSS_ACTIVE:
+		priv->media_connected = true;
+		break;
+	case EVENT_UAP_BSS_START:
+		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
+		memcpy(priv->netdev->dev_addr, adapter->event_body + 2,
+		       ETH_ALEN);
+		break;
+	case EVENT_UAP_MIC_COUNTERMEASURES:
+		/* For future development */
+		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
+		break;
+	default:
+		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
+			eventcause);
+		break;
+	}
+
+	return 0;
+}
-- 
1.7.0.2


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

* [PATCH 09/16] mwifiex: create list for associated stations in AP mode
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (7 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 08/16] mwifiex: separate file for handling AP events Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 10/16] mwifiex: improve uAP RX handling Bing Zhao
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

After station is associated an entry would be added to station
list. This entry would have station specific information such as
11n support, AMSDU size. The entry would be deleted after
deauthentication. All station entries would be deleted during
BSS_IDLE event.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/init.c      |    3 +
 drivers/net/wireless/mwifiex/main.h      |   19 ++++
 drivers/net/wireless/mwifiex/uap_event.c |  158 +++++++++++++++++++++++++++++-
 3 files changed, 177 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 118a29f..fad2c8d 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -424,6 +424,7 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter)
 				list_del(&priv->wmm.tid_tbl_ptr[j].ra_list);
 			list_del(&priv->tx_ba_stream_tbl_ptr);
 			list_del(&priv->rx_reorder_tbl_ptr);
+			list_del(&priv->sta_list);
 		}
 	}
 }
@@ -486,6 +487,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
 			spin_lock_init(&priv->rx_pkt_lock);
 			spin_lock_init(&priv->wmm.ra_list_spinlock);
 			spin_lock_init(&priv->curr_bcn_buf_lock);
+			spin_lock_init(&priv->sta_list_spinlock);
 		}
 	}
 
@@ -518,6 +520,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter)
 		}
 		INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr);
 		INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr);
+		INIT_LIST_HEAD(&priv->sta_list);
 
 		spin_lock_init(&priv->tx_ba_stream_tbl_lock);
 		spin_lock_init(&priv->rx_reorder_tbl_lock);
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index cac0c2d..9a0174d 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -432,6 +432,9 @@ struct mwifiex_private {
 	u8 wmm_enabled;
 	u8 wmm_qosinfo;
 	struct mwifiex_wmm_desc wmm;
+	struct list_head sta_list;
+	/* spin lock for associated station list */
+	spinlock_t sta_list_spinlock;
 	struct list_head tx_ba_stream_tbl_ptr;
 	/* spin lock for tx_ba_stream_tbl_ptr queue */
 	spinlock_t tx_ba_stream_tbl_lock;
@@ -552,6 +555,19 @@ struct mwifiex_bss_priv {
 	u64 fw_tsf;
 };
 
+/* This is AP specific structure which stores information
+ * about associated STA
+ */
+struct mwifiex_sta_node {
+	struct list_head list;
+	u8 mac_addr[ETH_ALEN];
+	u8 is_wmm_enabled;
+	u8 is_11n_enabled;
+	u8 ampdu_sta[MAX_NUM_TID];
+	u16 rx_seq[MAX_NUM_TID];
+	u16 max_amsdu;
+};
+
 struct mwifiex_if_ops {
 	int (*init_if) (struct mwifiex_adapter *);
 	void (*cleanup_if) (struct mwifiex_adapter *);
@@ -786,6 +802,9 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
 				  struct sk_buff *skb);
 int mwifiex_process_sta_event(struct mwifiex_private *);
 int mwifiex_process_uap_event(struct mwifiex_private *);
+struct mwifiex_sta_node *
+mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
+void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
 void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
 int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta);
 int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 5af60d8..37cc642 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -21,6 +21,130 @@
 #include "main.h"
 
 /*
+ * This function will return the pointer to station entry in station list
+ * table which matches specified mac address.
+ * This function should be called after acquiring RA list spinlock.
+ * NULL is returned if station entry is not found in associated STA list.
+ */
+struct mwifiex_sta_node *
+mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *node;
+
+	if (!mac)
+		return NULL;
+
+	list_for_each_entry(node, &priv->sta_list, list) {
+		if (!memcmp(node->mac_addr, mac, ETH_ALEN))
+			return node;
+	}
+
+	return NULL;
+}
+
+/*
+ * This function will add a sta_node entry to associated station list
+ * table with the given mac address.
+ * If entry exist already, existing entry is returned.
+ * If received mac address is NULL, NULL is returned.
+ */
+static struct mwifiex_sta_node *
+mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *node;
+	unsigned long flags;
+
+	if (!mac)
+		return NULL;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+	node = mwifiex_get_sta_entry(priv, mac);
+	if (node)
+		goto done;
+
+	node = kzalloc(sizeof(struct mwifiex_sta_node), GFP_KERNEL);
+	if (!node)
+		goto done;
+
+	memcpy(node->mac_addr, mac, ETH_ALEN);
+	list_add_tail(&node->list, &priv->sta_list);
+
+done:
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+	return node;
+}
+
+/*
+ * This function will search for HT IE in association request IEs
+ * and set station HT parameters accordingly.
+ */
+static void
+mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
+		       int ies_len, struct mwifiex_sta_node *node)
+{
+	const struct ieee80211_ht_cap *ht_cap;
+
+	if (!ies)
+		return;
+
+	ht_cap = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, ies_len);
+	if (ht_cap) {
+		node->is_11n_enabled = 1;
+		node->max_amsdu = le16_to_cpu(ht_cap->cap_info) &
+				  IEEE80211_HT_CAP_MAX_AMSDU ?
+				  MWIFIEX_TX_DATA_BUF_SIZE_8K :
+				  MWIFIEX_TX_DATA_BUF_SIZE_4K;
+	} else {
+		node->is_11n_enabled = 0;
+	}
+
+	return;
+}
+
+/*
+ * This function will delete a station entry from station list
+ */
+static void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
+{
+	struct mwifiex_sta_node *node, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+
+	node = mwifiex_get_sta_entry(priv, mac);
+	if (node) {
+		list_for_each_entry_safe(node, tmp, &priv->sta_list,
+					 list) {
+			list_del(&node->list);
+			kfree(node);
+		}
+	}
+
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+	return;
+}
+
+/*
+ * This function will delete all stations from associated station list.
+ */
+static void mwifiex_del_all_sta_list(struct mwifiex_private *priv)
+{
+	struct mwifiex_sta_node *node, *tmp;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+
+	list_for_each_entry_safe(node, tmp, &priv->sta_list, list) {
+		list_del(&node->list);
+		kfree(node);
+	}
+
+	INIT_LIST_HEAD(&priv->sta_list);
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
+	return;
+}
+
+/*
  * This function handles AP interface specific events generated by firmware.
  *
  * Event specific routines are called by this function based
@@ -38,10 +162,12 @@
 int mwifiex_process_uap_event(struct mwifiex_private *priv)
 {
 	struct mwifiex_adapter *adapter = priv->adapter;
-	int len;
+	int len, i;
 	u32 eventcause = adapter->event_cause;
 	struct station_info sinfo;
 	struct mwifiex_assoc_event *event;
+	struct mwifiex_sta_node *node;
+	u8 *deauth_mac;
 
 	switch (eventcause) {
 	case EVENT_UAP_STA_ASSOC:
@@ -70,13 +196,39 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 		}
 		cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo,
 				 GFP_KERNEL);
+
+		node = mwifiex_add_sta_entry(priv, event->sta_addr);
+		if (!node) {
+			dev_warn(adapter->dev,
+				 "could not create station entry!\n");
+			return -1;
+		}
+
+		if (!priv->ap_11n_enabled)
+			break;
+
+		mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies,
+				       sinfo.assoc_req_ies_len, node);
+
+		for (i = 0; i < MAX_NUM_TID; i++) {
+			if (node->is_11n_enabled)
+				node->ampdu_sta[i] =
+					      priv->aggr_prio_tbl[i].ampdu_user;
+			else
+				node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED;
+		}
+		memset(node->rx_seq, 0xff, sizeof(node->rx_seq));
 		break;
 	case EVENT_UAP_STA_DEAUTH:
-		cfg80211_del_sta(priv->netdev, adapter->event_body +
-				 MWIFIEX_UAP_EVENT_EXTRA_HEADER, GFP_KERNEL);
+		deauth_mac = adapter->event_body +
+			     MWIFIEX_UAP_EVENT_EXTRA_HEADER;
+		cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
+
+		mwifiex_del_sta_entry(priv, deauth_mac);
 		break;
 	case EVENT_UAP_BSS_IDLE:
 		priv->media_connected = false;
+		mwifiex_del_all_sta_list(priv);
 		break;
 	case EVENT_UAP_BSS_ACTIVE:
 		priv->media_connected = true;
-- 
1.7.0.2


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

* [PATCH 10/16] mwifiex: improve uAP RX handling
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (8 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 09/16] mwifiex: create list for associated stations in AP mode Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 11/16] mwifiex: support RX AMSDU aggregation for uAP Bing Zhao
                   ` (5 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

1. Separate file for uAP RX handling.
2. If received packet is broadcast/multicast, send it to kernel
   as well as requeue it back to uAP TX queue.
3. If received packet is for associated STA (intra-BSS), requeue
   it back to uAP TX queue.
4. In all other cases (packets for AP or inter-BSS packets),
   pass packet to kernel to handle it accordingly.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/Makefile   |    1 +
 drivers/net/wireless/mwifiex/decl.h     |    3 +
 drivers/net/wireless/mwifiex/fw.h       |   25 ++++
 drivers/net/wireless/mwifiex/main.h     |    5 +
 drivers/net/wireless/mwifiex/txrx.c     |    5 +
 drivers/net/wireless/mwifiex/uap_txrx.c |  205 +++++++++++++++++++++++++++++++
 6 files changed, 244 insertions(+), 0 deletions(-)
 create mode 100644 drivers/net/wireless/mwifiex/uap_txrx.c

diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile
index 20932f2..dd0410d 100644
--- a/drivers/net/wireless/mwifiex/Makefile
+++ b/drivers/net/wireless/mwifiex/Makefile
@@ -36,6 +36,7 @@ mwifiex-y += sta_event.o
 mwifiex-y += uap_event.o
 mwifiex-y += sta_tx.o
 mwifiex-y += sta_rx.o
+mwifiex-y += uap_txrx.o
 mwifiex-y += cfg80211.o
 mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o
 obj-$(CONFIG_MWIFIEX) += mwifiex.o
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h
index 070ef25..400d360 100644
--- a/drivers/net/wireless/mwifiex/decl.h
+++ b/drivers/net/wireless/mwifiex/decl.h
@@ -60,6 +60,9 @@
 #define MWIFIEX_SDIO_BLOCK_SIZE            256
 
 #define MWIFIEX_BUF_FLAG_REQUEUED_PKT      BIT(0)
+#define MWIFIEX_BUF_FLAG_BRIDGED_PKT	   BIT(1)
+
+#define MWIFIEX_BRIDGED_PKTS_THRESHOLD     1024
 
 enum mwifiex_bss_type {
 	MWIFIEX_BSS_TYPE_STA = 0,
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index a0222ec..1c1274d 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -439,6 +439,31 @@ struct rxpd {
 	u8 reserved;
 } __packed;
 
+struct uap_txpd {
+	u8 bss_type;
+	u8 bss_num;
+	__le16 tx_pkt_length;
+	__le16 tx_pkt_offset;
+	__le16 tx_pkt_type;
+	__le32 tx_control;
+	u8 priority;
+	u8 flags;
+	u8 pkt_delay_2ms;
+	u8 reserved1;
+	__le32 reserved2;
+};
+
+struct uap_rxpd {
+	u8 bss_type;
+	u8 bss_num;
+	__le16 rx_pkt_length;
+	__le16 rx_pkt_offset;
+	__le16 rx_pkt_type;
+	__le16 seq_num;
+	u8 priority;
+	u8 reserved1;
+};
+
 enum mwifiex_chan_scan_mode_bitmasks {
 	MWIFIEX_PASSIVE_SCAN = BIT(0),
 	MWIFIEX_DISABLE_CHAN_FILT = BIT(1),
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 9a0174d..014fe9a 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -710,6 +710,7 @@ struct mwifiex_adapter {
 	u8 scan_delay_cnt;
 	u8 empty_tx_q_cnt;
 	atomic_t is_tx_received;
+	atomic_t pending_bridged_pkts;
 };
 
 int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -800,6 +801,10 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no,
 				struct host_cmd_ds_command *resp);
 int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *,
 				  struct sk_buff *skb);
+int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
+				  struct sk_buff *skb);
+int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
+				  struct sk_buff *skb);
 int mwifiex_process_sta_event(struct mwifiex_private *);
 int mwifiex_process_uap_event(struct mwifiex_private *);
 struct mwifiex_sta_node *
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index cecb272..985073d 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -51,6 +51,9 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
 	rx_info->bss_num = priv->bss_num;
 	rx_info->bss_type = priv->bss_type;
 
+	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+		return mwifiex_process_uap_rx_packet(adapter, skb);
+
 	return mwifiex_process_sta_rx_packet(adapter, skb);
 }
 EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet);
@@ -157,6 +160,8 @@ int mwifiex_write_data_complete(struct mwifiex_adapter *adapter,
 		priv->stats.tx_errors++;
 	}
 
+	if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT)
+		atomic_dec_return(&adapter->pending_bridged_pkts);
 	if (atomic_dec_return(&adapter->tx_pending) >= LOW_TX_PENDING)
 		goto done;
 
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
new file mode 100644
index 0000000..f55c5ac
--- /dev/null
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -0,0 +1,205 @@
+/*
+ * Marvell Wireless LAN device driver: AP TX and RX data handling
+ *
+ * Copyright (C) 2012, Marvell International Ltd.
+ *
+ * This software file (the "File") is distributed by Marvell International
+ * Ltd. under the terms of the GNU General Public License Version 2, June 1991
+ * (the "License").  You may use, redistribute and/or modify this File in
+ * accordance with the terms and conditions of the License, a copy of which
+ * is available by writing to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
+ * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
+ *
+ * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
+ * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
+ * this warranty disclaimer.
+ */
+
+#include "decl.h"
+#include "ioctl.h"
+#include "main.h"
+#include "wmm.h"
+
+static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
+					 struct sk_buff *skb)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct uap_rxpd *uap_rx_pd;
+	struct rx_packet_hdr *rx_pkt_hdr;
+	struct sk_buff *new_skb;
+	struct mwifiex_txinfo *tx_info;
+	int hdr_chop;
+	struct timeval tv;
+	u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
+
+	uap_rx_pd = (struct uap_rxpd *)(skb->data);
+	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+
+	if ((atomic_read(&adapter->pending_bridged_pkts) >=
+					     MWIFIEX_BRIDGED_PKTS_THRESHOLD)) {
+		dev_err(priv->adapter->dev,
+			"Tx: Bridge packet limit reached. Drop packet!\n");
+		kfree_skb(skb);
+		return;
+	}
+
+	if (!memcmp(&rx_pkt_hdr->rfc1042_hdr,
+		    rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)))
+		/* Chop off the rxpd + the excess memory from
+		 * 802.2/llc/snap header that was removed.
+		 */
+		hdr_chop = (u8 *)eth_hdr - (u8 *)uap_rx_pd;
+	else
+		/* Chop off the rxpd */
+		hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd;
+
+	/* Chop off the leading header bytes so the it points
+	 * to the start of either the reconstructed EthII frame
+	 * or the 802.2/llc/snap frame.
+	 */
+	skb_pull(skb, hdr_chop);
+
+	if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) {
+		dev_dbg(priv->adapter->dev,
+			"data: Tx: insufficient skb headroom %d\n",
+			skb_headroom(skb));
+		/* Insufficient skb headroom - allocate a new skb */
+		new_skb =
+			skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN);
+		if (unlikely(!new_skb)) {
+			dev_err(priv->adapter->dev,
+				"Tx: cannot allocate new_skb\n");
+			kfree_skb(skb);
+			priv->stats.tx_dropped++;
+			return;
+		}
+
+		kfree_skb(skb);
+		skb = new_skb;
+		dev_dbg(priv->adapter->dev, "info: new skb headroom %d\n",
+			skb_headroom(skb));
+	}
+
+	tx_info = MWIFIEX_SKB_TXCB(skb);
+	tx_info->bss_num = priv->bss_num;
+	tx_info->bss_type = priv->bss_type;
+	tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT;
+
+	do_gettimeofday(&tv);
+	skb->tstamp = timeval_to_ktime(tv);
+	mwifiex_wmm_add_buf_txqueue(priv, skb);
+	atomic_inc(&adapter->tx_pending);
+	atomic_inc(&adapter->pending_bridged_pkts);
+
+	if ((atomic_read(&adapter->tx_pending) >= MAX_TX_PENDING)) {
+		mwifiex_set_trans_start(priv->netdev);
+		mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter);
+	}
+	return;
+}
+
+/*
+ * This function contains logic for AP packet forwarding.
+ *
+ * If a packet is multicast/broadcast, it is sent to kernel/upper layer
+ * as well as queued back to AP TX queue so that it can be sent to other
+ * associated stations.
+ * If a packet is unicast and RA is present in associated station list,
+ * it is again requeued into AP TX queue.
+ * If a packet is unicast and RA is not in associated station list,
+ * packet is forwarded to kernel to handle routing logic.
+ */
+int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv,
+				  struct sk_buff *skb)
+{
+	struct mwifiex_adapter *adapter = priv->adapter;
+	struct uap_rxpd *uap_rx_pd;
+	struct rx_packet_hdr *rx_pkt_hdr;
+	u8 ra[ETH_ALEN];
+	struct sk_buff *skb_uap;
+
+	uap_rx_pd = (struct uap_rxpd *)(skb->data);
+	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+
+	/* don't do packet forwarding in disconnected state */
+	if (!priv->media_connected) {
+		dev_err(adapter->dev, "drop packet in disconnected state.\n");
+		dev_kfree_skb_any(skb);
+		return 0;
+	}
+
+	memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN);
+
+	if (is_multicast_ether_addr(ra)) {
+		skb_uap = skb_copy(skb, GFP_ATOMIC);
+		mwifiex_uap_queue_bridged_pkt(priv, skb_uap);
+	} else {
+		if (mwifiex_get_sta_entry(priv, ra)) {
+			/* Requeue Intra-BSS packet */
+			mwifiex_uap_queue_bridged_pkt(priv, skb);
+			return 0;
+		}
+	}
+
+	/* Forward unicat/Inter-BSS packets to kernel. */
+	return mwifiex_process_rx_packet(adapter, skb);
+}
+
+/*
+ * This function processes the packet received on AP interface.
+ *
+ * The function looks into the RxPD and performs sanity tests on the
+ * received buffer to ensure its a valid packet before processing it
+ * further. If the packet is determined to be aggregated, it is
+ * de-aggregated accordingly. Then skb is passed to AP packet forwarding logic.
+ *
+ * The completion callback is called after processing is complete.
+ */
+int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
+				  struct sk_buff *skb)
+{
+	int ret;
+	struct uap_rxpd *uap_rx_pd;
+	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
+	struct rx_packet_hdr *rx_pkt_hdr;
+	u16 rx_pkt_type;
+	struct mwifiex_private *priv =
+			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
+					       rx_info->bss_type);
+
+	if (!priv)
+		return -1;
+
+	uap_rx_pd = (struct uap_rxpd *)(skb->data);
+	rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type);
+	rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset);
+
+	if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) +
+	     le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) {
+		dev_err(adapter->dev,
+			"wrong rx packet: len=%d, offset=%d, length=%d\n",
+			skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset),
+			le16_to_cpu(uap_rx_pd->rx_pkt_length));
+		priv->stats.rx_dropped++;
+
+		if (adapter->if_ops.data_complete)
+			adapter->if_ops.data_complete(adapter, skb);
+		else
+			dev_kfree_skb_any(skb);
+
+		return 0;
+	}
+	ret = mwifiex_handle_uap_rx_forward(priv, skb);
+
+	if (ret) {
+		priv->stats.rx_dropped++;
+		if (adapter->if_ops.data_complete)
+			adapter->if_ops.data_complete(adapter, skb);
+		else
+			dev_kfree_skb_any(skb);
+	}
+
+	return ret;
+}
-- 
1.7.0.2


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

* [PATCH 11/16] mwifiex: support RX AMSDU aggregation for uAP
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (9 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 10/16] mwifiex: improve uAP RX handling Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 12/16] mwifiex: add 11n Block Ack support " Bing Zhao
                   ` (4 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

This patch adds support for reception and decoding of AMSDU
aggregation frames for AP interface.
Patch also adds support for handling AMSDU aggregation event.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/11n_rxreorder.c |   26 +++++++++---
 drivers/net/wireless/mwifiex/11n_rxreorder.h |    2 +
 drivers/net/wireless/mwifiex/uap_event.c     |   13 ++++++
 drivers/net/wireless/mwifiex/uap_txrx.c      |   56 ++++++++++++++++++++++++-
 4 files changed, 88 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 591ccd3..20367fe 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -54,8 +54,13 @@ mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv,
 			tbl->rx_reorder_ptr[i] = NULL;
 		}
 		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-		if (rx_tmp_ptr)
-			mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
+		if (rx_tmp_ptr) {
+			if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+				mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
+			else
+				mwifiex_process_rx_packet(priv->adapter,
+							  rx_tmp_ptr);
+		}
 	}
 
 	spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -97,7 +102,11 @@ mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv,
 		rx_tmp_ptr = tbl->rx_reorder_ptr[i];
 		tbl->rx_reorder_ptr[i] = NULL;
 		spin_unlock_irqrestore(&priv->rx_pkt_lock, flags);
-		mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
+
+		if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+			mwifiex_handle_uap_rx_forward(priv, rx_tmp_ptr);
+		else
+			mwifiex_process_rx_packet(priv->adapter, rx_tmp_ptr);
 	}
 
 	spin_lock_irqsave(&priv->rx_pkt_lock, flags);
@@ -148,7 +157,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv,
  * This function returns the pointer to an entry in Rx reordering
  * table which matches the given TA/TID pair.
  */
-static struct mwifiex_rx_reorder_tbl *
+struct mwifiex_rx_reorder_tbl *
 mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
 {
 	struct mwifiex_rx_reorder_tbl *tbl;
@@ -396,8 +405,13 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv,
 
 	tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta);
 	if (!tbl) {
-		if (pkt_type != PKT_TYPE_BAR)
-			mwifiex_process_rx_packet(priv->adapter, payload);
+		if (pkt_type != PKT_TYPE_BAR) {
+			if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP)
+				mwifiex_handle_uap_rx_forward(priv, payload);
+			else
+				mwifiex_process_rx_packet(priv->adapter,
+							  payload);
+		}
 		return 0;
 	}
 	start_win = tbl->start_win;
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 6c9815a..1cd51d8 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -68,5 +68,7 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
 							   mwifiex_private
 							   *priv, int tid,
 							   u8 *ta);
+struct mwifiex_rx_reorder_tbl *
+mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
 
 #endif /* _MWIFIEX_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 37cc642..6270c80 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -242,6 +242,19 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 		/* For future development */
 		dev_dbg(adapter->dev, "AP EVENT: event id: %#x\n", eventcause);
 		break;
+	case EVENT_AMSDU_AGGR_CTRL:
+		dev_dbg(adapter->dev, "event:  AMSDU_AGGR_CTRL %d\n",
+			*(u16 *)adapter->event_body);
+
+		if (priv->media_connected) {
+			adapter->tx_buf_size =
+			       min(adapter->curr_tx_buf_size,
+				   le16_to_cpu(*(__le16 *)adapter->event_body));
+
+			dev_dbg(adapter->dev, "event: tx_buf_size %d\n",
+				adapter->tx_buf_size);
+		}
+		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index f55c5ac..6d814f0 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -21,6 +21,8 @@
 #include "ioctl.h"
 #include "main.h"
 #include "wmm.h"
+#include "11n_aggr.h"
+#include "11n_rxreorder.h"
 
 static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
 					 struct sk_buff *skb)
@@ -165,6 +167,9 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
 	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
 	struct rx_packet_hdr *rx_pkt_hdr;
 	u16 rx_pkt_type;
+	u8 ta[ETH_ALEN], pkt_type;
+	struct mwifiex_sta_node *node;
+
 	struct mwifiex_private *priv =
 			mwifiex_get_priv_by_id(adapter, rx_info->bss_num,
 					       rx_info->bss_type);
@@ -191,15 +196,60 @@ int mwifiex_process_uap_rx_packet(struct mwifiex_adapter *adapter,
 
 		return 0;
 	}
-	ret = mwifiex_handle_uap_rx_forward(priv, skb);
 
-	if (ret) {
-		priv->stats.rx_dropped++;
+	if (le16_to_cpu(uap_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) {
+		struct sk_buff_head list;
+		struct sk_buff *rx_skb;
+
+		__skb_queue_head_init(&list);
+		skb_pull(skb, le16_to_cpu(uap_rx_pd->rx_pkt_offset));
+		skb_trim(skb, le16_to_cpu(uap_rx_pd->rx_pkt_length));
+
+		ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr,
+					 priv->wdev->iftype, 0, false);
+
+		while (!skb_queue_empty(&list)) {
+			rx_skb = __skb_dequeue(&list);
+			ret = mwifiex_recv_packet(adapter, rx_skb);
+			if (ret)
+				dev_err(adapter->dev,
+					"AP:Rx A-MSDU failed");
+		}
+
+		return 0;
+	}
+
+	memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN);
+
+	if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) {
+		node = mwifiex_get_sta_entry(priv, ta);
+		if (node)
+			node->rx_seq[uap_rx_pd->priority] =
+						le16_to_cpu(uap_rx_pd->seq_num);
+	}
+
+	if (!priv->ap_11n_enabled ||
+	    (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) &&
+	    (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) {
+		ret = mwifiex_handle_uap_rx_forward(priv, skb);
+		return ret;
+	}
+
+	/* Reorder and send to kernel */
+	pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type);
+	ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num),
+					 uap_rx_pd->priority, ta, pkt_type,
+					 skb);
+
+	if (ret || (rx_pkt_type == PKT_TYPE_BAR)) {
 		if (adapter->if_ops.data_complete)
 			adapter->if_ops.data_complete(adapter, skb);
 		else
 			dev_kfree_skb_any(skb);
 	}
 
+	if (ret)
+		priv->stats.rx_dropped++;
+
 	return ret;
 }
-- 
1.7.0.2


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

* [PATCH 12/16] mwifiex: add 11n Block Ack support for uAP
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (10 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 11/16] mwifiex: support RX AMSDU aggregation for uAP Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 13/16] mwifiex: cleanup TX/RX BA tables " Bing Zhao
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

This patch adds support for handling BA request and BA setup
events for AP interface.

RA list is marked as either 11n enabled or disabled from station's
capabilities in association request. BA setup is initiated only
after some specific number of packets for particular RA list are
transmitted.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/11n.h           |   14 ++++++
 drivers/net/wireless/mwifiex/11n_rxreorder.c |   15 +++++--
 drivers/net/wireless/mwifiex/11n_rxreorder.h |    2 +
 drivers/net/wireless/mwifiex/main.h          |    3 +
 drivers/net/wireless/mwifiex/uap_event.c     |   21 +++++++++
 drivers/net/wireless/mwifiex/wmm.c           |   59 +++++++++++++++++++++++--
 6 files changed, 105 insertions(+), 9 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 28366e9..6d2edb4 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -157,4 +157,18 @@ mwifiex_is_ba_stream_setup(struct mwifiex_private *priv,
 
 	return false;
 }
+
+/*
+ * This function checks whether associated station is 11n enabled
+ */
+static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
+					     struct mwifiex_sta_node *node)
+{
+
+	if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) ||
+	    !priv->ap_11n_enabled)
+		return 0;
+
+	return node->is_11n_enabled;
+}
 #endif /* !_MWIFIEX_11N_H_ */
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index 20367fe..e43d27d 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -235,6 +235,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
 	struct mwifiex_rx_reorder_tbl *tbl, *new_node;
 	u16 last_seq = 0;
 	unsigned long flags;
+	struct mwifiex_sta_node *node;
 
 	/*
 	 * If we get a TID, ta pair which is already present dispatch all the
@@ -257,13 +258,19 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta,
 	new_node->tid = tid;
 	memcpy(new_node->ta, ta, ETH_ALEN);
 	new_node->start_win = seq_num;
-	if (mwifiex_queuing_ra_based(priv))
-		/* TODO for adhoc */
+
+	if (mwifiex_queuing_ra_based(priv)) {
 		dev_dbg(priv->adapter->dev,
-			"info: ADHOC:last_seq=%d start_win=%d\n",
+			"info: AP/ADHOC:last_seq=%d start_win=%d\n",
 			last_seq, new_node->start_win);
-	else
+		if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) {
+			node = mwifiex_get_sta_entry(priv, ta);
+			if (node)
+				last_seq = node->rx_seq[tid];
+		}
+	} else {
 		last_seq = priv->rx_seq[tid];
+	}
 
 	if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM &&
 	    last_seq >= new_node->start_win)
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 1cd51d8..13ecb61 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -38,6 +38,8 @@
 #define ADDBA_RSP_STATUS_ACCEPT 0
 
 #define MWIFIEX_DEF_11N_RX_SEQ_NUM	0xffff
+#define BA_SETUP_MAX_PACKET_THRESHOLD	16
+#define BA_SETUP_PACKET_OFFSET		16
 
 static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv)
 {
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 014fe9a..c39cd8e 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -200,6 +200,9 @@ struct mwifiex_ra_list_tbl {
 	u8 ra[ETH_ALEN];
 	u32 total_pkts_size;
 	u32 is_11n_enabled;
+	u16 max_amsdu;
+	u16 pkt_count;
+	u8 ba_packet_thr;
 };
 
 struct mwifiex_tid_tbl {
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index 6270c80..a10bd95 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -19,6 +19,7 @@
 
 #include "decl.h"
 #include "main.h"
+#include "11n.h"
 
 /*
  * This function will return the pointer to station entry in station list
@@ -168,6 +169,7 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 	struct mwifiex_assoc_event *event;
 	struct mwifiex_sta_node *node;
 	u8 *deauth_mac;
+	struct host_cmd_ds_11n_batimeout *ba_timeout;
 
 	switch (eventcause) {
 	case EVENT_UAP_STA_ASSOC:
@@ -255,6 +257,25 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 				adapter->tx_buf_size);
 		}
 		break;
+	case EVENT_ADDBA:
+		dev_dbg(adapter->dev, "event: ADDBA Request\n");
+		if (priv->media_connected)
+			mwifiex_send_cmd_async(priv, HostCmd_CMD_11N_ADDBA_RSP,
+					       HostCmd_ACT_GEN_SET, 0,
+					       adapter->event_body);
+		break;
+	case EVENT_DELBA:
+		dev_dbg(adapter->dev, "event: DELBA Request\n");
+		if (priv->media_connected)
+			mwifiex_11n_delete_ba_stream(priv, adapter->event_body);
+		break;
+	case EVENT_BA_STREAM_TIEMOUT:
+		dev_dbg(adapter->dev, "event:  BA Stream timeout\n");
+		if (priv->media_connected) {
+			ba_timeout = (void *)adapter->event_body;
+			mwifiex_11n_ba_stream_timeout(priv, ba_timeout);
+		}
+		break;
 	default:
 		dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
 			eventcause);
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 3fa4d41..8ccd699 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -127,6 +127,29 @@ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
 	return ra_list;
 }
 
+/* This function returns random no between 16 and 32 to be used as threshold
+ * for no of packets after which BA setup is initiated.
+ */
+static u8 mwifiex_get_random_ba_threshold(void)
+{
+	u32 sec, usec;
+	struct timeval ba_tstamp;
+	u8 ba_threshold;
+
+	/* setup ba_packet_threshold here random number between
+	 * [BA_SETUP_PACKET_OFFSET,
+	 * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1]
+	 */
+
+	do_gettimeofday(&ba_tstamp);
+	sec = (ba_tstamp.tv_sec & 0xFFFF) + (ba_tstamp.tv_sec >> 16);
+	usec = (ba_tstamp.tv_usec & 0xFFFF) + (ba_tstamp.tv_usec >> 16);
+	ba_threshold = (((sec << 16) + usec) % BA_SETUP_MAX_PACKET_THRESHOLD)
+						      + BA_SETUP_PACKET_OFFSET;
+
+	return ba_threshold;
+}
+
 /*
  * This function allocates and adds a RA list for all TIDs
  * with the given RA.
@@ -137,6 +160,12 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
 	int i;
 	struct mwifiex_ra_list_tbl *ra_list;
 	struct mwifiex_adapter *adapter = priv->adapter;
+	struct mwifiex_sta_node *node;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_list_spinlock, flags);
+	node = mwifiex_get_sta_entry(priv, ra);
+	spin_unlock_irqrestore(&priv->sta_list_spinlock, flags);
 
 	for (i = 0; i < MAX_NUM_TID; ++i) {
 		ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra);
@@ -145,14 +174,24 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
 		if (!ra_list)
 			break;
 
-		if (!mwifiex_queuing_ra_based(priv))
+		ra_list->is_11n_enabled = 0;
+		if (!mwifiex_queuing_ra_based(priv)) {
 			ra_list->is_11n_enabled = IS_11N_ENABLED(priv);
-		else
-			ra_list->is_11n_enabled = false;
+		} else {
+			ra_list->is_11n_enabled =
+				      mwifiex_is_sta_11n_enabled(priv, node);
+			if (ra_list->is_11n_enabled)
+				ra_list->max_amsdu = node->max_amsdu;
+		}
 
 		dev_dbg(adapter->dev, "data: ralist %p: is_11n_enabled=%d\n",
 			ra_list, ra_list->is_11n_enabled);
 
+		if (ra_list->is_11n_enabled) {
+			ra_list->pkt_count = 0;
+			ra_list->ba_packet_thr =
+					      mwifiex_get_random_ba_threshold();
+		}
 		list_add_tail(&ra_list->list,
 			      &priv->wmm.tid_tbl_ptr[i].ra_list);
 
@@ -647,6 +686,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
 	skb_queue_tail(&ra_list->skb_head, skb);
 
 	ra_list->total_pkts_size += skb->len;
+	ra_list->pkt_count++;
 
 	atomic_inc(&priv->wmm.tx_pkts_queued);
 
@@ -986,10 +1026,17 @@ mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv,
 {
 	int count = 0, total_size = 0;
 	struct sk_buff *skb, *tmp;
+	int max_amsdu_size;
+
+	if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled &&
+	    ptr->is_11n_enabled)
+		max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size);
+	else
+		max_amsdu_size = max_buf_size;
 
 	skb_queue_walk_safe(&ptr->skb_head, skb, tmp) {
 		total_size += skb->len;
-		if (total_size >= max_buf_size)
+		if (total_size >= max_amsdu_size)
 			break;
 		if (++count >= MIN_NUM_AMSDU)
 			return true;
@@ -1050,6 +1097,7 @@ mwifiex_send_single_packet(struct mwifiex_private *priv,
 		skb_queue_tail(&ptr->skb_head, skb);
 
 		ptr->total_pkts_size += skb->len;
+		ptr->pkt_count++;
 		tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT;
 		spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock,
 				       ra_list_flags);
@@ -1231,7 +1279,8 @@ mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter)
 		/* ra_list_spinlock has been freed in
 		   mwifiex_send_single_packet() */
 	} else {
-		if (mwifiex_is_ampdu_allowed(priv, tid)) {
+		if (mwifiex_is_ampdu_allowed(priv, tid) &&
+		    ptr->pkt_count > ptr->ba_packet_thr) {
 			if (mwifiex_space_avail_for_new_ba_stream(adapter)) {
 				mwifiex_create_ba_tbl(priv, ptr->ra, tid,
 						      BA_SETUP_INPROGRESS);
-- 
1.7.0.2


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

* [PATCH 13/16] mwifiex: cleanup TX/RX BA tables for uAP
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (11 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 12/16] mwifiex: add 11n Block Ack support " Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 14/16] mwifiex: rename wapi_rxpn to pn Bing Zhao
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Avinash Patil <patila@marvell.com>

Cleanup TX/RX BA tables when AP receives deauthentication from
associated station. During BSS_IDLE event, all wmm queues, BA
streams created for AP interface are deleted.

Signed-off-by: Avinash Patil <patila@marvell.com>
Signed-off-by: Kiran Divekar <dkiran@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/11n.c           |   26 ++++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/11n.h           |    1 +
 drivers/net/wireless/mwifiex/11n_rxreorder.c |   25 +++++++++++++++++++++++++
 drivers/net/wireless/mwifiex/11n_rxreorder.h |    1 +
 drivers/net/wireless/mwifiex/uap_event.c     |    5 +++++
 5 files changed, 58 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index e535c93..d273273 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -726,3 +726,29 @@ int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv,
 
 	return count;
 }
+
+/*
+ * This function retrieves the entry for specific tx BA stream table by RA and
+ * deletes it.
+ */
+void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra)
+{
+	struct mwifiex_tx_ba_stream_tbl *tbl, *tmp;
+	unsigned long flags;
+
+	if (!ra)
+		return;
+
+	spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+	list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) {
+		if (!memcmp(tbl->ra, ra, ETH_ALEN)) {
+			spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock,
+					       flags);
+			mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl);
+			spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags);
+		}
+	}
+	spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags);
+
+	return;
+}
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 6d2edb4..67c087c 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -69,6 +69,7 @@ int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv,
 int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd,
 				int cmd_action,
 				struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
+void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
 
 /*
  * This function checks whether AMPDU is allowed or not for a particular TID.
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c
index e43d27d..24e2582 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.c
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c
@@ -176,6 +176,31 @@ mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta)
 	return NULL;
 }
 
+/* This function retrieves the pointer to an entry in Rx reordering
+ * table which matches the given TA and deletes it.
+ */
+void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta)
+{
+	struct mwifiex_rx_reorder_tbl *tbl, *tmp;
+	unsigned long flags;
+
+	if (!ta)
+		return;
+
+	spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+	list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) {
+		if (!memcmp(tbl->ta, ta, ETH_ALEN)) {
+			spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock,
+					       flags);
+			mwifiex_del_rx_reorder_entry(priv, tbl);
+			spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags);
+		}
+	}
+	spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags);
+
+	return;
+}
+
 /*
  * This function finds the last sequence number used in the packets
  * buffered in Rx reordering table.
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h
index 13ecb61..7284859 100644
--- a/drivers/net/wireless/mwifiex/11n_rxreorder.h
+++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h
@@ -72,5 +72,6 @@ struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct
 							   u8 *ta);
 struct mwifiex_rx_reorder_tbl *
 mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta);
+void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta);
 
 #endif /* _MWIFIEX_11N_RXREORDER_H_ */
diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c
index a10bd95..14d4f04 100644
--- a/drivers/net/wireless/mwifiex/uap_event.c
+++ b/drivers/net/wireless/mwifiex/uap_event.c
@@ -226,10 +226,15 @@ int mwifiex_process_uap_event(struct mwifiex_private *priv)
 			     MWIFIEX_UAP_EVENT_EXTRA_HEADER;
 		cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL);
 
+		if (priv->ap_11n_enabled) {
+			mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac);
+			mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac);
+		}
 		mwifiex_del_sta_entry(priv, deauth_mac);
 		break;
 	case EVENT_UAP_BSS_IDLE:
 		priv->media_connected = false;
+		mwifiex_clean_txrx(priv);
 		mwifiex_del_all_sta_list(priv);
 		break;
 	case EVENT_UAP_BSS_ACTIVE:
-- 
1.7.0.2


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

* [PATCH 14/16] mwifiex: rename wapi_rxpn to pn
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (12 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 13/16] mwifiex: cleanup TX/RX BA tables " Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 15/16] mwifiex: pass key_params pointer in mwifiex_set_encode Bing Zhao
  2012-08-04  1:06 ` [PATCH 16/16] mwifiex: add AES_CMAC support in key_material cmd Bing Zhao
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Ying Luo <luoy@marvell.com>

This array was used for wapi_rxpn only. Now it will be used for
AES_CMAC as well. So make a generic name for it.

Signed-off-by: Ying Luo <luoy@marvell.com>
Signed-off-by: Stone Piao <piaoyun@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/ioctl.h   |    4 ++--
 drivers/net/wireless/mwifiex/sta_cmd.c |    2 +-
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index 5019153..f2865b5 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -213,7 +213,7 @@ struct mwifiex_debug_info {
 };
 
 #define MWIFIEX_KEY_INDEX_UNICAST	0x40000000
-#define WAPI_RXPN_LEN			16
+#define PN_LEN				16
 
 struct mwifiex_ds_encrypt_key {
 	u32 key_disable;
@@ -222,7 +222,7 @@ struct mwifiex_ds_encrypt_key {
 	u8 key_material[WLAN_MAX_KEY_LEN];
 	u8 mac_addr[ETH_ALEN];
 	u32 is_wapi_key;
-	u8 wapi_rxpn[WAPI_RXPN_LEN];
+	u8 pn[PN_LEN];		/* packet number */
 };
 
 struct mwifiex_power_cfg {
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index df3a33c..a4a4a19 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -610,7 +610,7 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
 		memcpy(&key_material->key_param_set.key[2],
 		       enc_key->key_material, enc_key->key_len);
 		memcpy(&key_material->key_param_set.key[2 + enc_key->key_len],
-		       enc_key->wapi_rxpn, WAPI_RXPN_LEN);
+		       enc_key->pn, PN_LEN);
 		key_material->key_param_set.length =
 			cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN);
 
-- 
1.7.0.2


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

* [PATCH 15/16] mwifiex: pass key_params pointer in mwifiex_set_encode
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (13 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 14/16] mwifiex: rename wapi_rxpn to pn Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  2012-08-04  1:06 ` [PATCH 16/16] mwifiex: add AES_CMAC support in key_material cmd Bing Zhao
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Ying Luo <luoy@marvell.com>

'cipher' and 'seq' coming from cfg80211 add_key handler will be
parsed in mwifiex_set_encode() to handle AES_CMAC cipher suite.

Signed-off-by: Ying Luo <luoy@marvell.com>
Signed-off-by: Stone Piao <piaoyun@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/cfg80211.c  |   15 +++++++++------
 drivers/net/wireless/mwifiex/ioctl.h     |    1 +
 drivers/net/wireless/mwifiex/main.h      |    6 +++---
 drivers/net/wireless/mwifiex/sta_ioctl.c |   12 +++++++++---
 4 files changed, 22 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 1f80f7e..e57f543 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -99,7 +99,7 @@ mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev,
 	const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	const u8 *peer_mac = pairwise ? mac_addr : bc_mac;
 
-	if (mwifiex_set_encode(priv, NULL, 0, key_index, peer_mac, 1)) {
+	if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) {
 		wiphy_err(wiphy, "deleting the crypto keys\n");
 		return -EFAULT;
 	}
@@ -171,7 +171,8 @@ mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
 
 	if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) {
 		priv->wep_key_curr_index = key_index;
-	} else if (mwifiex_set_encode(priv, NULL, 0, key_index, NULL, 0)) {
+	} else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index,
+				      NULL, 0)) {
 		wiphy_err(wiphy, "set default Tx key index\n");
 		return -EFAULT;
 	}
@@ -207,7 +208,7 @@ mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev,
 		return 0;
 	}
 
-	if (mwifiex_set_encode(priv, params->key, params->key_len,
+	if (mwifiex_set_encode(priv, params, params->key, params->key_len,
 			       key_index, peer_mac, 0)) {
 		wiphy_err(wiphy, "crypto keys added\n");
 		return -EFAULT;
@@ -748,6 +749,7 @@ static const u32 mwifiex_cipher_suites[] = {
 	WLAN_CIPHER_SUITE_WEP104,
 	WLAN_CIPHER_SUITE_TKIP,
 	WLAN_CIPHER_SUITE_CCMP,
+	WLAN_CIPHER_SUITE_AES_CMAC,
 };
 
 /*
@@ -1161,7 +1163,7 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
 	priv->wep_key_curr_index = 0;
 	priv->sec_info.encryption_mode = 0;
 	priv->sec_info.is_authtype_auto = 0;
-	ret = mwifiex_set_encode(priv, NULL, 0, 0, NULL, 1);
+	ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1);
 
 	if (mode == NL80211_IFTYPE_ADHOC) {
 		/* "privacy" is set only for ad-hoc mode */
@@ -1208,8 +1210,9 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
 				"info: setting wep encryption"
 				" with key len %d\n", sme->key_len);
 			priv->wep_key_curr_index = sme->key_idx;
-			ret = mwifiex_set_encode(priv, sme->key, sme->key_len,
-						 sme->key_idx, NULL, 0);
+			ret = mwifiex_set_encode(priv, NULL, sme->key,
+						 sme->key_len, sme->key_idx,
+						 NULL, 0);
 		}
 	}
 done:
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index f2865b5..6a5eded 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -223,6 +223,7 @@ struct mwifiex_ds_encrypt_key {
 	u8 mac_addr[ETH_ALEN];
 	u32 is_wapi_key;
 	u8 pn[PN_LEN];		/* packet number */
+	u8 is_igtk_key;
 };
 
 struct mwifiex_power_cfg {
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index c39cd8e..994bc4f 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -981,9 +981,9 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
 			  const struct mwifiex_user_scan_cfg *user_scan_in);
 int mwifiex_set_radio(struct mwifiex_private *priv, u8 option);
 
-int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
-		       int key_len, u8 key_index, const u8 *mac_addr,
-		       int disable);
+int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
+		       const u8 *key, int key_len, u8 key_index,
+		       const u8 *mac_addr, int disable);
 
 int mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len);
 
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index fb21360..3f02597 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -942,20 +942,26 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version,
  * This function allocates the IOCTL request buffer, fills it
  * with requisite parameters and calls the IOCTL handler.
  */
-int mwifiex_set_encode(struct mwifiex_private *priv, const u8 *key,
-			int key_len, u8 key_index,
-			const u8 *mac_addr, int disable)
+int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp,
+		       const u8 *key, int key_len, u8 key_index,
+		       const u8 *mac_addr, int disable)
 {
 	struct mwifiex_ds_encrypt_key encrypt_key;
 
 	memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key));
 	encrypt_key.key_len = key_len;
+
+	if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC)
+		encrypt_key.is_igtk_key = true;
+
 	if (!disable) {
 		encrypt_key.key_index = key_index;
 		if (key_len)
 			memcpy(encrypt_key.key_material, key, key_len);
 		if (mac_addr)
 			memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN);
+		if (kp && kp->seq && kp->seq_len)
+			memcpy(encrypt_key.pn, kp->seq, kp->seq_len);
 	} else {
 		encrypt_key.key_disable = true;
 		if (mac_addr)
-- 
1.7.0.2


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

* [PATCH 16/16] mwifiex: add AES_CMAC support in key_material cmd
  2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
                   ` (14 preceding siblings ...)
  2012-08-04  1:06 ` [PATCH 15/16] mwifiex: pass key_params pointer in mwifiex_set_encode Bing Zhao
@ 2012-08-04  1:06 ` Bing Zhao
  15 siblings, 0 replies; 17+ messages in thread
From: Bing Zhao @ 2012-08-04  1:06 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Amitkumar Karwar, Avinash Patil, Kiran Divekar,
	Yogesh Powar, Stone Piao, Ying Luo, Frank Huang, Bing Zhao

From: Ying Luo <luoy@marvell.com>

The sequence counter will be sent to firmware via key_material
command.

Signed-off-by: Ying Luo <luoy@marvell.com>
Signed-off-by: Stone Piao <piaoyun@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
 drivers/net/wireless/mwifiex/fw.h      |    9 +++++
 drivers/net/wireless/mwifiex/sta_cmd.c |   53 ++++++++++++++++++++++++++------
 2 files changed, 52 insertions(+), 10 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 1c1274d..ae06f31 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -65,10 +65,12 @@ enum KEY_TYPE_ID {
 	KEY_TYPE_ID_TKIP,
 	KEY_TYPE_ID_AES,
 	KEY_TYPE_ID_WAPI,
+	KEY_TYPE_ID_AES_CMAC,
 };
 #define KEY_MCAST	BIT(0)
 #define KEY_UNICAST	BIT(1)
 #define KEY_ENABLED	BIT(2)
+#define KEY_IGTK	BIT(10)
 
 #define WAPI_KEY_LEN			50
 
@@ -583,6 +585,13 @@ struct mwifiex_ie_type_key_param_set {
 	u8 key[50];
 } __packed;
 
+#define IGTK_PN_LEN		8
+
+struct mwifiex_cmac_param {
+	u8 ipn[IGTK_PN_LEN];
+	u8 key[WLAN_KEY_LEN_AES_CMAC];
+} __packed;
+
 struct host_cmd_ds_802_11_key_material {
 	__le16 action;
 	struct mwifiex_ie_type_key_param_set key_param_set;
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index a4a4a19..9af9692 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -621,23 +621,38 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
 		return ret;
 	}
 	if (enc_key->key_len == WLAN_KEY_LEN_CCMP) {
-		dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
-		key_material->key_param_set.key_type_id =
+		if (enc_key->is_igtk_key) {
+			dev_dbg(priv->adapter->dev, "cmd: CMAC_AES\n");
+			key_material->key_param_set.key_type_id =
+					cpu_to_le16(KEY_TYPE_ID_AES_CMAC);
+			if (cmd_oid == KEY_INFO_ENABLED)
+				key_material->key_param_set.key_info =
+						cpu_to_le16(KEY_ENABLED);
+			else
+				key_material->key_param_set.key_info =
+						cpu_to_le16(!KEY_ENABLED);
+
+			key_material->key_param_set.key_info |=
+							cpu_to_le16(KEY_IGTK);
+		} else {
+			dev_dbg(priv->adapter->dev, "cmd: WPA_AES\n");
+			key_material->key_param_set.key_type_id =
 						cpu_to_le16(KEY_TYPE_ID_AES);
-		if (cmd_oid == KEY_INFO_ENABLED)
-			key_material->key_param_set.key_info =
+			if (cmd_oid == KEY_INFO_ENABLED)
+				key_material->key_param_set.key_info =
 						cpu_to_le16(KEY_ENABLED);
-		else
-			key_material->key_param_set.key_info =
+			else
+				key_material->key_param_set.key_info =
 						cpu_to_le16(!KEY_ENABLED);
 
-		if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
+			if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST)
 				/* AES pairwise key: unicast */
-			key_material->key_param_set.key_info |=
+				key_material->key_param_set.key_info |=
 						cpu_to_le16(KEY_UNICAST);
-		else		/* AES group key: multicast */
-			key_material->key_param_set.key_info |=
+			else	/* AES group key: multicast */
+				key_material->key_param_set.key_info |=
 							cpu_to_le16(KEY_MCAST);
+		}
 	} else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) {
 		dev_dbg(priv->adapter->dev, "cmd: WPA_TKIP\n");
 		key_material->key_param_set.key_type_id =
@@ -668,6 +683,24 @@ mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv,
 		key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN)
 				+ sizeof(struct mwifiex_ie_types_header);
 
+		if (le16_to_cpu(key_material->key_param_set.key_type_id) ==
+							KEY_TYPE_ID_AES_CMAC) {
+			struct mwifiex_cmac_param *param =
+					(void *)key_material->key_param_set.key;
+
+			memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN);
+			memcpy(param->key, enc_key->key_material,
+			       enc_key->key_len);
+
+			key_param_len = sizeof(struct mwifiex_cmac_param);
+			key_material->key_param_set.key_len =
+						cpu_to_le16(key_param_len);
+			key_param_len += KEYPARAMSET_FIXED_LEN;
+			key_material->key_param_set.length =
+						cpu_to_le16(key_param_len);
+			key_param_len += sizeof(struct mwifiex_ie_types_header);
+		}
+
 		cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN
 					+ key_param_len);
 
-- 
1.7.0.2


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

end of thread, other threads:[~2012-08-04  1:54 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-04  1:05 [PATCH 00/16] mwifiex: patches for 3.7 Bing Zhao
2012-08-04  1:05 ` [PATCH 01/16] mwifiex: copy MSDU subframes correctly Bing Zhao
2012-08-04  1:06 ` [PATCH 02/16] mwifiex: remove extra padding to AMSDU Bing Zhao
2012-08-04  1:06 ` [PATCH 03/16] mwifiex: correction in MSDU padding logic Bing Zhao
2012-08-04  1:06 ` [PATCH 04/16] mwifiex: do le_to_cpu conversion for Rx packet header elements Bing Zhao
2012-08-04  1:06 ` [PATCH 05/16] mwifiex: update max_chan_per_scan correctly for SSID scan Bing Zhao
2012-08-04  1:06 ` [PATCH 06/16] mwifiex: improve scan delay logic during Tx traffic Bing Zhao
2012-08-04  1:06 ` [PATCH 07/16] mwifiex: update 11n status as per start_ap IE Bing Zhao
2012-08-04  1:06 ` [PATCH 08/16] mwifiex: separate file for handling AP events Bing Zhao
2012-08-04  1:06 ` [PATCH 09/16] mwifiex: create list for associated stations in AP mode Bing Zhao
2012-08-04  1:06 ` [PATCH 10/16] mwifiex: improve uAP RX handling Bing Zhao
2012-08-04  1:06 ` [PATCH 11/16] mwifiex: support RX AMSDU aggregation for uAP Bing Zhao
2012-08-04  1:06 ` [PATCH 12/16] mwifiex: add 11n Block Ack support " Bing Zhao
2012-08-04  1:06 ` [PATCH 13/16] mwifiex: cleanup TX/RX BA tables " Bing Zhao
2012-08-04  1:06 ` [PATCH 14/16] mwifiex: rename wapi_rxpn to pn Bing Zhao
2012-08-04  1:06 ` [PATCH 15/16] mwifiex: pass key_params pointer in mwifiex_set_encode Bing Zhao
2012-08-04  1:06 ` [PATCH 16/16] mwifiex: add AES_CMAC support in key_material cmd Bing Zhao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).