linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2] cfg80211: make stripping of 802.11 header optional from AMSDU
@ 2011-05-13 18:22 Bing Zhao
  2011-05-13 18:22 ` [PATCH v2] mwifiex: use ieee80211_amsdu_to_8023s routine Bing Zhao
  0 siblings, 1 reply; 2+ messages in thread
From: Bing Zhao @ 2011-05-13 18:22 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Johannes Berg, Amitkumar Karwar, Kiran Divekar,
	Yogesh Powar, Marc Yang, Frank Huang, Bing Zhao

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

Currently the devices that have already stripped IEEE 802.11
header from the AMSDU SKB can not use ieee80211_amsdu_to_8023s
routine. This patch enhances ieee80211_amsdu_to_8023s() API by
changing mandatory removing of IEEE 802.11 header from AMSDU
to optional.

Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
v2: Changed newly added flag from 'stripped_80211_header' to
    'has_80211_header' (suggested by Johannes)

 drivers/net/wireless/iwmc3200wifi/rx.c |    3 ++-
 include/net/cfg80211.h                 |    4 +++-
 net/mac80211/rx.c                      |    2 +-
 net/wireless/util.c                    |   21 +++++++++++++--------
 4 files changed, 19 insertions(+), 11 deletions(-)

diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index 9a57cf6..5665a1a 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1576,7 +1576,8 @@ static void iwm_rx_process_amsdu(struct iwm_priv *iwm, struct sk_buff *skb)
 	IWM_HEXDUMP(iwm, DBG, RX, "A-MSDU: ", skb->data, skb->len);
 
 	__skb_queue_head_init(&list);
-	ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0);
+	ieee80211_amsdu_to_8023s(skb, &list, ndev->dev_addr, wdev->iftype, 0,
+									true);
 
 	while ((frame = __skb_dequeue(&list))) {
 		ndev->stats.rx_packets++;
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e1f1b41..c0fad47 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2176,10 +2176,12 @@ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
  * @addr: The device MAC address.
  * @iftype: The device interface type.
  * @extra_headroom: The hardware extra headroom for SKBs in the @list.
+ * @has_80211_header: Set it true if SKB is with IEEE 802.11 header.
  */
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 			      const u8 *addr, enum nl80211_iftype iftype,
-			      const unsigned int extra_headroom);
+			      const unsigned int extra_headroom,
+			      bool has_80211_header);
 
 /**
  * cfg80211_classify8021d - determine the 802.1p/1d tag for a data frame
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b6bde2e..866116c 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1783,7 +1783,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 
 	ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
 				 rx->sdata->vif.type,
-				 rx->local->hw.extra_tx_headroom);
+				 rx->local->hw.extra_tx_headroom, true);
 
 	while (!skb_queue_empty(&frame_list)) {
 		rx->skb = __skb_dequeue(&frame_list);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 414c9f6..ad7ffc7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -544,7 +544,8 @@ EXPORT_SYMBOL(ieee80211_data_from_8023);
 
 void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 			      const u8 *addr, enum nl80211_iftype iftype,
-			      const unsigned int extra_headroom)
+			      const unsigned int extra_headroom,
+			      bool has_80211_header)
 {
 	struct sk_buff *frame = NULL;
 	u16 ethertype;
@@ -553,14 +554,18 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 	int remaining, err;
 	u8 dst[ETH_ALEN], src[ETH_ALEN];
 
-	err = ieee80211_data_to_8023(skb, addr, iftype);
-	if (err)
-		goto out;
+	if (has_80211_header) {
+		err = ieee80211_data_to_8023(skb, addr, iftype);
+		if (err)
+			goto out;
 
-	/* skip the wrapping header */
-	eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
-	if (!eth)
-		goto out;
+		/* skip the wrapping header */
+		eth = (struct ethhdr *) skb_pull(skb, sizeof(struct ethhdr));
+		if (!eth)
+			goto out;
+	} else {
+		eth = (struct ethhdr *) skb->data;
+	}
 
 	while (skb != frame) {
 		u8 padding;
-- 
1.7.0.2


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

* [PATCH v2] mwifiex: use ieee80211_amsdu_to_8023s routine
  2011-05-13 18:22 [PATCH v2] cfg80211: make stripping of 802.11 header optional from AMSDU Bing Zhao
@ 2011-05-13 18:22 ` Bing Zhao
  0 siblings, 0 replies; 2+ messages in thread
From: Bing Zhao @ 2011-05-13 18:22 UTC (permalink / raw)
  To: linux-wireless
  Cc: John W. Linville, Johannes Berg, Amitkumar Karwar, Kiran Divekar,
	Yogesh Powar, Marc Yang, Frank Huang, Bing Zhao

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

mwifiex was using its own implementation of converting 802.11n
AMSDU to 802.3s.  This patch removes mwifiex specific
implementation and uses existing ieee80211_amsdu_to_8023s
routine.

Signed-off-by: Yogesh Ashok Powar <yogeshp@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
---
This patch depends on the cfg80211 patch:
"[PATCH v2] cfg80211: make stripping of 802.11 header optional from AMSDU"

v2: Call ieee80211_amsdu_to_8023s with has_80211_header set to 'false'

 drivers/net/wireless/mwifiex/11n_aggr.c |  125 -------------------------------
 drivers/net/wireless/mwifiex/sta_rx.c   |   22 +++++-
 2 files changed, 20 insertions(+), 127 deletions(-)

diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 2b2cca5..d3d5e08 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -136,131 +136,6 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
 }
 
 /*
- * Counts the number of subframes in an aggregate packet.
- *
- * This function parses an aggregate packet buffer, looking for
- * subframes and counting the number of such subframe found. The
- * function automatically skips the DA/SA fields at the beginning
- * of each subframe and padding at the end.
- */
-static int
-mwifiex_11n_get_num_aggr_pkts(u8 *data, int total_pkt_len)
-{
-	int pkt_count = 0, pkt_len, pad;
-
-	while (total_pkt_len > 0) {
-		/* Length will be in network format, change it to host */
-		pkt_len = ntohs((*(__be16 *)(data + 2 * ETH_ALEN)));
-		pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ?
-			(4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0;
-		data += pkt_len + pad + sizeof(struct ethhdr);
-		total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr);
-		++pkt_count;
-	}
-
-	return pkt_count;
-}
-
-/*
- * De-aggregate received packets.
- *
- * This function parses the received aggregate buffer, extracts each subframe,
- * strips off the SNAP header from them and sends the data portion for further
- * processing.
- *
- * Each subframe body is copied onto a separate buffer, which are freed by
- * upper layer after processing. The function also performs sanity tests on
- * the received buffer.
- */
-int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv,
-				struct sk_buff *skb)
-{
-	u16 pkt_len;
-	int total_pkt_len;
-	u8 *data;
-	int pad;
-	struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb);
-	struct rxpd *local_rx_pd = (struct rxpd *) skb->data;
-	struct sk_buff *skb_daggr;
-	struct mwifiex_rxinfo *rx_info_daggr;
-	int ret = -1;
-	struct rx_packet_hdr *rx_pkt_hdr;
-	struct mwifiex_adapter *adapter = priv->adapter;
-	u8 rfc1042_eth_hdr[ETH_ALEN] = { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00};
-
-	data = (u8 *) (local_rx_pd + local_rx_pd->rx_pkt_offset);
-	total_pkt_len = local_rx_pd->rx_pkt_length;
-
-	/* Sanity test */
-	if (total_pkt_len > MWIFIEX_RX_DATA_BUF_SIZE) {
-		dev_err(adapter->dev, "total pkt len greater than buffer"
-		       " size %d\n", total_pkt_len);
-		return -1;
-	}
-
-	rx_info->use_count = mwifiex_11n_get_num_aggr_pkts(data, total_pkt_len);
-
-	while (total_pkt_len > 0) {
-		rx_pkt_hdr = (struct rx_packet_hdr *) data;
-		/* Length will be in network format, change it to host */
-		pkt_len = ntohs((*(__be16 *) (data + 2 * ETH_ALEN)));
-		if (pkt_len > total_pkt_len) {
-			dev_err(adapter->dev, "pkt_len %d > total_pkt_len %d\n",
-			       total_pkt_len, pkt_len);
-			break;
-		}
-
-		pad = (((pkt_len + sizeof(struct ethhdr)) & 3)) ?
-			(4 - ((pkt_len + sizeof(struct ethhdr)) & 3)) : 0;
-
-		total_pkt_len -= pkt_len + pad + sizeof(struct ethhdr);
-
-		if (memcmp(&rx_pkt_hdr->rfc1042_hdr,
-			   rfc1042_eth_hdr, sizeof(rfc1042_eth_hdr)) == 0) {
-			memmove(data + LLC_SNAP_LEN, data, 2 * ETH_ALEN);
-			data += LLC_SNAP_LEN;
-			pkt_len += sizeof(struct ethhdr) - LLC_SNAP_LEN;
-		} else {
-			*(u16 *) (data + 2 * ETH_ALEN) = (u16) 0;
-			pkt_len += sizeof(struct ethhdr);
-		}
-
-		skb_daggr = dev_alloc_skb(pkt_len);
-		if (!skb_daggr) {
-			dev_err(adapter->dev, "%s: failed to alloc skb_daggr\n",
-			       __func__);
-			return -1;
-		}
-		rx_info_daggr = MWIFIEX_SKB_RXCB(skb_daggr);
-
-		rx_info_daggr->bss_index = rx_info->bss_index;
-		skb_daggr->tstamp = skb->tstamp;
-		rx_info_daggr->parent = skb;
-		skb_daggr->priority = skb->priority;
-		skb_put(skb_daggr, pkt_len);
-		memcpy(skb_daggr->data, data, pkt_len);
-
-		ret = mwifiex_recv_packet(adapter, skb_daggr);
-
-		switch (ret) {
-		case -EINPROGRESS:
-			break;
-		case -1:
-			dev_err(adapter->dev, "deaggr: host_to_card failed\n");
-		case 0:
-			mwifiex_recv_packet_complete(adapter, skb_daggr, ret);
-			break;
-		default:
-			break;
-		}
-
-		data += pkt_len + pad;
-	}
-
-	return ret;
-}
-
-/*
  * Create aggregated packet.
  *
  * This function creates an aggregated MSDU packet, by combining buffers
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index e047f0d..1fdddec 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -141,10 +141,28 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_adapter *adapter,
 		dev_kfree_skb_any(skb);
 		return ret;
 	}
+
 	if (local_rx_pd->rx_pkt_type == PKT_TYPE_AMSDU) {
-		mwifiex_11n_deaggregate_pkt(priv, skb);
-		return ret;
+		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);
+
+		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 == -1)
+				dev_err(adapter->dev, "Rx of A-MSDU failed");
+		}
+		return 0;
 	}
+
 	/*
 	 * If the packet is not an unicast packet then send the packet
 	 * directly to os. Don't pass thru rx reordering
-- 
1.7.0.2


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

end of thread, other threads:[~2011-05-13 18:17 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-05-13 18:22 [PATCH v2] cfg80211: make stripping of 802.11 header optional from AMSDU Bing Zhao
2011-05-13 18:22 ` [PATCH v2] mwifiex: use ieee80211_amsdu_to_8023s routine 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).