All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <1255758143.21134.1360.camel@rc-desk>

diff --git a/a/2.txt b/N1/2.txt
index a376430..070ceb3 100644
--- a/a/2.txt
+++ b/N1/2.txt
@@ -1,5 +1,5 @@
-From d94fc37fb25aacec8a41e3d14ec333fa5a8f681e Mon Sep 17 00:00:00 2001
-From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
+>From d94fc37fb25aacec8a41e3d14ec333fa5a8f681e Mon Sep 17 00:00:00 2001
+From: Zhu Yi <yi.zhu@intel.com>
 Date: Fri, 9 Oct 2009 17:19:45 +0800
 Subject: [PATCH 1/2] iwlwifi: use paged Rx
 
@@ -24,8 +24,8 @@ required data frames before handed to mac80211. For all the other frames,
 we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211
 to handle them properly.
 
-Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-Signed-off-by: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
+Signed-off-by: Zhu Yi <yi.zhu@intel.com>
+Signed-off-by: John W. Linville <linville@tuxdriver.com>
 ---
  drivers/net/wireless/iwlwifi/iwl-3945.c     |   67 ++++++++++-----
  drivers/net/wireless/iwlwifi/iwl-4965.c     |    2 +-
diff --git a/a/3.txt b/N1/3.txt
index 35abb91..c91e2fd 100644
--- a/a/3.txt
+++ b/N1/3.txt
@@ -1,5 +1,5 @@
-From 000c60eef9bf7a579c02ccb7deee447a2231d2b0 Mon Sep 17 00:00:00 2001
-From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
+>From 000c60eef9bf7a579c02ccb7deee447a2231d2b0 Mon Sep 17 00:00:00 2001
+From: Zhu Yi <yi.zhu@intel.com>
 Date: Thu, 15 Oct 2009 20:00:57 -0700
 Subject: [PATCH 2/2] iwlwifi: fix use after free bug for paged rx
 
@@ -11,10 +11,10 @@ access the page after being handled to the upper layer, we can use
 get_page/put_page to handle it. For now, it's just not necessary.
 
 It also fixed a debug message print bug reported by Stanislaw Gruszka
-<sgruszka-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>.
+<sgruszka@redhat.com>.
 
-Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-Signed-off-by: Reinette Chatre <reinette.chatre-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
+Signed-off-by: Zhu Yi <yi.zhu@intel.com>
+Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
 ---
  drivers/net/wireless/iwlwifi/iwl-3945.c     |   16 +++++++++++-----
  drivers/net/wireless/iwlwifi/iwl-agn.c      |   11 +++++++++--
diff --git a/a/content_digest b/N1/content_digest
index 33cc605..6d5adb7 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -2,24 +2,23 @@
  "ref\0200910150402.03953.elendil@planet.nl\0"
  "ref\01255620567.21134.162.camel@rc-desk\0"
  "ref\0200910152142.02876.elendil@planet.nl\0"
- "ref\0200910152142.02876.elendil-EIBgga6/0yRmR6Xm/wNWPw@public.gmane.org\0"
- "From\0reinette chatre <reinette.chatre-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\0"
+ "From\0reinette chatre <reinette.chatre@intel.com>\0"
  "Subject\0Re: [Bug #14141] order 2 page allocation failures in iwlagn\0"
  "Date\0Fri, 16 Oct 2009 22:42:23 -0700\0"
- "To\0Frans Pop <elendil-EIBgga6/0yRmR6Xm/wNWPw@public.gmane.org>\0"
- "Cc\0Mel Gorman <mel-wPRd99KPJ+uzQB+pC5nmwQ@public.gmane.org>"
-  David Rientjes <rientjes-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
-  KOSAKI Motohiro <kosaki.motohiro-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
-  Rafael J. Wysocki <rjw-KKrjLPT3xs0@public.gmane.org>
-  Linux Kernel Mailing List <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
-  Kernel Testers List <kernel-testers-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
-  Pekka Enberg <penberg-bbCR+/B0CizivPeTLB3BmA@public.gmane.org>
-  Bartlomiej Zolnierkiewicz <bzolnier-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
-  Karol Lewandowski <karol.k.lewandowski-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ "To\0Frans Pop <elendil@planet.nl>\0"
+ "Cc\0Mel Gorman <mel@csn.ul.ie>"
+  David Rientjes <rientjes@google.com>
+  KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+  Rafael J. Wysocki <rjw@sisk.pl>
+  Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+  Kernel Testers List <kernel-testers@vger.kernel.org>
+  Pekka Enberg <penberg@cs.helsinki.fi>
+  Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+  Karol Lewandowski <karol.k.lewandowski@gmail.com>
   Abbas
-  Mohamed <mohamed.abbas-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-  John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
- " linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org <linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>\0"
+  Mohamed <mohamed.abbas@intel.com>
+  John W. Linville <linville@tuxdriver.com>
+ " linux-mm@kvack.org <linux-mm@kvack.org>\0"
  "\01:1\0"
  "b\0"
  "Hi Frans,\n"
@@ -52,8 +51,8 @@
  "\01:2\0"
  "fn\00001-iwlwifi-use-paged-Rx.patch\0"
  "b\0"
- "From d94fc37fb25aacec8a41e3d14ec333fa5a8f681e Mon Sep 17 00:00:00 2001\n"
- "From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
+ ">From d94fc37fb25aacec8a41e3d14ec333fa5a8f681e Mon Sep 17 00:00:00 2001\n"
+ "From: Zhu Yi <yi.zhu@intel.com>\n"
  "Date: Fri, 9 Oct 2009 17:19:45 +0800\n"
  "Subject: [PATCH 1/2] iwlwifi: use paged Rx\n"
  "\n"
@@ -78,8 +77,8 @@
  "we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211\n"
  "to handle them properly.\n"
  "\n"
- "Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "Signed-off-by: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>\n"
+ "Signed-off-by: Zhu Yi <yi.zhu@intel.com>\n"
+ "Signed-off-by: John W. Linville <linville@tuxdriver.com>\n"
  "---\n"
  " drivers/net/wireless/iwlwifi/iwl-3945.c     |   67 ++++++++++-----\n"
  " drivers/net/wireless/iwlwifi/iwl-4965.c     |    2 +-\n"
@@ -1451,8 +1450,8 @@
  "\01:3\0"
  "fn\00002-iwlwifi-fix-use-after-free-bug-for-paged-rx.patch\0"
  "b\0"
- "From 000c60eef9bf7a579c02ccb7deee447a2231d2b0 Mon Sep 17 00:00:00 2001\n"
- "From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
+ ">From 000c60eef9bf7a579c02ccb7deee447a2231d2b0 Mon Sep 17 00:00:00 2001\n"
+ "From: Zhu Yi <yi.zhu@intel.com>\n"
  "Date: Thu, 15 Oct 2009 20:00:57 -0700\n"
  "Subject: [PATCH 2/2] iwlwifi: fix use after free bug for paged rx\n"
  "\n"
@@ -1464,10 +1463,10 @@
  "get_page/put_page to handle it. For now, it's just not necessary.\n"
  "\n"
  "It also fixed a debug message print bug reported by Stanislaw Gruszka\n"
- "<sgruszka-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>.\n"
+ "<sgruszka@redhat.com>.\n"
  "\n"
- "Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "Signed-off-by: Reinette Chatre <reinette.chatre-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
+ "Signed-off-by: Zhu Yi <yi.zhu@intel.com>\n"
+ "Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>\n"
  "---\n"
  " drivers/net/wireless/iwlwifi/iwl-3945.c     |   16 +++++++++++-----\n"
  " drivers/net/wireless/iwlwifi/iwl-agn.c      |   11 +++++++++--\n"
@@ -1679,4 +1678,4 @@
  "-- \n"
  1.5.6.3
 
-99025b4ff234e0365c9a5f712d085ec78b9bfec0a747f8ae86d0864485f7fa1a
+aa7236099248af5f6fdeca3025c038702a8be298c67f8964a070e89293cf3a99

diff --git a/a/2.txt b/N2/2.txt
index a376430..8b13789 100644
--- a/a/2.txt
+++ b/N2/2.txt
@@ -1,1396 +1 @@
-From d94fc37fb25aacec8a41e3d14ec333fa5a8f681e Mon Sep 17 00:00:00 2001
-From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-Date: Fri, 9 Oct 2009 17:19:45 +0800
-Subject: [PATCH 1/2] iwlwifi: use paged Rx
 
-This switches the iwlwifi driver to use paged skb from linear skb for Rx
-buffer. So that it relieves some Rx buffer allocation pressure for the
-memory subsystem. Currently iwlwifi (4K for 3945) requests 8K bytes for
-Rx buffer. Due to the trailing skb_shared_info in the skb->data,
-alloc_skb() will do the next order allocation, which is 16K bytes. This
-is suboptimal and more likely to fail when the system is under memory
-usage pressure. Switching to paged Rx skb lets us allocate the RXB
-directly by alloc_pages(), so that only order 1 allocation is required.
-
-It also adjusts the area spin_lock (with IRQ disabled) protected in the
-tasklet because tasklet guarentees to run only on one CPU and the new
-unprotected code can be preempted by the IRQ handler. This saves us from
-spawning another workqueue to make skb_linearize/__pskb_pull_tail happy
-(which cannot be called in hard irq context).
-
-Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb
-for all the management frames and software decryption or defragmentation
-required data frames before handed to mac80211. For all the other frames,
-we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211
-to handle them properly.
-
-Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-Signed-off-by: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
----
- drivers/net/wireless/iwlwifi/iwl-3945.c     |   67 ++++++++++-----
- drivers/net/wireless/iwlwifi/iwl-4965.c     |    2 +-
- drivers/net/wireless/iwlwifi/iwl-5000.c     |    4 +-
- drivers/net/wireless/iwlwifi/iwl-agn.c      |   42 ++++-----
- drivers/net/wireless/iwlwifi/iwl-commands.h |   10 ++
- drivers/net/wireless/iwlwifi/iwl-core.c     |   13 ++--
- drivers/net/wireless/iwlwifi/iwl-core.h     |    2 +-
- drivers/net/wireless/iwlwifi/iwl-dev.h      |   27 ++++--
- drivers/net/wireless/iwlwifi/iwl-hcmd.c     |   21 ++----
- drivers/net/wireless/iwlwifi/iwl-rx.c       |  122 +++++++++++++++++----------
- drivers/net/wireless/iwlwifi/iwl-scan.c     |   20 ++--
- drivers/net/wireless/iwlwifi/iwl-spectrum.c |    2 +-
- drivers/net/wireless/iwlwifi/iwl-sta.c      |   62 +++++--------
- drivers/net/wireless/iwlwifi/iwl-tx.c       |   10 +-
- drivers/net/wireless/iwlwifi/iwl3945-base.c |  120 +++++++++++++-------------
- 15 files changed, 284 insertions(+), 240 deletions(-)
-
-diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
-index f059b49..7d5962d 100644
---- a/drivers/net/wireless/iwlwifi/iwl-3945.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
-@@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
- static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
- 			    struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- 	int txq_id = SEQ_TO_QUEUE(sequence);
- 	int index = SEQ_TO_INDEX(sequence);
-@@ -353,7 +353,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
- void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
- 		struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
- 		     (int)sizeof(struct iwl3945_notif_statistics),
- 		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
-@@ -545,14 +545,17 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
- 				   struct iwl_rx_mem_buffer *rxb,
- 				   struct ieee80211_rx_status *stats)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
- 	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- 	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
--	short len = le16_to_cpu(rx_hdr->len);
-+	u16 len = le16_to_cpu(rx_hdr->len);
-+	struct sk_buff *skb;
-+	int ret;
- 
- 	/* We received data from the HW, so stop the watchdog */
--	if (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {
-+	if (unlikely(len + IWL39_RX_FRAME_SIZE >
-+		     PAGE_SIZE << priv->hw_params.rx_page_order)) {
- 		IWL_DEBUG_DROP(priv, "Corruption detected!\n");
- 		return;
- 	}
-@@ -564,24 +567,49 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
- 		return;
- 	}
- 
--	skb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);
--	/* Set the size of the skb to the size of the frame */
--	skb_put(rxb->skb, le16_to_cpu(rx_hdr->len));
-+	skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
-+	if (!skb) {
-+		IWL_ERR(priv, "alloc_skb failed\n");
-+		return;
-+	}
- 
- 	if (!iwl3945_mod_params.sw_crypto)
- 		iwl_set_decrypted_flag(priv,
--				       (struct ieee80211_hdr *)rxb->skb->data,
-+				       (struct ieee80211_hdr *)rxb_addr(rxb),
- 				       le32_to_cpu(rx_end->status), stats);
- 
-+	skb_add_rx_frag(skb, 0, rxb->page,
-+			(void *)rx_hdr->payload - (void *)pkt, len);
-+
-+	/* mac80211 currently doesn't support paged SKB. Convert it to
-+	 * linear SKB for management frame and data frame requires
-+	 * software decryption or software defragementation. */
-+	if (ieee80211_is_mgmt(hdr->frame_control) ||
-+	    ieee80211_has_protected(hdr->frame_control) ||
-+	    ieee80211_has_morefrags(hdr->frame_control) ||
-+	    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
-+		ret = skb_linearize(skb);
-+	else
-+		ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
-+			0 : -ENOMEM;
-+
-+	if (ret) {
-+		kfree_skb(skb);
-+		goto out;
-+	}
-+
- #ifdef CONFIG_IWLWIFI_LEDS
- 	if (ieee80211_is_data(hdr->frame_control))
- 		priv->rxtxpackets += len;
- #endif
- 	iwl_update_stats(priv, false, hdr->frame_control, len);
- 
--	memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
--	ieee80211_rx_irqsafe(priv->hw, rxb->skb);
--	rxb->skb = NULL;
-+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-+	ieee80211_rx(priv->hw, skb);
-+
-+ out:
-+	priv->alloc_rxb_page--;
-+	rxb->page = NULL;
- }
- 
- #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-@@ -591,7 +619,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
- {
- 	struct ieee80211_hdr *header;
- 	struct ieee80211_rx_status rx_status;
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
- 	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
- 	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-@@ -1858,7 +1886,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
- static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
- {
- 	int rc = 0;
--	struct iwl_rx_packet *res = NULL;
-+	struct iwl_rx_packet *pkt;
- 	struct iwl3945_rxon_assoc_cmd rxon_assoc;
- 	struct iwl_host_cmd cmd = {
- 		.id = REPLY_RXON_ASSOC,
-@@ -1887,14 +1915,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)
- 	if (rc)
- 		return rc;
- 
--	res = (struct iwl_rx_packet *)cmd.reply_skb->data;
--	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
- 		rc = -EIO;
- 	}
- 
--	priv->alloc_rxb_skb--;
--	dev_kfree_skb_any(cmd.reply_skb);
-+	priv->alloc_rxb_page--;
-+	free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
- 
- 	return rc;
- }
-@@ -2560,8 +2588,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
- 	priv->hw_params.max_txq_num = IWL39_NUM_QUEUES;
- 
- 	priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
--	priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K;
--	priv->hw_params.max_pkt_size = 2342;
-+	priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
- 	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
- 	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
- 	priv->hw_params.max_stations = IWL3945_STATION_COUNT;
-diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
-index 6f703a0..e7c67d8 100644
---- a/drivers/net/wireless/iwlwifi/iwl-4965.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
-@@ -2078,7 +2078,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
- static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
- 				struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- 	int txq_id = SEQ_TO_QUEUE(sequence);
- 	int index = SEQ_TO_INDEX(sequence);
-diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
-index 6e6f516..29dfe27 100644
---- a/drivers/net/wireless/iwlwifi/iwl-5000.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
-@@ -493,7 +493,7 @@ static int iwl5000_send_calib_cfg(struct iwl_priv *priv)
- static void iwl5000_rx_calib_result(struct iwl_priv *priv,
- 			     struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
- 	int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
- 	int index;
-@@ -1218,7 +1218,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
- static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
- 				struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- 	int txq_id = SEQ_TO_QUEUE(sequence);
- 	int index = SEQ_TO_INDEX(sequence);
-diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
-index eaafae0..c5ff7c0 100644
---- a/drivers/net/wireless/iwlwifi/iwl-agn.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
-@@ -521,7 +521,7 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,
- static void iwl_rx_reply_alive(struct iwl_priv *priv,
- 				struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_alive_resp *palive;
- 	struct delayed_work *pwork;
- 
-@@ -607,7 +607,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
- 				struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl4965_beacon_notif *beacon =
- 		(struct iwl4965_beacon_notif *)pkt->u.raw;
- 	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-@@ -631,7 +631,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,
- static void iwl_rx_card_state_notif(struct iwl_priv *priv,
- 				    struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
- 	unsigned long status = priv->status;
- 
-@@ -783,10 +783,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
- 
- 		rxq->queue[i] = NULL;
- 
--		pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
--				 priv->hw_params.rx_buf_size + 256,
--				 PCI_DMA_FROMDEVICE);
--		pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+		pci_unmap_page(priv->pci_dev, rxb->page_dma,
-+			       PAGE_SIZE << priv->hw_params.rx_page_order,
-+			       PCI_DMA_FROMDEVICE);
-+		pkt = rxb_addr(rxb);
- 
- 		/* Reclaim a command buffer only if this packet is a response
- 		 *   to a (driver-originated) command.
-@@ -819,10 +819,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
- 		}
- 
- 		if (reclaim) {
--			/* Invoke any callbacks, transfer the skb to caller, and
--			 * fire off the (possibly) blocking iwl_send_cmd()
-+			/* Invoke any callbacks, transfer the buffer to caller,
-+			 * and fire off the (possibly) blocking iwl_send_cmd()
- 			 * as we reclaim the driver command queue */
--			if (rxb && rxb->skb)
-+			if (rxb && rxb->page)
- 				iwl_tx_cmd_complete(priv, rxb);
- 			else
- 				IWL_WARN(priv, "Claim null rxb?\n");
-@@ -831,10 +831,10 @@ void iwl_rx_handle(struct iwl_priv *priv)
- 		/* For now we just don't re-use anything.  We can tweak this
- 		 * later to try and re-use notification packets and SKBs that
- 		 * fail to Rx correctly */
--		if (rxb->skb != NULL) {
--			priv->alloc_rxb_skb--;
--			dev_kfree_skb_any(rxb->skb);
--			rxb->skb = NULL;
-+		if (rxb->page != NULL) {
-+			priv->alloc_rxb_page--;
-+			__free_pages(rxb->page, priv->hw_params.rx_page_order);
-+			rxb->page = NULL;
- 		}
- 
- 		spin_lock_irqsave(&rxq->lock, flags);
-@@ -901,6 +901,8 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
- 	}
- #endif
- 
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+
- 	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
- 	 * atomic, make sure that inta covers all the interrupts that
- 	 * we've discovered, even if FH interrupt came in just after
-@@ -922,8 +924,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
- 
- 		handled |= CSR_INT_BIT_HW_ERR;
- 
--		spin_unlock_irqrestore(&priv->lock, flags);
--
- 		return;
- 	}
- 
-@@ -1050,7 +1050,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)
- 			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
- 	}
- #endif
--	spin_unlock_irqrestore(&priv->lock, flags);
- }
- 
- /* tasklet for iwlagn interrupt */
-@@ -1080,6 +1079,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
- 				inta, inta_mask);
- 	}
- #endif
-+
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+
- 	/* saved interrupt in inta variable now we can reset priv->inta */
- 	priv->inta = 0;
- 
-@@ -1095,8 +1097,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
- 
- 		handled |= CSR_INT_BIT_HW_ERR;
- 
--		spin_unlock_irqrestore(&priv->lock, flags);
--
- 		return;
- 	}
- 
-@@ -1236,14 +1236,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)
- 			 inta & ~priv->inta_mask);
- 	}
- 
--
- 	/* Re-enable all interrupts */
- 	/* only Re-enable if diabled by irq */
- 	if (test_bit(STATUS_INT_ENABLED, &priv->status))
- 		iwl_enable_interrupts(priv);
--
--	spin_unlock_irqrestore(&priv->lock, flags);
--
- }
- 
- 
-diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
-index 4afaf77..dd54bf2 100644
---- a/drivers/net/wireless/iwlwifi/iwl-commands.h
-+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
-@@ -3495,6 +3495,16 @@ struct iwl_wimax_coex_cmd {
-  *****************************************************************************/
- 
- struct iwl_rx_packet {
-+	/*
-+	 * The first 4 bytes of the RX frame header contain both the RX frame
-+	 * size and some flags.
-+	 * Bit fields:
-+	 * 31:    flag flush RB request
-+	 * 30:    flag ignore TC (terminal counter) request
-+	 * 29:    flag fast IRQ request
-+	 * 28-14: Reserved
-+	 * 13-00: RX frame size
-+	 */
- 	__le32 len_n_flags;
- 	struct iwl_cmd_header hdr;
- 	union {
-diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
-index 2dc9287..bb9ff29 100644
---- a/drivers/net/wireless/iwlwifi/iwl-core.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
-@@ -1281,7 +1281,7 @@ static void iwl_set_rate(struct iwl_priv *priv)
- 
- void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;
- 	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
- 	IWL_DEBUG_11H(priv, "CSA notif: channel %d, status %d\n",
-@@ -1456,10 +1456,9 @@ int iwl_set_hw_params(struct iwl_priv *priv)
- 	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
- 	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
- 	if (priv->cfg->mod_params->amsdu_size_8K)
--		priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;
-+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
- 	else
--		priv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;
--	priv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;
-+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
- 
- 	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
- 
-@@ -2143,7 +2142,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
- 			   struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);
- 	IWL_DEBUG_RX(priv, "sleep mode: %d, src: %d\n",
- 		     sleep->pm_sleep_mode, sleep->pm_wakeup_src);
-@@ -2154,7 +2153,7 @@ EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);
- void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
- 				      struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
- 	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
- 			"notification for %s:\n", len,
-@@ -2166,7 +2165,7 @@ EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
- void iwl_rx_reply_error(struct iwl_priv *priv,
- 			struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 
- 	IWL_ERR(priv, "Error Reply type 0x%08X cmd %s (0x%02X) "
- 		"seq 0x%04X ser 0x%08X\n",
-diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
-index e50103a..d95674e 100644
---- a/drivers/net/wireless/iwlwifi/iwl-core.h
-+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
-@@ -509,7 +509,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
- 			   const void *data,
- 			   void (*callback)(struct iwl_priv *priv,
- 					    struct iwl_device_cmd *cmd,
--					    struct sk_buff *skb));
-+					    struct iwl_rx_packet *pkt));
- 
- int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
- 
-diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
-index 028d505..7fb1688 100644
---- a/drivers/net/wireless/iwlwifi/iwl-dev.h
-+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
-@@ -144,12 +144,13 @@ extern void iwl5000_temperature(struct iwl_priv *priv);
- #define	DEFAULT_LONG_RETRY_LIMIT  4U
- 
- struct iwl_rx_mem_buffer {
--	dma_addr_t real_dma_addr;
--	dma_addr_t aligned_dma_addr;
--	struct sk_buff *skb;
-+	dma_addr_t page_dma;
-+	struct page *page;
- 	struct list_head list;
- };
- 
-+#define rxb_addr(r) page_address(r->page)
-+
- /* defined below */
- struct iwl_device_cmd;
- 
-@@ -165,7 +166,7 @@ struct iwl_cmd_meta {
- 	 */
- 	void (*callback)(struct iwl_priv *priv,
- 			 struct iwl_device_cmd *cmd,
--			 struct sk_buff *skb);
-+			 struct iwl_rx_packet *pkt);
- 
- 	/* The CMD_SIZE_HUGE flag bit indicates that the command
- 	 * structure is stored at the end of the shared queue memory. */
-@@ -358,6 +359,13 @@ enum {
- 
- #define IWL_CMD_MAX_PAYLOAD 320
- 
-+/*
-+ * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header,
-+ * SNAP header and alignment. It should also be big enough for 802.11
-+ * control frames.
-+ */
-+#define IWL_LINK_HDR_MAX 64
-+
- /**
-  * struct iwl_device_cmd
-  *
-@@ -382,10 +390,10 @@ struct iwl_device_cmd {
- 
- struct iwl_host_cmd {
- 	const void *data;
--	struct sk_buff *reply_skb;
-+	unsigned long reply_page;
- 	void (*callback)(struct iwl_priv *priv,
- 			 struct iwl_device_cmd *cmd,
--			 struct sk_buff *skb);
-+			 struct iwl_rx_packet *pkt);
- 	u32 flags;
- 	u16 len;
- 	u8 id;
-@@ -639,7 +647,7 @@ struct iwl_sensitivity_ranges {
-  * @valid_tx/rx_ant: usable antennas
-  * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
-  * @max_rxq_log: Log-base-2 of max_rxq_size
-- * @rx_buf_size: Rx buffer size
-+ * @rx_page_order: Rx buffer page order
-  * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
-  * @max_stations:
-  * @bcast_sta_id:
-@@ -662,9 +670,8 @@ struct iwl_hw_params {
- 	u8  valid_rx_ant;
- 	u16 max_rxq_size;
- 	u16 max_rxq_log;
--	u32 rx_buf_size;
-+	u32 rx_page_order;
- 	u32 rx_wrt_ptr_reg;
--	u32 max_pkt_size;
- 	u8  max_stations;
- 	u8  bcast_sta_id;
- 	u8  ht40_channel;
-@@ -976,7 +983,7 @@ struct iwl_priv {
- 	int frames_count;
- 
- 	enum ieee80211_band band;
--	int alloc_rxb_skb;
-+	int alloc_rxb_page;
- 
- 	void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
- 				       struct iwl_rx_mem_buffer *rxb);
-diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
-index a6856da..1bf17d2 100644
---- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c
-@@ -104,17 +104,8 @@ EXPORT_SYMBOL(get_cmd_string);
- 
- static void iwl_generic_cmd_callback(struct iwl_priv *priv,
- 				     struct iwl_device_cmd *cmd,
--				     struct sk_buff *skb)
-+				     struct iwl_rx_packet *pkt)
- {
--	struct iwl_rx_packet *pkt = NULL;
--
--	if (!skb) {
--		IWL_ERR(priv, "Error: Response NULL in %s.\n",
--				get_cmd_string(cmd->hdr.cmd));
--		return;
--	}
--
--	pkt = (struct iwl_rx_packet *)skb->data;
- 	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
- 			get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
-@@ -216,7 +207,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
- 		ret = -EIO;
- 		goto fail;
- 	}
--	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {
-+	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
- 		IWL_ERR(priv, "Error: Response NULL in '%s'\n",
- 			  get_cmd_string(cmd->id));
- 		ret = -EIO;
-@@ -238,9 +229,9 @@ cancel:
- 							~CMD_WANT_SKB;
- 	}
- fail:
--	if (cmd->reply_skb) {
--		dev_kfree_skb_any(cmd->reply_skb);
--		cmd->reply_skb = NULL;
-+	if (cmd->reply_page) {
-+		free_pages(cmd->reply_page, priv->hw_params.rx_page_order);
-+		cmd->reply_page = 0;
- 	}
- out:
- 	clear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);
-@@ -273,7 +264,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
- 			   u8 id, u16 len, const void *data,
- 			   void (*callback)(struct iwl_priv *priv,
- 					    struct iwl_device_cmd *cmd,
--					    struct sk_buff *skb))
-+					    struct iwl_rx_packet *pkt))
- {
- 	struct iwl_host_cmd cmd = {
- 		.id = id,
-diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
-index 493626b..5e56857 100644
---- a/drivers/net/wireless/iwlwifi/iwl-rx.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
-@@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)
- 		list_del(element);
- 
- 		/* Point to Rx buffer via next RBD in circular buffer */
--		rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr);
-+		rxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma);
- 		rxq->queue[rxq->write] = rxb;
- 		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
- 		rxq->free_count--;
-@@ -239,7 +239,7 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 	struct iwl_rx_queue *rxq = &priv->rxq;
- 	struct list_head *element;
- 	struct iwl_rx_mem_buffer *rxb;
--	struct sk_buff *skb;
-+	struct page *page;
- 	unsigned long flags;
- 
- 	while (1) {
-@@ -252,29 +252,34 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 
- 		if (rxq->free_count > RX_LOW_WATERMARK)
- 			priority |= __GFP_NOWARN;
--		/* Alloc a new receive buffer */
--		skb = alloc_skb(priv->hw_params.rx_buf_size + 256,
--						priority);
- 
--		if (!skb) {
-+		if (priv->hw_params.rx_page_order > 0)
-+			priority |= __GFP_COMP;
-+
-+		/* Alloc a new receive buffer */
-+		page = alloc_pages(priority, priv->hw_params.rx_page_order);
-+		if (!page) {
- 			if (net_ratelimit())
--				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
-+				IWL_DEBUG_INFO(priv, "alloc_pages failed, "
-+					       "order: %d\n",
-+					       priv->hw_params.rx_page_order);
-+
- 			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
- 			    net_ratelimit())
--				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
-+				IWL_CRIT(priv, "Failed to alloc_pages with %s. Only %u free buffers remaining.\n",
- 					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
- 					 rxq->free_count);
- 			/* We don't reschedule replenish work here -- we will
- 			 * call the restock method and if it still needs
- 			 * more buffers it will schedule replenish */
--			break;
-+			return;
- 		}
- 
- 		spin_lock_irqsave(&rxq->lock, flags);
- 
- 		if (list_empty(&rxq->rx_used)) {
- 			spin_unlock_irqrestore(&rxq->lock, flags);
--			dev_kfree_skb_any(skb);
-+			__free_pages(page, priv->hw_params.rx_page_order);
- 			return;
- 		}
- 		element = rxq->rx_used.next;
-@@ -283,24 +288,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 
- 		spin_unlock_irqrestore(&rxq->lock, flags);
- 
--		rxb->skb = skb;
--		/* Get physical address of RB/SKB */
--		rxb->real_dma_addr = pci_map_single(
--					priv->pci_dev,
--					rxb->skb->data,
--					priv->hw_params.rx_buf_size + 256,
--					PCI_DMA_FROMDEVICE);
-+		rxb->page = page;
-+		/* Get physical address of the RB */
-+		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-+				PAGE_SIZE << priv->hw_params.rx_page_order,
-+				PCI_DMA_FROMDEVICE);
- 		/* dma address must be no more than 36 bits */
--		BUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36));
-+		BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
- 		/* and also 256 byte aligned! */
--		rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);
--		skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);
-+		BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
- 
- 		spin_lock_irqsave(&rxq->lock, flags);
- 
- 		list_add_tail(&rxb->list, &rxq->rx_free);
- 		rxq->free_count++;
--		priv->alloc_rxb_skb++;
-+		priv->alloc_rxb_page++;
- 
- 		spin_unlock_irqrestore(&rxq->lock, flags);
- 	}
-@@ -336,12 +338,14 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- {
- 	int i;
- 	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
--		if (rxq->pool[i].skb != NULL) {
--			pci_unmap_single(priv->pci_dev,
--					 rxq->pool[i].real_dma_addr,
--					 priv->hw_params.rx_buf_size + 256,
--					 PCI_DMA_FROMDEVICE);
--			dev_kfree_skb(rxq->pool[i].skb);
-+		if (rxq->pool[i].page != NULL) {
-+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-+				PAGE_SIZE << priv->hw_params.rx_page_order,
-+				PCI_DMA_FROMDEVICE);
-+			__free_pages(rxq->pool[i].page,
-+				     priv->hw_params.rx_page_order);
-+			rxq->pool[i].page = NULL;
-+			priv->alloc_rxb_page--;
- 		}
- 	}
- 
-@@ -405,14 +409,14 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- 	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
- 		/* In the reset function, these buffers may have been allocated
- 		 * to an SKB, so we need to unmap and free potential storage */
--		if (rxq->pool[i].skb != NULL) {
--			pci_unmap_single(priv->pci_dev,
--					 rxq->pool[i].real_dma_addr,
--					 priv->hw_params.rx_buf_size + 256,
--					 PCI_DMA_FROMDEVICE);
--			priv->alloc_rxb_skb--;
--			dev_kfree_skb(rxq->pool[i].skb);
--			rxq->pool[i].skb = NULL;
-+		if (rxq->pool[i].page != NULL) {
-+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-+				PAGE_SIZE << priv->hw_params.rx_page_order,
-+				PCI_DMA_FROMDEVICE);
-+			priv->alloc_rxb_page--;
-+			__free_pages(rxq->pool[i].page,
-+				     priv->hw_params.rx_page_order);
-+			rxq->pool[i].page = NULL;
- 		}
- 		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
- 	}
-@@ -491,7 +495,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
- 				struct iwl_rx_mem_buffer *rxb)
- 
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_missed_beacon_notif *missed_beacon;
- 
- 	missed_beacon = &pkt->u.missed_beacon;
-@@ -554,7 +558,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,
- 			      struct iwl_rx_mem_buffer *rxb)
- {
- 	int change;
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 
- 	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
- 		     (int)sizeof(priv->statistics),
-@@ -878,6 +882,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
- 					struct iwl_rx_mem_buffer *rxb,
- 					struct ieee80211_rx_status *stats)
- {
-+	struct sk_buff *skb;
-+	int ret = 0;
-+
- 	/* We only process data packets if the interface is open */
- 	if (unlikely(!priv->is_open)) {
- 		IWL_DEBUG_DROP_LIMIT(priv,
-@@ -890,15 +897,38 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
- 	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
- 		return;
- 
--	/* Resize SKB from mac header to end of packet */
--	skb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);
--	skb_put(rxb->skb, len);
-+	skb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);
-+	if (!skb) {
-+		IWL_ERR(priv, "alloc_skb failed\n");
-+		return;
-+	}
-+
-+	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
-+
-+	/* mac80211 currently doesn't support paged SKB. Convert it to
-+	 * linear SKB for management frame and data frame requires
-+	 * software decryption or software defragementation. */
-+	if (ieee80211_is_mgmt(hdr->frame_control) ||
-+	    ieee80211_has_protected(hdr->frame_control) ||
-+	    ieee80211_has_morefrags(hdr->frame_control) ||
-+	    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
-+		ret = skb_linearize(skb);
-+	else
-+		ret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?
-+			 0 : -ENOMEM;
-+
-+	if (ret) {
-+		kfree_skb(skb);
-+		goto out;
-+	}
- 
- 	iwl_update_stats(priv, false, hdr->frame_control, len);
--	memcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));
--	ieee80211_rx_irqsafe(priv->hw, rxb->skb);
--	priv->alloc_rxb_skb--;
--	rxb->skb = NULL;
-+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-+
-+	ieee80211_rx(priv->hw, skb);
-+ out:
-+	priv->alloc_rxb_page--;
-+	rxb->page = NULL;
- }
- 
- /* This is necessary only for a number of statistics, see the caller. */
-@@ -926,7 +956,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,
- {
- 	struct ieee80211_hdr *header;
- 	struct ieee80211_rx_status rx_status;
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_rx_phy_res *phy_res;
- 	__le32 rx_pkt_status;
- 	struct iwl4965_rx_mpdu_res_start *amsdu;
-@@ -1087,7 +1117,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx);
- void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
- 				    struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	priv->last_phy_res[0] = 1;
- 	memcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),
- 	       sizeof(struct iwl_rx_phy_res));
-diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
-index 4f3a108..bcccc6f 100644
---- a/drivers/net/wireless/iwlwifi/iwl-scan.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
-@@ -112,7 +112,7 @@ EXPORT_SYMBOL(iwl_scan_cancel_timeout);
- static int iwl_send_scan_abort(struct iwl_priv *priv)
- {
- 	int ret = 0;
--	struct iwl_rx_packet *res;
-+	struct iwl_rx_packet *pkt;
- 	struct iwl_host_cmd cmd = {
- 		.id = REPLY_SCAN_ABORT_CMD,
- 		.flags = CMD_WANT_SKB,
-@@ -132,21 +132,21 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
- 		return ret;
- 	}
- 
--	res = (struct iwl_rx_packet *)cmd.reply_skb->data;
--	if (res->u.status != CAN_ABORT_STATUS) {
-+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-+	if (pkt->u.status != CAN_ABORT_STATUS) {
- 		/* The scan abort will return 1 for success or
- 		 * 2 for "failure".  A failure condition can be
- 		 * due to simply not being in an active scan which
- 		 * can occur if we send the scan abort before we
- 		 * the microcode has notified us that a scan is
- 		 * completed. */
--		IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", res->u.status);
-+		IWL_DEBUG_INFO(priv, "SCAN_ABORT returned %d.\n", pkt->u.status);
- 		clear_bit(STATUS_SCAN_ABORTING, &priv->status);
- 		clear_bit(STATUS_SCAN_HW, &priv->status);
- 	}
- 
--	priv->alloc_rxb_skb--;
--	dev_kfree_skb_any(cmd.reply_skb);
-+	priv->alloc_rxb_page--;
-+	free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
- 
- 	return ret;
- }
-@@ -156,7 +156,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
- 			      struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_scanreq_notification *notif =
- 	    (struct iwl_scanreq_notification *)pkt->u.raw;
- 
-@@ -168,7 +168,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,
- static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
- 				    struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_scanstart_notification *notif =
- 	    (struct iwl_scanstart_notification *)pkt->u.raw;
- 	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
-@@ -187,7 +187,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,
- 				      struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_scanresults_notification *notif =
- 	    (struct iwl_scanresults_notification *)pkt->u.raw;
- 
-@@ -214,7 +214,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,
- 				       struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
- 
- 	IWL_DEBUG_SCAN(priv, "Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
-diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
-index 022bcf1..1ea5cd3 100644
---- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c
-@@ -177,7 +177,7 @@ static int iwl_get_measurement(struct iwl_priv *priv,
- static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
- 					  struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
- 
- 	if (!report->state) {
-diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c
-index c6633fe..dc74c16 100644
---- a/drivers/net/wireless/iwlwifi/iwl-sta.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c
-@@ -99,32 +99,25 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
- 
- static void iwl_add_sta_callback(struct iwl_priv *priv,
- 				 struct iwl_device_cmd *cmd,
--				 struct sk_buff *skb)
-+				 struct iwl_rx_packet *pkt)
- {
--	struct iwl_rx_packet *res = NULL;
- 	struct iwl_addsta_cmd *addsta =
- 		(struct iwl_addsta_cmd *)cmd->cmd.payload;
- 	u8 sta_id = addsta->sta.sta_id;
- 
--	if (!skb) {
--		IWL_ERR(priv, "Error: Response NULL in REPLY_ADD_STA.\n");
--		return;
--	}
--
--	res = (struct iwl_rx_packet *)skb->data;
--	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
--			  res->hdr.flags);
-+			  pkt->hdr.flags);
- 		return;
- 	}
- 
--	switch (res->u.add_sta.status) {
-+	switch (pkt->u.add_sta.status) {
- 	case ADD_STA_SUCCESS_MSK:
- 		iwl_sta_ucode_activate(priv, sta_id);
- 		 /* fall through */
- 	default:
- 		IWL_DEBUG_HC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
--			     res->u.add_sta.status);
-+			     pkt->u.add_sta.status);
- 		break;
- 	}
- }
-@@ -132,7 +125,7 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,
- int iwl_send_add_sta(struct iwl_priv *priv,
- 		     struct iwl_addsta_cmd *sta, u8 flags)
- {
--	struct iwl_rx_packet *res = NULL;
-+	struct iwl_rx_packet *pkt = NULL;
- 	int ret = 0;
- 	u8 data[sizeof(*sta)];
- 	struct iwl_host_cmd cmd = {
-@@ -152,15 +145,15 @@ int iwl_send_add_sta(struct iwl_priv *priv,
- 	if (ret || (flags & CMD_ASYNC))
- 		return ret;
- 
--	res = (struct iwl_rx_packet *)cmd.reply_skb->data;
--	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
--			  res->hdr.flags);
-+			  pkt->hdr.flags);
- 		ret = -EIO;
- 	}
- 
- 	if (ret == 0) {
--		switch (res->u.add_sta.status) {
-+		switch (pkt->u.add_sta.status) {
- 		case ADD_STA_SUCCESS_MSK:
- 			iwl_sta_ucode_activate(priv, sta->sta.sta_id);
- 			IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
-@@ -172,8 +165,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,
- 		}
- 	}
- 
--	priv->alloc_rxb_skb--;
--	dev_kfree_skb_any(cmd.reply_skb);
-+	priv->alloc_rxb_page--;
-+	free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
- 
- 	return ret;
- }
-@@ -324,26 +317,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)
- 
- static void iwl_remove_sta_callback(struct iwl_priv *priv,
- 				    struct iwl_device_cmd *cmd,
--				    struct sk_buff *skb)
-+				    struct iwl_rx_packet *pkt)
- {
--	struct iwl_rx_packet *res = NULL;
- 	struct iwl_rem_sta_cmd *rm_sta =
--		 (struct iwl_rem_sta_cmd *)cmd->cmd.payload;
-+			(struct iwl_rem_sta_cmd *)cmd->cmd.payload;
- 	const char *addr = rm_sta->addr;
- 
--	if (!skb) {
--		IWL_ERR(priv, "Error: Response NULL in REPLY_REMOVE_STA.\n");
--		return;
--	}
--
--	res = (struct iwl_rx_packet *)skb->data;
--	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
--		res->hdr.flags);
-+		pkt->hdr.flags);
- 		return;
- 	}
- 
--	switch (res->u.rem_sta.status) {
-+	switch (pkt->u.rem_sta.status) {
- 	case REM_STA_SUCCESS_MSK:
- 		iwl_sta_ucode_deactivate(priv, addr);
- 		break;
-@@ -356,7 +342,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv,
- static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
- 				   u8 flags)
- {
--	struct iwl_rx_packet *res = NULL;
-+	struct iwl_rx_packet *pkt;
- 	int ret;
- 
- 	struct iwl_rem_sta_cmd rm_sta_cmd;
-@@ -381,15 +367,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
- 	if (ret || (flags & CMD_ASYNC))
- 		return ret;
- 
--	res = (struct iwl_rx_packet *)cmd.reply_skb->data;
--	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
--			  res->hdr.flags);
-+			  pkt->hdr.flags);
- 		ret = -EIO;
- 	}
- 
- 	if (!ret) {
--		switch (res->u.rem_sta.status) {
-+		switch (pkt->u.rem_sta.status) {
- 		case REM_STA_SUCCESS_MSK:
- 			iwl_sta_ucode_deactivate(priv, addr);
- 			IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
-@@ -401,8 +387,8 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,
- 		}
- 	}
- 
--	priv->alloc_rxb_skb--;
--	dev_kfree_skb_any(cmd.reply_skb);
-+	priv->alloc_rxb_page--;
-+	free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
- 
- 	return ret;
- }
-diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
-index fb9bcfa..a98d60d 100644
---- a/drivers/net/wireless/iwlwifi/iwl-tx.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
-@@ -1132,7 +1132,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
-  */
- void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
- 	int txq_id = SEQ_TO_QUEUE(sequence);
- 	int index = SEQ_TO_INDEX(sequence);
-@@ -1159,10 +1159,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
- 
- 	/* Input error checking is done when commands are added to queue. */
- 	if (meta->flags & CMD_WANT_SKB) {
--		meta->source->reply_skb = rxb->skb;
--		rxb->skb = NULL;
-+		meta->source->reply_page = (unsigned long)rxb_addr(rxb);
-+		rxb->page = NULL;
- 	} else if (meta->callback)
--		meta->callback(priv, cmd, rxb->skb);
-+		meta->callback(priv, cmd, pkt);
- 
- 	iwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
- 
-@@ -1421,7 +1421,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
- void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
- 					   struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
- 	struct iwl_tx_queue *txq = NULL;
- 	struct iwl_ht_agg *agg;
-diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
-index d00a803..e20690d 100644
---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
-+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
-@@ -758,7 +758,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
- 			       u8 type)
- {
- 	struct iwl_spectrum_cmd spectrum;
--	struct iwl_rx_packet *res;
-+	struct iwl_rx_packet *pkt;
- 	struct iwl_host_cmd cmd = {
- 		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
- 		.data = (void *)&spectrum,
-@@ -803,18 +803,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
- 	if (rc)
- 		return rc;
- 
--	res = (struct iwl_rx_packet *)cmd.reply_skb->data;
--	if (res->hdr.flags & IWL_CMD_FAILED_MSK) {
-+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
- 		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
- 		rc = -EIO;
- 	}
- 
--	spectrum_resp_status = le16_to_cpu(res->u.spectrum.status);
-+	spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
- 	switch (spectrum_resp_status) {
- 	case 0:		/* Command will be handled */
--		if (res->u.spectrum.id != 0xff) {
-+		if (pkt->u.spectrum.id != 0xff) {
- 			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
--						res->u.spectrum.id);
-+						pkt->u.spectrum.id);
- 			priv->measurement_status &= ~MEASUREMENT_READY;
- 		}
- 		priv->measurement_status |= MEASUREMENT_ACTIVE;
-@@ -826,7 +826,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
- 		break;
- 	}
- 
--	dev_kfree_skb_any(cmd.reply_skb);
-+	free_pages(cmd.reply_page, priv->hw_params.rx_page_order);
- 
- 	return rc;
- }
-@@ -835,7 +835,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,
- static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
- 			       struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl_alive_resp *palive;
- 	struct delayed_work *pwork;
- 
-@@ -872,7 +872,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
- 				 struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- #endif
- 
- 	IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
-@@ -908,7 +908,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
- 				struct iwl_rx_mem_buffer *rxb)
- {
- #ifdef CONFIG_IWLWIFI_DEBUG
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
- 	u8 rate = beacon->beacon_notify_hdr.rate;
- 
-@@ -931,7 +931,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
- static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
- 				    struct iwl_rx_mem_buffer *rxb)
- {
--	struct iwl_rx_packet *pkt = (void *)rxb->skb->data;
-+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
- 	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
- 	unsigned long status = priv->status;
- 
-@@ -1095,7 +1095,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)
- 		list_del(element);
- 
- 		/* Point to Rx buffer via next RBD in circular buffer */
--		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr);
-+		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
- 		rxq->queue[rxq->write] = rxb;
- 		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
- 		rxq->free_count--;
-@@ -1135,7 +1135,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 	struct iwl_rx_queue *rxq = &priv->rxq;
- 	struct list_head *element;
- 	struct iwl_rx_mem_buffer *rxb;
--	struct sk_buff *skb;
-+	struct page *page;
- 	unsigned long flags;
- 
- 	while (1) {
-@@ -1149,9 +1149,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 
- 		if (rxq->free_count > RX_LOW_WATERMARK)
- 			priority |= __GFP_NOWARN;
-+
-+		if (priv->hw_params.rx_page_order > 0)
-+			priority |= __GFP_COMP;
-+
- 		/* Alloc a new receive buffer */
--		skb = alloc_skb(priv->hw_params.rx_buf_size, priority);
--		if (!skb) {
-+		page = alloc_pages(priority, priv->hw_params.rx_page_order);
-+		if (!page) {
- 			if (net_ratelimit())
- 				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
- 			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-@@ -1168,7 +1172,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 		spin_lock_irqsave(&rxq->lock, flags);
- 		if (list_empty(&rxq->rx_used)) {
- 			spin_unlock_irqrestore(&rxq->lock, flags);
--			dev_kfree_skb_any(skb);
-+			__free_pages(page, priv->hw_params.rx_page_order);
- 			return;
- 		}
- 		element = rxq->rx_used.next;
-@@ -1176,26 +1180,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 		list_del(element);
- 		spin_unlock_irqrestore(&rxq->lock, flags);
- 
--		rxb->skb = skb;
--
--		/* If radiotap head is required, reserve some headroom here.
--		 * The physical head count is a variable rx_stats->phy_count.
--		 * We reserve 4 bytes here. Plus these extra bytes, the
--		 * headroom of the physical head should be enough for the
--		 * radiotap head that iwl3945 supported. See iwl3945_rt.
--		 */
--		skb_reserve(rxb->skb, 4);
--
-+		rxb->page = page;
- 		/* Get physical address of RB/SKB */
--		rxb->real_dma_addr = pci_map_single(priv->pci_dev,
--						rxb->skb->data,
--						priv->hw_params.rx_buf_size,
--						PCI_DMA_FROMDEVICE);
-+		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-+				PAGE_SIZE << priv->hw_params.rx_page_order,
-+				PCI_DMA_FROMDEVICE);
- 
- 		spin_lock_irqsave(&rxq->lock, flags);
-+
- 		list_add_tail(&rxb->list, &rxq->rx_free);
--		priv->alloc_rxb_skb++;
- 		rxq->free_count++;
-+		priv->alloc_rxb_page++;
-+
- 		spin_unlock_irqrestore(&rxq->lock, flags);
- 	}
- }
-@@ -1211,14 +1207,14 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- 	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
- 		/* In the reset function, these buffers may have been allocated
- 		 * to an SKB, so we need to unmap and free potential storage */
--		if (rxq->pool[i].skb != NULL) {
--			pci_unmap_single(priv->pci_dev,
--					 rxq->pool[i].real_dma_addr,
--					 priv->hw_params.rx_buf_size,
--					 PCI_DMA_FROMDEVICE);
--			priv->alloc_rxb_skb--;
--			dev_kfree_skb(rxq->pool[i].skb);
--			rxq->pool[i].skb = NULL;
-+		if (rxq->pool[i].page != NULL) {
-+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-+				PAGE_SIZE << priv->hw_params.rx_page_order,
-+				PCI_DMA_FROMDEVICE);
-+			priv->alloc_rxb_page--;
-+			__free_pages(rxq->pool[i].page,
-+				     priv->hw_params.rx_page_order);
-+			rxq->pool[i].page = NULL;
- 		}
- 		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
- 	}
-@@ -1226,8 +1222,8 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
- 	/* Set us so that we have processed and used all buffers, but have
- 	 * not restocked the Rx queue with fresh buffers */
- 	rxq->read = rxq->write = 0;
--	rxq->free_count = 0;
- 	rxq->write_actual = 0;
-+	rxq->free_count = 0;
- 	spin_unlock_irqrestore(&rxq->lock, flags);
- }
- 
-@@ -1260,12 +1256,14 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx
- {
- 	int i;
- 	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
--		if (rxq->pool[i].skb != NULL) {
--			pci_unmap_single(priv->pci_dev,
--					 rxq->pool[i].real_dma_addr,
--					 priv->hw_params.rx_buf_size,
--					 PCI_DMA_FROMDEVICE);
--			dev_kfree_skb(rxq->pool[i].skb);
-+		if (rxq->pool[i].page != NULL) {
-+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-+				PAGE_SIZE << priv->hw_params.rx_page_order,
-+				PCI_DMA_FROMDEVICE);
-+			__free_pages(rxq->pool[i].page,
-+				     priv->hw_params.rx_page_order);
-+			rxq->pool[i].page = NULL;
-+			priv->alloc_rxb_page--;
- 		}
- 	}
- 
-@@ -1401,10 +1399,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
- 
- 		rxq->queue[i] = NULL;
- 
--		pci_unmap_single(priv->pci_dev, rxb->real_dma_addr,
--				priv->hw_params.rx_buf_size,
--				PCI_DMA_FROMDEVICE);
--		pkt = (struct iwl_rx_packet *)rxb->skb->data;
-+		pci_unmap_page(priv->pci_dev, rxb->page_dma,
-+			       PAGE_SIZE << priv->hw_params.rx_page_order,
-+			       PCI_DMA_FROMDEVICE);
-+		pkt = rxb_addr(rxb);
- 
- 		/* Reclaim a command buffer only if this packet is a response
- 		 *   to a (driver-originated) command.
-@@ -1426,16 +1424,17 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
- 			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
- 		} else {
- 			/* No handling needed */
--			IWL_DEBUG_RX(priv, "r %d i %d No handler needed for %s, 0x%02x\n",
-+			IWL_DEBUG_RX(priv,
-+				"r %d i %d No handler needed for %s, 0x%02x\n",
- 				r, i, get_cmd_string(pkt->hdr.cmd),
- 				pkt->hdr.cmd);
- 		}
- 
- 		if (reclaim) {
--			/* Invoke any callbacks, transfer the skb to caller, and
--			 * fire off the (possibly) blocking iwl_send_cmd()
-+			/* Invoke any callbacks, transfer the buffer to caller,
-+			 * and fire off the (possibly) blocking iwl_send_cmd()
- 			 * as we reclaim the driver command queue */
--			if (rxb && rxb->skb)
-+			if (rxb && rxb->page)
- 				iwl_tx_cmd_complete(priv, rxb);
- 			else
- 				IWL_WARN(priv, "Claim null rxb?\n");
-@@ -1444,10 +1443,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
- 		/* For now we just don't re-use anything.  We can tweak this
- 		 * later to try and re-use notification packets and SKBs that
- 		 * fail to Rx correctly */
--		if (rxb->skb != NULL) {
--			priv->alloc_rxb_skb--;
--			dev_kfree_skb_any(rxb->skb);
--			rxb->skb = NULL;
-+		if (rxb->page != NULL) {
-+			priv->alloc_rxb_page--;
-+			__free_pages(rxb->page, priv->hw_params.rx_page_order);
-+			rxb->page = NULL;
- 		}
- 
- 		spin_lock_irqsave(&rxq->lock, flags);
-@@ -1685,6 +1684,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
- 	}
- #endif
- 
-+	spin_unlock_irqrestore(&priv->lock, flags);
-+
- 	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
- 	 * atomic, make sure that inta covers all the interrupts that
- 	 * we've discovered, even if FH interrupt came in just after
-@@ -1706,8 +1707,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
- 
- 		handled |= CSR_INT_BIT_HW_ERR;
- 
--		spin_unlock_irqrestore(&priv->lock, flags);
--
- 		return;
- 	}
- 
-@@ -1799,7 +1798,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)
- 			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
- 	}
- #endif
--	spin_unlock_irqrestore(&priv->lock, flags);
- }
- 
- static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
--- 
-1.5.6.3
diff --git a/a/3.hdr b/a/3.hdr
deleted file mode 100644
index 52c17ce..0000000
--- a/a/3.hdr
+++ /dev/null
@@ -1,3 +0,0 @@
-Content-Disposition: attachment; filename="0002-iwlwifi-fix-use-after-free-bug-for-paged-rx.patch"
-Content-Type: text/x-patch; name="0002-iwlwifi-fix-use-after-free-bug-for-paged-rx.patch"; charset="UTF-8"
-Content-Transfer-Encoding: 7bit
diff --git a/a/3.txt b/a/3.txt
deleted file mode 100644
index 35abb91..0000000
--- a/a/3.txt
+++ /dev/null
@@ -1,227 +0,0 @@
-From 000c60eef9bf7a579c02ccb7deee447a2231d2b0 Mon Sep 17 00:00:00 2001
-From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-Date: Thu, 15 Oct 2009 20:00:57 -0700
-Subject: [PATCH 2/2] iwlwifi: fix use after free bug for paged rx
-
-In the paged rx patch (4854fde2), I introduced a bug that could possibly
-touch an already freed page. It is fixed by avoiding the access in this
-patch. I've also added some comments so that other people touching the
-code won't make the same mistake. In the future, if we cannot avoid
-access the page after being handled to the upper layer, we can use
-get_page/put_page to handle it. For now, it's just not necessary.
-
-It also fixed a debug message print bug reported by Stanislaw Gruszka
-<sgruszka-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>.
-
-Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-Signed-off-by: Reinette Chatre <reinette.chatre-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
----
- drivers/net/wireless/iwlwifi/iwl-3945.c     |   16 +++++++++++-----
- drivers/net/wireless/iwlwifi/iwl-agn.c      |   11 +++++++++--
- drivers/net/wireless/iwlwifi/iwl-rx.c       |   21 ++++++++++++++-------
- drivers/net/wireless/iwlwifi/iwl3945-base.c |   18 +++++++++++++-----
- 4 files changed, 47 insertions(+), 19 deletions(-)
-
-diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
-index 7d5962d..4406650 100644
---- a/drivers/net/wireless/iwlwifi/iwl-3945.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
-@@ -552,6 +552,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
- 	u16 len = le16_to_cpu(rx_hdr->len);
- 	struct sk_buff *skb;
- 	int ret;
-+	__le16 fc = hdr->frame_control;
- 
- 	/* We received data from the HW, so stop the watchdog */
- 	if (unlikely(len + IWL39_RX_FRAME_SIZE >
-@@ -584,9 +585,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
- 	/* mac80211 currently doesn't support paged SKB. Convert it to
- 	 * linear SKB for management frame and data frame requires
- 	 * software decryption or software defragementation. */
--	if (ieee80211_is_mgmt(hdr->frame_control) ||
--	    ieee80211_has_protected(hdr->frame_control) ||
--	    ieee80211_has_morefrags(hdr->frame_control) ||
-+	if (ieee80211_is_mgmt(fc) ||
-+	    ieee80211_has_protected(fc) ||
-+	    ieee80211_has_morefrags(fc) ||
- 	    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
- 		ret = skb_linearize(skb);
- 	else
-@@ -598,11 +599,16 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
- 		goto out;
- 	}
- 
-+	/*
-+	 * XXX: We cannot touch the page and its virtual memory (pkt) after
-+	 * here. It might have already been freed by the above skb change.
-+	 */
-+
- #ifdef CONFIG_IWLWIFI_LEDS
--	if (ieee80211_is_data(hdr->frame_control))
-+	if (ieee80211_is_data(fc))
- 		priv->rxtxpackets += len;
- #endif
--	iwl_update_stats(priv, false, hdr->frame_control, len);
-+	iwl_update_stats(priv, false, fc, len);
- 
- 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
- 	ieee80211_rx(priv->hw, skb);
-diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
-index c5ff7c0..475f677 100644
---- a/drivers/net/wireless/iwlwifi/iwl-agn.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
-@@ -808,8 +808,8 @@ void iwl_rx_handle(struct iwl_priv *priv)
- 		if (priv->rx_handlers[pkt->hdr.cmd]) {
- 			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
- 				i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
--			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
- 			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
- 		} else {
- 			/* No handling needed */
- 			IWL_DEBUG_RX(priv,
-@@ -818,11 +818,18 @@ void iwl_rx_handle(struct iwl_priv *priv)
- 				pkt->hdr.cmd);
- 		}
- 
-+		/*
-+		 * XXX: After here, we should always check rxb->page
-+		 * against NULL before touching it or its virtual
-+		 * memory (pkt). Because some rx_handler might have
-+		 * already taken or freed the pages.
-+		 */
-+
- 		if (reclaim) {
- 			/* Invoke any callbacks, transfer the buffer to caller,
- 			 * and fire off the (possibly) blocking iwl_send_cmd()
- 			 * as we reclaim the driver command queue */
--			if (rxb && rxb->page)
-+			if (rxb->page)
- 				iwl_tx_cmd_complete(priv, rxb);
- 			else
- 				IWL_WARN(priv, "Claim null rxb?\n");
-diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c
-index 5e56857..2663689 100644
---- a/drivers/net/wireless/iwlwifi/iwl-rx.c
-+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c
-@@ -241,6 +241,7 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 	struct iwl_rx_mem_buffer *rxb;
- 	struct page *page;
- 	unsigned long flags;
-+	gfp_t gfp_mask = priority;
- 
- 	while (1) {
- 		spin_lock_irqsave(&rxq->lock, flags);
-@@ -251,13 +252,13 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 		spin_unlock_irqrestore(&rxq->lock, flags);
- 
- 		if (rxq->free_count > RX_LOW_WATERMARK)
--			priority |= __GFP_NOWARN;
-+			gfp_mask |= __GFP_NOWARN;
- 
- 		if (priv->hw_params.rx_page_order > 0)
--			priority |= __GFP_COMP;
-+			gfp_mask |= __GFP_COMP;
- 
- 		/* Alloc a new receive buffer */
--		page = alloc_pages(priority, priv->hw_params.rx_page_order);
-+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
- 		if (!page) {
- 			if (net_ratelimit())
- 				IWL_DEBUG_INFO(priv, "alloc_pages failed, "
-@@ -884,6 +885,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
- {
- 	struct sk_buff *skb;
- 	int ret = 0;
-+	__le16 fc = hdr->frame_control;
- 
- 	/* We only process data packets if the interface is open */
- 	if (unlikely(!priv->is_open)) {
-@@ -908,9 +910,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
- 	/* mac80211 currently doesn't support paged SKB. Convert it to
- 	 * linear SKB for management frame and data frame requires
- 	 * software decryption or software defragementation. */
--	if (ieee80211_is_mgmt(hdr->frame_control) ||
--	    ieee80211_has_protected(hdr->frame_control) ||
--	    ieee80211_has_morefrags(hdr->frame_control) ||
-+	if (ieee80211_is_mgmt(fc) ||
-+	    ieee80211_has_protected(fc) ||
-+	    ieee80211_has_morefrags(fc) ||
- 	    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
- 		ret = skb_linearize(skb);
- 	else
-@@ -922,7 +924,12 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
- 		goto out;
- 	}
- 
--	iwl_update_stats(priv, false, hdr->frame_control, len);
-+	/*
-+	 * XXX: We cannot touch the page and its virtual memory (hdr) after
-+	 * here. It might have already been freed by the above skb change.
-+	 */
-+
-+	iwl_update_stats(priv, false, fc, len);
- 	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
- 
- 	ieee80211_rx(priv->hw, skb);
-diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
-index e20690d..5ae8698 100644
---- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
-+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
-@@ -1137,6 +1137,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 	struct iwl_rx_mem_buffer *rxb;
- 	struct page *page;
- 	unsigned long flags;
-+	gfp_t gfp_mask = priority;
- 
- 	while (1) {
- 		spin_lock_irqsave(&rxq->lock, flags);
-@@ -1148,13 +1149,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
- 		spin_unlock_irqrestore(&rxq->lock, flags);
- 
- 		if (rxq->free_count > RX_LOW_WATERMARK)
--			priority |= __GFP_NOWARN;
-+			gfp_mask |= __GFP_NOWARN;
- 
- 		if (priv->hw_params.rx_page_order > 0)
--			priority |= __GFP_COMP;
-+			gfp_mask |= __GFP_COMP;
- 
- 		/* Alloc a new receive buffer */
--		page = alloc_pages(priority, priv->hw_params.rx_page_order);
-+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
- 		if (!page) {
- 			if (net_ratelimit())
- 				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
-@@ -1420,8 +1421,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
- 		if (priv->rx_handlers[pkt->hdr.cmd]) {
- 			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
- 				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
--			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
- 			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
- 		} else {
- 			/* No handling needed */
- 			IWL_DEBUG_RX(priv,
-@@ -1430,11 +1431,18 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
- 				pkt->hdr.cmd);
- 		}
- 
-+		/*
-+		 * XXX: After here, we should always check rxb->page
-+		 * against NULL before touching it or its virtual
-+		 * memory (pkt). Because some rx_handler might have
-+		 * already taken or freed the pages.
-+		 */
-+
- 		if (reclaim) {
- 			/* Invoke any callbacks, transfer the buffer to caller,
- 			 * and fire off the (possibly) blocking iwl_send_cmd()
- 			 * as we reclaim the driver command queue */
--			if (rxb && rxb->page)
-+			if (rxb->page)
- 				iwl_tx_cmd_complete(priv, rxb);
- 			else
- 				IWL_WARN(priv, "Claim null rxb?\n");
--- 
-1.5.6.3
diff --git a/a/content_digest b/N2/content_digest
index 33cc605..834781f 100644
--- a/a/content_digest
+++ b/N2/content_digest
@@ -2,24 +2,23 @@
  "ref\0200910150402.03953.elendil@planet.nl\0"
  "ref\01255620567.21134.162.camel@rc-desk\0"
  "ref\0200910152142.02876.elendil@planet.nl\0"
- "ref\0200910152142.02876.elendil-EIBgga6/0yRmR6Xm/wNWPw@public.gmane.org\0"
- "From\0reinette chatre <reinette.chatre-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\0"
+ "From\0reinette chatre <reinette.chatre@intel.com>\0"
  "Subject\0Re: [Bug #14141] order 2 page allocation failures in iwlagn\0"
  "Date\0Fri, 16 Oct 2009 22:42:23 -0700\0"
- "To\0Frans Pop <elendil-EIBgga6/0yRmR6Xm/wNWPw@public.gmane.org>\0"
- "Cc\0Mel Gorman <mel-wPRd99KPJ+uzQB+pC5nmwQ@public.gmane.org>"
-  David Rientjes <rientjes-hpIqsD4AKlfQT0dZR+AlfA@public.gmane.org>
-  KOSAKI Motohiro <kosaki.motohiro-+CUm20s59erQFUHtdCDX3A@public.gmane.org>
-  Rafael J. Wysocki <rjw-KKrjLPT3xs0@public.gmane.org>
-  Linux Kernel Mailing List <linux-kernel-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
-  Kernel Testers List <kernel-testers-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
-  Pekka Enberg <penberg-bbCR+/B0CizivPeTLB3BmA@public.gmane.org>
-  Bartlomiej Zolnierkiewicz <bzolnier-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
-  Karol Lewandowski <karol.k.lewandowski-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
+ "To\0Frans Pop <elendil@planet.nl>\0"
+ "Cc\0Mel Gorman <mel@csn.ul.ie>"
+  David Rientjes <rientjes@google.com>
+  KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
+  Rafael J. Wysocki <rjw@sisk.pl>
+  Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
+  Kernel Testers List <kernel-testers@vger.kernel.org>
+  Pekka Enberg <penberg@cs.helsinki.fi>
+  Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
+  Karol Lewandowski <karol.k.lewandowski@gmail.com>
   Abbas
-  Mohamed <mohamed.abbas-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
-  John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>
- " linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org <linux-mm-Bw31MaZKKs3YtjvyW6yDsg@public.gmane.org>\0"
+  Mohamed <mohamed.abbas@intel.com>
+  John W. Linville <linville@tuxdriver.com>
+ " linux-mm@kvack.org <linux-mm@kvack.org>\0"
  "\01:1\0"
  "b\0"
  "Hi Frans,\n"
@@ -52,1631 +51,5 @@
  "\01:2\0"
  "fn\00001-iwlwifi-use-paged-Rx.patch\0"
  "b\0"
- "From d94fc37fb25aacec8a41e3d14ec333fa5a8f681e Mon Sep 17 00:00:00 2001\n"
- "From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "Date: Fri, 9 Oct 2009 17:19:45 +0800\n"
- "Subject: [PATCH 1/2] iwlwifi: use paged Rx\n"
- "\n"
- "This switches the iwlwifi driver to use paged skb from linear skb for Rx\n"
- "buffer. So that it relieves some Rx buffer allocation pressure for the\n"
- "memory subsystem. Currently iwlwifi (4K for 3945) requests 8K bytes for\n"
- "Rx buffer. Due to the trailing skb_shared_info in the skb->data,\n"
- "alloc_skb() will do the next order allocation, which is 16K bytes. This\n"
- "is suboptimal and more likely to fail when the system is under memory\n"
- "usage pressure. Switching to paged Rx skb lets us allocate the RXB\n"
- "directly by alloc_pages(), so that only order 1 allocation is required.\n"
- "\n"
- "It also adjusts the area spin_lock (with IRQ disabled) protected in the\n"
- "tasklet because tasklet guarentees to run only on one CPU and the new\n"
- "unprotected code can be preempted by the IRQ handler. This saves us from\n"
- "spawning another workqueue to make skb_linearize/__pskb_pull_tail happy\n"
- "(which cannot be called in hard irq context).\n"
- "\n"
- "Finally, mac80211 doesn't support paged Rx yet. So we linearize the skb\n"
- "for all the management frames and software decryption or defragmentation\n"
- "required data frames before handed to mac80211. For all the other frames,\n"
- "we __pskb_pull_tail 64 bytes in the linear area of the skb for mac80211\n"
- "to handle them properly.\n"
- "\n"
- "Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "Signed-off-by: John W. Linville <linville-2XuSBdqkA4R54TAoqtyWWQ@public.gmane.org>\n"
- "---\n"
- " drivers/net/wireless/iwlwifi/iwl-3945.c     |   67 ++++++++++-----\n"
- " drivers/net/wireless/iwlwifi/iwl-4965.c     |    2 +-\n"
- " drivers/net/wireless/iwlwifi/iwl-5000.c     |    4 +-\n"
- " drivers/net/wireless/iwlwifi/iwl-agn.c      |   42 ++++-----\n"
- " drivers/net/wireless/iwlwifi/iwl-commands.h |   10 ++\n"
- " drivers/net/wireless/iwlwifi/iwl-core.c     |   13 ++--\n"
- " drivers/net/wireless/iwlwifi/iwl-core.h     |    2 +-\n"
- " drivers/net/wireless/iwlwifi/iwl-dev.h      |   27 ++++--\n"
- " drivers/net/wireless/iwlwifi/iwl-hcmd.c     |   21 ++----\n"
- " drivers/net/wireless/iwlwifi/iwl-rx.c       |  122 +++++++++++++++++----------\n"
- " drivers/net/wireless/iwlwifi/iwl-scan.c     |   20 ++--\n"
- " drivers/net/wireless/iwlwifi/iwl-spectrum.c |    2 +-\n"
- " drivers/net/wireless/iwlwifi/iwl-sta.c      |   62 +++++--------\n"
- " drivers/net/wireless/iwlwifi/iwl-tx.c       |   10 +-\n"
- " drivers/net/wireless/iwlwifi/iwl3945-base.c |  120 +++++++++++++-------------\n"
- " 15 files changed, 284 insertions(+), 240 deletions(-)\n"
- "\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c\n"
- "index f059b49..7d5962d 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-3945.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c\n"
- "@@ -293,7 +293,7 @@ static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,\n"
- " static void iwl3945_rx_reply_tx(struct iwl_priv *priv,\n"
- " \t\t\t    struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu16 sequence = le16_to_cpu(pkt->hdr.sequence);\n"
- " \tint txq_id = SEQ_TO_QUEUE(sequence);\n"
- " \tint index = SEQ_TO_INDEX(sequence);\n"
- "@@ -353,7 +353,7 @@ static void iwl3945_rx_reply_tx(struct iwl_priv *priv,\n"
- " void iwl3945_hw_rx_statistics(struct iwl_priv *priv,\n"
- " \t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tIWL_DEBUG_RX(priv, \"Statistics notification received (%d vs %d).\\n\",\n"
- " \t\t     (int)sizeof(struct iwl3945_notif_statistics),\n"
- " \t\t     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);\n"
- "@@ -545,14 +545,17 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t\t\t\t   struct iwl_rx_mem_buffer *rxb,\n"
- " \t\t\t\t   struct ieee80211_rx_status *stats)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);\n"
- " \tstruct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);\n"
- " \tstruct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);\n"
- "-\tshort len = le16_to_cpu(rx_hdr->len);\n"
- "+\tu16 len = le16_to_cpu(rx_hdr->len);\n"
- "+\tstruct sk_buff *skb;\n"
- "+\tint ret;\n"
- " \n"
- " \t/* We received data from the HW, so stop the watchdog */\n"
- "-\tif (unlikely((len + IWL39_RX_FRAME_SIZE) > skb_tailroom(rxb->skb))) {\n"
- "+\tif (unlikely(len + IWL39_RX_FRAME_SIZE >\n"
- "+\t\t     PAGE_SIZE << priv->hw_params.rx_page_order)) {\n"
- " \t\tIWL_DEBUG_DROP(priv, \"Corruption detected!\\n\");\n"
- " \t\treturn;\n"
- " \t}\n"
- "@@ -564,24 +567,49 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t\treturn;\n"
- " \t}\n"
- " \n"
- "-\tskb_reserve(rxb->skb, (void *)rx_hdr->payload - (void *)pkt);\n"
- "-\t/* Set the size of the skb to the size of the frame */\n"
- "-\tskb_put(rxb->skb, le16_to_cpu(rx_hdr->len));\n"
- "+\tskb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);\n"
- "+\tif (!skb) {\n"
- "+\t\tIWL_ERR(priv, \"alloc_skb failed\\n\");\n"
- "+\t\treturn;\n"
- "+\t}\n"
- " \n"
- " \tif (!iwl3945_mod_params.sw_crypto)\n"
- " \t\tiwl_set_decrypted_flag(priv,\n"
- "-\t\t\t\t       (struct ieee80211_hdr *)rxb->skb->data,\n"
- "+\t\t\t\t       (struct ieee80211_hdr *)rxb_addr(rxb),\n"
- " \t\t\t\t       le32_to_cpu(rx_end->status), stats);\n"
- " \n"
- "+\tskb_add_rx_frag(skb, 0, rxb->page,\n"
- "+\t\t\t(void *)rx_hdr->payload - (void *)pkt, len);\n"
- "+\n"
- "+\t/* mac80211 currently doesn't support paged SKB. Convert it to\n"
- "+\t * linear SKB for management frame and data frame requires\n"
- "+\t * software decryption or software defragementation. */\n"
- "+\tif (ieee80211_is_mgmt(hdr->frame_control) ||\n"
- "+\t    ieee80211_has_protected(hdr->frame_control) ||\n"
- "+\t    ieee80211_has_morefrags(hdr->frame_control) ||\n"
- "+\t    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)\n"
- "+\t\tret = skb_linearize(skb);\n"
- "+\telse\n"
- "+\t\tret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?\n"
- "+\t\t\t0 : -ENOMEM;\n"
- "+\n"
- "+\tif (ret) {\n"
- "+\t\tkfree_skb(skb);\n"
- "+\t\tgoto out;\n"
- "+\t}\n"
- "+\n"
- " #ifdef CONFIG_IWLWIFI_LEDS\n"
- " \tif (ieee80211_is_data(hdr->frame_control))\n"
- " \t\tpriv->rxtxpackets += len;\n"
- " #endif\n"
- " \tiwl_update_stats(priv, false, hdr->frame_control, len);\n"
- " \n"
- "-\tmemcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));\n"
- "-\tieee80211_rx_irqsafe(priv->hw, rxb->skb);\n"
- "-\trxb->skb = NULL;\n"
- "+\tmemcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));\n"
- "+\tieee80211_rx(priv->hw, skb);\n"
- "+\n"
- "+ out:\n"
- "+\tpriv->alloc_rxb_page--;\n"
- "+\trxb->page = NULL;\n"
- " }\n"
- " \n"
- " #define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)\n"
- "@@ -591,7 +619,7 @@ static void iwl3945_rx_reply_rx(struct iwl_priv *priv,\n"
- " {\n"
- " \tstruct ieee80211_hdr *header;\n"
- " \tstruct ieee80211_rx_status rx_status;\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);\n"
- " \tstruct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);\n"
- " \tstruct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);\n"
- "@@ -1858,7 +1886,7 @@ int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)\n"
- " static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)\n"
- " {\n"
- " \tint rc = 0;\n"
- "-\tstruct iwl_rx_packet *res = NULL;\n"
- "+\tstruct iwl_rx_packet *pkt;\n"
- " \tstruct iwl3945_rxon_assoc_cmd rxon_assoc;\n"
- " \tstruct iwl_host_cmd cmd = {\n"
- " \t\t.id = REPLY_RXON_ASSOC,\n"
- "@@ -1887,14 +1915,14 @@ static int iwl3945_send_rxon_assoc(struct iwl_priv *priv)\n"
- " \tif (rc)\n"
- " \t\treturn rc;\n"
- " \n"
- "-\tres = (struct iwl_rx_packet *)cmd.reply_skb->data;\n"
- "-\tif (res->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- "+\tpkt = (struct iwl_rx_packet *)cmd.reply_page;\n"
- "+\tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from REPLY_RXON_ASSOC command\\n\");\n"
- " \t\trc = -EIO;\n"
- " \t}\n"
- " \n"
- "-\tpriv->alloc_rxb_skb--;\n"
- "-\tdev_kfree_skb_any(cmd.reply_skb);\n"
- "+\tpriv->alloc_rxb_page--;\n"
- "+\tfree_pages(cmd.reply_page, priv->hw_params.rx_page_order);\n"
- " \n"
- " \treturn rc;\n"
- " }\n"
- "@@ -2560,8 +2588,7 @@ int iwl3945_hw_set_hw_params(struct iwl_priv *priv)\n"
- " \tpriv->hw_params.max_txq_num = IWL39_NUM_QUEUES;\n"
- " \n"
- " \tpriv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);\n"
- "-\tpriv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_3K;\n"
- "-\tpriv->hw_params.max_pkt_size = 2342;\n"
- "+\tpriv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);\n"
- " \tpriv->hw_params.max_rxq_size = RX_QUEUE_SIZE;\n"
- " \tpriv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;\n"
- " \tpriv->hw_params.max_stations = IWL3945_STATION_COUNT;\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c\n"
- "index 6f703a0..e7c67d8 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-4965.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c\n"
- "@@ -2078,7 +2078,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,\n"
- " static void iwl4965_rx_reply_tx(struct iwl_priv *priv,\n"
- " \t\t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu16 sequence = le16_to_cpu(pkt->hdr.sequence);\n"
- " \tint txq_id = SEQ_TO_QUEUE(sequence);\n"
- " \tint index = SEQ_TO_INDEX(sequence);\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c\n"
- "index 6e6f516..29dfe27 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-5000.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c\n"
- "@@ -493,7 +493,7 @@ static int iwl5000_send_calib_cfg(struct iwl_priv *priv)\n"
- " static void iwl5000_rx_calib_result(struct iwl_priv *priv,\n"
- " \t\t\t     struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;\n"
- " \tint len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;\n"
- " \tint index;\n"
- "@@ -1218,7 +1218,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,\n"
- " static void iwl5000_rx_reply_tx(struct iwl_priv *priv,\n"
- " \t\t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu16 sequence = le16_to_cpu(pkt->hdr.sequence);\n"
- " \tint txq_id = SEQ_TO_QUEUE(sequence);\n"
- " \tint index = SEQ_TO_INDEX(sequence);\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c\n"
- "index eaafae0..c5ff7c0 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-agn.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c\n"
- "@@ -521,7 +521,7 @@ int iwl_hw_tx_queue_init(struct iwl_priv *priv,\n"
- " static void iwl_rx_reply_alive(struct iwl_priv *priv,\n"
- " \t\t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_alive_resp *palive;\n"
- " \tstruct delayed_work *pwork;\n"
- " \n"
- "@@ -607,7 +607,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,\n"
- " \t\t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl4965_beacon_notif *beacon =\n"
- " \t\t(struct iwl4965_beacon_notif *)pkt->u.raw;\n"
- " \tu8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);\n"
- "@@ -631,7 +631,7 @@ static void iwl_rx_beacon_notif(struct iwl_priv *priv,\n"
- " static void iwl_rx_card_state_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t    struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);\n"
- " \tunsigned long status = priv->status;\n"
- " \n"
- "@@ -783,10 +783,10 @@ void iwl_rx_handle(struct iwl_priv *priv)\n"
- " \n"
- " \t\trxq->queue[i] = NULL;\n"
- " \n"
- "-\t\tpci_unmap_single(priv->pci_dev, rxb->real_dma_addr,\n"
- "-\t\t\t\t priv->hw_params.rx_buf_size + 256,\n"
- "-\t\t\t\t PCI_DMA_FROMDEVICE);\n"
- "-\t\tpkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\t\tpci_unmap_page(priv->pci_dev, rxb->page_dma,\n"
- "+\t\t\t       PAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t       PCI_DMA_FROMDEVICE);\n"
- "+\t\tpkt = rxb_addr(rxb);\n"
- " \n"
- " \t\t/* Reclaim a command buffer only if this packet is a response\n"
- " \t\t *   to a (driver-originated) command.\n"
- "@@ -819,10 +819,10 @@ void iwl_rx_handle(struct iwl_priv *priv)\n"
- " \t\t}\n"
- " \n"
- " \t\tif (reclaim) {\n"
- "-\t\t\t/* Invoke any callbacks, transfer the skb to caller, and\n"
- "-\t\t\t * fire off the (possibly) blocking iwl_send_cmd()\n"
- "+\t\t\t/* Invoke any callbacks, transfer the buffer to caller,\n"
- "+\t\t\t * and fire off the (possibly) blocking iwl_send_cmd()\n"
- " \t\t\t * as we reclaim the driver command queue */\n"
- "-\t\t\tif (rxb && rxb->skb)\n"
- "+\t\t\tif (rxb && rxb->page)\n"
- " \t\t\t\tiwl_tx_cmd_complete(priv, rxb);\n"
- " \t\t\telse\n"
- " \t\t\t\tIWL_WARN(priv, \"Claim null rxb?\\n\");\n"
- "@@ -831,10 +831,10 @@ void iwl_rx_handle(struct iwl_priv *priv)\n"
- " \t\t/* For now we just don't re-use anything.  We can tweak this\n"
- " \t\t * later to try and re-use notification packets and SKBs that\n"
- " \t\t * fail to Rx correctly */\n"
- "-\t\tif (rxb->skb != NULL) {\n"
- "-\t\t\tpriv->alloc_rxb_skb--;\n"
- "-\t\t\tdev_kfree_skb_any(rxb->skb);\n"
- "-\t\t\trxb->skb = NULL;\n"
- "+\t\tif (rxb->page != NULL) {\n"
- "+\t\t\tpriv->alloc_rxb_page--;\n"
- "+\t\t\t__free_pages(rxb->page, priv->hw_params.rx_page_order);\n"
- "+\t\t\trxb->page = NULL;\n"
- " \t\t}\n"
- " \n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- "@@ -901,6 +901,8 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)\n"
- " \t}\n"
- " #endif\n"
- " \n"
- "+\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "+\n"
- " \t/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not\n"
- " \t * atomic, make sure that inta covers all the interrupts that\n"
- " \t * we've discovered, even if FH interrupt came in just after\n"
- "@@ -922,8 +924,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)\n"
- " \n"
- " \t\thandled |= CSR_INT_BIT_HW_ERR;\n"
- " \n"
- "-\t\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "-\n"
- " \t\treturn;\n"
- " \t}\n"
- " \n"
- "@@ -1050,7 +1050,6 @@ static void iwl_irq_tasklet_legacy(struct iwl_priv *priv)\n"
- " \t\t\t\"flags 0x%08lx\\n\", inta, inta_mask, inta_fh, flags);\n"
- " \t}\n"
- " #endif\n"
- "-\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- " }\n"
- " \n"
- " /* tasklet for iwlagn interrupt */\n"
- "@@ -1080,6 +1079,9 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)\n"
- " \t\t\t\tinta, inta_mask);\n"
- " \t}\n"
- " #endif\n"
- "+\n"
- "+\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "+\n"
- " \t/* saved interrupt in inta variable now we can reset priv->inta */\n"
- " \tpriv->inta = 0;\n"
- " \n"
- "@@ -1095,8 +1097,6 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)\n"
- " \n"
- " \t\thandled |= CSR_INT_BIT_HW_ERR;\n"
- " \n"
- "-\t\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "-\n"
- " \t\treturn;\n"
- " \t}\n"
- " \n"
- "@@ -1236,14 +1236,10 @@ static void iwl_irq_tasklet(struct iwl_priv *priv)\n"
- " \t\t\t inta & ~priv->inta_mask);\n"
- " \t}\n"
- " \n"
- "-\n"
- " \t/* Re-enable all interrupts */\n"
- " \t/* only Re-enable if diabled by irq */\n"
- " \tif (test_bit(STATUS_INT_ENABLED, &priv->status))\n"
- " \t\tiwl_enable_interrupts(priv);\n"
- "-\n"
- "-\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "-\n"
- " }\n"
- " \n"
- " \n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h\n"
- "index 4afaf77..dd54bf2 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-commands.h\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h\n"
- "@@ -3495,6 +3495,16 @@ struct iwl_wimax_coex_cmd {\n"
- "  *****************************************************************************/\n"
- " \n"
- " struct iwl_rx_packet {\n"
- "+\t/*\n"
- "+\t * The first 4 bytes of the RX frame header contain both the RX frame\n"
- "+\t * size and some flags.\n"
- "+\t * Bit fields:\n"
- "+\t * 31:    flag flush RB request\n"
- "+\t * 30:    flag ignore TC (terminal counter) request\n"
- "+\t * 29:    flag fast IRQ request\n"
- "+\t * 28-14: Reserved\n"
- "+\t * 13-00: RX frame size\n"
- "+\t */\n"
- " \t__le32 len_n_flags;\n"
- " \tstruct iwl_cmd_header hdr;\n"
- " \tunion {\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c\n"
- "index 2dc9287..bb9ff29 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-core.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-core.c\n"
- "@@ -1281,7 +1281,7 @@ static void iwl_set_rate(struct iwl_priv *priv)\n"
- " \n"
- " void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_rxon_cmd *rxon = (void *)&priv->active_rxon;\n"
- " \tstruct iwl_csa_notification *csa = &(pkt->u.csa_notif);\n"
- " \tIWL_DEBUG_11H(priv, \"CSA notif: channel %d, status %d\\n\",\n"
- "@@ -1456,10 +1456,9 @@ int iwl_set_hw_params(struct iwl_priv *priv)\n"
- " \tpriv->hw_params.max_rxq_size = RX_QUEUE_SIZE;\n"
- " \tpriv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;\n"
- " \tif (priv->cfg->mod_params->amsdu_size_8K)\n"
- "-\t\tpriv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_8K;\n"
- "+\t\tpriv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);\n"
- " \telse\n"
- "-\t\tpriv->hw_params.rx_buf_size = IWL_RX_BUF_SIZE_4K;\n"
- "-\tpriv->hw_params.max_pkt_size = priv->hw_params.rx_buf_size - 256;\n"
- "+\t\tpriv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);\n"
- " \n"
- " \tpriv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;\n"
- " \n"
- "@@ -2143,7 +2142,7 @@ void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,\n"
- " \t\t\t   struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_sleep_notification *sleep = &(pkt->u.sleep_notif);\n"
- " \tIWL_DEBUG_RX(priv, \"sleep mode: %d, src: %d\\n\",\n"
- " \t\t     sleep->pm_sleep_mode, sleep->pm_wakeup_src);\n"
- "@@ -2154,7 +2153,7 @@ EXPORT_SYMBOL(iwl_rx_pm_sleep_notif);\n"
- " void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t      struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;\n"
- " \tIWL_DEBUG_RADIO(priv, \"Dumping %d bytes of unhandled \"\n"
- " \t\t\t\"notification for %s:\\n\", len,\n"
- "@@ -2166,7 +2165,7 @@ EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);\n"
- " void iwl_rx_reply_error(struct iwl_priv *priv,\n"
- " \t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \n"
- " \tIWL_ERR(priv, \"Error Reply type 0x%08X cmd %s (0x%02X) \"\n"
- " \t\t\"seq 0x%04X ser 0x%08X\\n\",\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h\n"
- "index e50103a..d95674e 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-core.h\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-core.h\n"
- "@@ -509,7 +509,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,\n"
- " \t\t\t   const void *data,\n"
- " \t\t\t   void (*callback)(struct iwl_priv *priv,\n"
- " \t\t\t\t\t    struct iwl_device_cmd *cmd,\n"
- "-\t\t\t\t\t    struct sk_buff *skb));\n"
- "+\t\t\t\t\t    struct iwl_rx_packet *pkt));\n"
- " \n"
- " int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);\n"
- " \n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h\n"
- "index 028d505..7fb1688 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-dev.h\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h\n"
- "@@ -144,12 +144,13 @@ extern void iwl5000_temperature(struct iwl_priv *priv);\n"
- " #define\tDEFAULT_LONG_RETRY_LIMIT  4U\n"
- " \n"
- " struct iwl_rx_mem_buffer {\n"
- "-\tdma_addr_t real_dma_addr;\n"
- "-\tdma_addr_t aligned_dma_addr;\n"
- "-\tstruct sk_buff *skb;\n"
- "+\tdma_addr_t page_dma;\n"
- "+\tstruct page *page;\n"
- " \tstruct list_head list;\n"
- " };\n"
- " \n"
- "+#define rxb_addr(r) page_address(r->page)\n"
- "+\n"
- " /* defined below */\n"
- " struct iwl_device_cmd;\n"
- " \n"
- "@@ -165,7 +166,7 @@ struct iwl_cmd_meta {\n"
- " \t */\n"
- " \tvoid (*callback)(struct iwl_priv *priv,\n"
- " \t\t\t struct iwl_device_cmd *cmd,\n"
- "-\t\t\t struct sk_buff *skb);\n"
- "+\t\t\t struct iwl_rx_packet *pkt);\n"
- " \n"
- " \t/* The CMD_SIZE_HUGE flag bit indicates that the command\n"
- " \t * structure is stored at the end of the shared queue memory. */\n"
- "@@ -358,6 +359,13 @@ enum {\n"
- " \n"
- " #define IWL_CMD_MAX_PAYLOAD 320\n"
- " \n"
- "+/*\n"
- "+ * IWL_LINK_HDR_MAX should include ieee80211_hdr, radiotap header,\n"
- "+ * SNAP header and alignment. It should also be big enough for 802.11\n"
- "+ * control frames.\n"
- "+ */\n"
- "+#define IWL_LINK_HDR_MAX 64\n"
- "+\n"
- " /**\n"
- "  * struct iwl_device_cmd\n"
- "  *\n"
- "@@ -382,10 +390,10 @@ struct iwl_device_cmd {\n"
- " \n"
- " struct iwl_host_cmd {\n"
- " \tconst void *data;\n"
- "-\tstruct sk_buff *reply_skb;\n"
- "+\tunsigned long reply_page;\n"
- " \tvoid (*callback)(struct iwl_priv *priv,\n"
- " \t\t\t struct iwl_device_cmd *cmd,\n"
- "-\t\t\t struct sk_buff *skb);\n"
- "+\t\t\t struct iwl_rx_packet *pkt);\n"
- " \tu32 flags;\n"
- " \tu16 len;\n"
- " \tu8 id;\n"
- "@@ -639,7 +647,7 @@ struct iwl_sensitivity_ranges {\n"
- "  * @valid_tx/rx_ant: usable antennas\n"
- "  * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)\n"
- "  * @max_rxq_log: Log-base-2 of max_rxq_size\n"
- "- * @rx_buf_size: Rx buffer size\n"
- "+ * @rx_page_order: Rx buffer page order\n"
- "  * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR\n"
- "  * @max_stations:\n"
- "  * @bcast_sta_id:\n"
- "@@ -662,9 +670,8 @@ struct iwl_hw_params {\n"
- " \tu8  valid_rx_ant;\n"
- " \tu16 max_rxq_size;\n"
- " \tu16 max_rxq_log;\n"
- "-\tu32 rx_buf_size;\n"
- "+\tu32 rx_page_order;\n"
- " \tu32 rx_wrt_ptr_reg;\n"
- "-\tu32 max_pkt_size;\n"
- " \tu8  max_stations;\n"
- " \tu8  bcast_sta_id;\n"
- " \tu8  ht40_channel;\n"
- "@@ -976,7 +983,7 @@ struct iwl_priv {\n"
- " \tint frames_count;\n"
- " \n"
- " \tenum ieee80211_band band;\n"
- "-\tint alloc_rxb_skb;\n"
- "+\tint alloc_rxb_page;\n"
- " \n"
- " \tvoid (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,\n"
- " \t\t\t\t       struct iwl_rx_mem_buffer *rxb);\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-hcmd.c b/drivers/net/wireless/iwlwifi/iwl-hcmd.c\n"
- "index a6856da..1bf17d2 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-hcmd.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-hcmd.c\n"
- "@@ -104,17 +104,8 @@ EXPORT_SYMBOL(get_cmd_string);\n"
- " \n"
- " static void iwl_generic_cmd_callback(struct iwl_priv *priv,\n"
- " \t\t\t\t     struct iwl_device_cmd *cmd,\n"
- "-\t\t\t\t     struct sk_buff *skb)\n"
- "+\t\t\t\t     struct iwl_rx_packet *pkt)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = NULL;\n"
- "-\n"
- "-\tif (!skb) {\n"
- "-\t\tIWL_ERR(priv, \"Error: Response NULL in %s.\\n\",\n"
- "-\t\t\t\tget_cmd_string(cmd->hdr.cmd));\n"
- "-\t\treturn;\n"
- "-\t}\n"
- "-\n"
- "-\tpkt = (struct iwl_rx_packet *)skb->data;\n"
- " \tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from %s (0x%08X)\\n\",\n"
- " \t\t\tget_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);\n"
- "@@ -216,7 +207,7 @@ int iwl_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)\n"
- " \t\tret = -EIO;\n"
- " \t\tgoto fail;\n"
- " \t}\n"
- "-\tif ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_skb) {\n"
- "+\tif ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {\n"
- " \t\tIWL_ERR(priv, \"Error: Response NULL in '%s'\\n\",\n"
- " \t\t\t  get_cmd_string(cmd->id));\n"
- " \t\tret = -EIO;\n"
- "@@ -238,9 +229,9 @@ cancel:\n"
- " \t\t\t\t\t\t\t~CMD_WANT_SKB;\n"
- " \t}\n"
- " fail:\n"
- "-\tif (cmd->reply_skb) {\n"
- "-\t\tdev_kfree_skb_any(cmd->reply_skb);\n"
- "-\t\tcmd->reply_skb = NULL;\n"
- "+\tif (cmd->reply_page) {\n"
- "+\t\tfree_pages(cmd->reply_page, priv->hw_params.rx_page_order);\n"
- "+\t\tcmd->reply_page = 0;\n"
- " \t}\n"
- " out:\n"
- " \tclear_bit(STATUS_HCMD_SYNC_ACTIVE, &priv->status);\n"
- "@@ -273,7 +264,7 @@ int iwl_send_cmd_pdu_async(struct iwl_priv *priv,\n"
- " \t\t\t   u8 id, u16 len, const void *data,\n"
- " \t\t\t   void (*callback)(struct iwl_priv *priv,\n"
- " \t\t\t\t\t    struct iwl_device_cmd *cmd,\n"
- "-\t\t\t\t\t    struct sk_buff *skb))\n"
- "+\t\t\t\t\t    struct iwl_rx_packet *pkt))\n"
- " {\n"
- " \tstruct iwl_host_cmd cmd = {\n"
- " \t\t.id = id,\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c\n"
- "index 493626b..5e56857 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-rx.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c\n"
- "@@ -200,7 +200,7 @@ int iwl_rx_queue_restock(struct iwl_priv *priv)\n"
- " \t\tlist_del(element);\n"
- " \n"
- " \t\t/* Point to Rx buffer via next RBD in circular buffer */\n"
- "-\t\trxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->aligned_dma_addr);\n"
- "+\t\trxq->bd[rxq->write] = iwl_dma_addr2rbd_ptr(priv, rxb->page_dma);\n"
- " \t\trxq->queue[rxq->write] = rxb;\n"
- " \t\trxq->write = (rxq->write + 1) & RX_QUEUE_MASK;\n"
- " \t\trxq->free_count--;\n"
- "@@ -239,7 +239,7 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \tstruct iwl_rx_queue *rxq = &priv->rxq;\n"
- " \tstruct list_head *element;\n"
- " \tstruct iwl_rx_mem_buffer *rxb;\n"
- "-\tstruct sk_buff *skb;\n"
- "+\tstruct page *page;\n"
- " \tunsigned long flags;\n"
- " \n"
- " \twhile (1) {\n"
- "@@ -252,29 +252,34 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \n"
- " \t\tif (rxq->free_count > RX_LOW_WATERMARK)\n"
- " \t\t\tpriority |= __GFP_NOWARN;\n"
- "-\t\t/* Alloc a new receive buffer */\n"
- "-\t\tskb = alloc_skb(priv->hw_params.rx_buf_size + 256,\n"
- "-\t\t\t\t\t\tpriority);\n"
- " \n"
- "-\t\tif (!skb) {\n"
- "+\t\tif (priv->hw_params.rx_page_order > 0)\n"
- "+\t\t\tpriority |= __GFP_COMP;\n"
- "+\n"
- "+\t\t/* Alloc a new receive buffer */\n"
- "+\t\tpage = alloc_pages(priority, priv->hw_params.rx_page_order);\n"
- "+\t\tif (!page) {\n"
- " \t\t\tif (net_ratelimit())\n"
- "-\t\t\t\tIWL_DEBUG_INFO(priv, \"Failed to allocate SKB buffer.\\n\");\n"
- "+\t\t\t\tIWL_DEBUG_INFO(priv, \"alloc_pages failed, \"\n"
- "+\t\t\t\t\t       \"order: %d\\n\",\n"
- "+\t\t\t\t\t       priv->hw_params.rx_page_order);\n"
- "+\n"
- " \t\t\tif ((rxq->free_count <= RX_LOW_WATERMARK) &&\n"
- " \t\t\t    net_ratelimit())\n"
- "-\t\t\t\tIWL_CRIT(priv, \"Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\\n\",\n"
- "+\t\t\t\tIWL_CRIT(priv, \"Failed to alloc_pages with %s. Only %u free buffers remaining.\\n\",\n"
- " \t\t\t\t\t priority == GFP_ATOMIC ?  \"GFP_ATOMIC\" : \"GFP_KERNEL\",\n"
- " \t\t\t\t\t rxq->free_count);\n"
- " \t\t\t/* We don't reschedule replenish work here -- we will\n"
- " \t\t\t * call the restock method and if it still needs\n"
- " \t\t\t * more buffers it will schedule replenish */\n"
- "-\t\t\tbreak;\n"
- "+\t\t\treturn;\n"
- " \t\t}\n"
- " \n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- " \n"
- " \t\tif (list_empty(&rxq->rx_used)) {\n"
- " \t\t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- "-\t\t\tdev_kfree_skb_any(skb);\n"
- "+\t\t\t__free_pages(page, priv->hw_params.rx_page_order);\n"
- " \t\t\treturn;\n"
- " \t\t}\n"
- " \t\telement = rxq->rx_used.next;\n"
- "@@ -283,24 +288,21 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \n"
- " \t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " \n"
- "-\t\trxb->skb = skb;\n"
- "-\t\t/* Get physical address of RB/SKB */\n"
- "-\t\trxb->real_dma_addr = pci_map_single(\n"
- "-\t\t\t\t\tpriv->pci_dev,\n"
- "-\t\t\t\t\trxb->skb->data,\n"
- "-\t\t\t\t\tpriv->hw_params.rx_buf_size + 256,\n"
- "-\t\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "+\t\trxb->page = page;\n"
- "+\t\t/* Get physical address of the RB */\n"
- "+\t\trxb->page_dma = pci_map_page(priv->pci_dev, page, 0,\n"
- "+\t\t\t\tPAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- " \t\t/* dma address must be no more than 36 bits */\n"
- "-\t\tBUG_ON(rxb->real_dma_addr & ~DMA_BIT_MASK(36));\n"
- "+\t\tBUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));\n"
- " \t\t/* and also 256 byte aligned! */\n"
- "-\t\trxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256);\n"
- "-\t\tskb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr);\n"
- "+\t\tBUG_ON(rxb->page_dma & DMA_BIT_MASK(8));\n"
- " \n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- " \n"
- " \t\tlist_add_tail(&rxb->list, &rxq->rx_free);\n"
- " \t\trxq->free_count++;\n"
- "-\t\tpriv->alloc_rxb_skb++;\n"
- "+\t\tpriv->alloc_rxb_page++;\n"
- " \n"
- " \t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " \t}\n"
- "@@ -336,12 +338,14 @@ void iwl_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)\n"
- " {\n"
- " \tint i;\n"
- " \tfor (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {\n"
- "-\t\tif (rxq->pool[i].skb != NULL) {\n"
- "-\t\t\tpci_unmap_single(priv->pci_dev,\n"
- "-\t\t\t\t\t rxq->pool[i].real_dma_addr,\n"
- "-\t\t\t\t\t priv->hw_params.rx_buf_size + 256,\n"
- "-\t\t\t\t\t PCI_DMA_FROMDEVICE);\n"
- "-\t\t\tdev_kfree_skb(rxq->pool[i].skb);\n"
- "+\t\tif (rxq->pool[i].page != NULL) {\n"
- "+\t\t\tpci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,\n"
- "+\t\t\t\tPAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "+\t\t\t__free_pages(rxq->pool[i].page,\n"
- "+\t\t\t\t     priv->hw_params.rx_page_order);\n"
- "+\t\t\trxq->pool[i].page = NULL;\n"
- "+\t\t\tpriv->alloc_rxb_page--;\n"
- " \t\t}\n"
- " \t}\n"
- " \n"
- "@@ -405,14 +409,14 @@ void iwl_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)\n"
- " \tfor (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {\n"
- " \t\t/* In the reset function, these buffers may have been allocated\n"
- " \t\t * to an SKB, so we need to unmap and free potential storage */\n"
- "-\t\tif (rxq->pool[i].skb != NULL) {\n"
- "-\t\t\tpci_unmap_single(priv->pci_dev,\n"
- "-\t\t\t\t\t rxq->pool[i].real_dma_addr,\n"
- "-\t\t\t\t\t priv->hw_params.rx_buf_size + 256,\n"
- "-\t\t\t\t\t PCI_DMA_FROMDEVICE);\n"
- "-\t\t\tpriv->alloc_rxb_skb--;\n"
- "-\t\t\tdev_kfree_skb(rxq->pool[i].skb);\n"
- "-\t\t\trxq->pool[i].skb = NULL;\n"
- "+\t\tif (rxq->pool[i].page != NULL) {\n"
- "+\t\t\tpci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,\n"
- "+\t\t\t\tPAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "+\t\t\tpriv->alloc_rxb_page--;\n"
- "+\t\t\t__free_pages(rxq->pool[i].page,\n"
- "+\t\t\t\t     priv->hw_params.rx_page_order);\n"
- "+\t\t\trxq->pool[i].page = NULL;\n"
- " \t\t}\n"
- " \t\tlist_add_tail(&rxq->pool[i].list, &rxq->rx_used);\n"
- " \t}\n"
- "@@ -491,7 +495,7 @@ void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,\n"
- " \t\t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " \n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_missed_beacon_notif *missed_beacon;\n"
- " \n"
- " \tmissed_beacon = &pkt->u.missed_beacon;\n"
- "@@ -554,7 +558,7 @@ void iwl_rx_statistics(struct iwl_priv *priv,\n"
- " \t\t\t      struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " \tint change;\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \n"
- " \tIWL_DEBUG_RX(priv, \"Statistics notification received (%d vs %d).\\n\",\n"
- " \t\t     (int)sizeof(priv->statistics),\n"
- "@@ -878,6 +882,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t\t\t\t\tstruct iwl_rx_mem_buffer *rxb,\n"
- " \t\t\t\t\tstruct ieee80211_rx_status *stats)\n"
- " {\n"
- "+\tstruct sk_buff *skb;\n"
- "+\tint ret = 0;\n"
- "+\n"
- " \t/* We only process data packets if the interface is open */\n"
- " \tif (unlikely(!priv->is_open)) {\n"
- " \t\tIWL_DEBUG_DROP_LIMIT(priv,\n"
- "@@ -890,15 +897,38 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))\n"
- " \t\treturn;\n"
- " \n"
- "-\t/* Resize SKB from mac header to end of packet */\n"
- "-\tskb_reserve(rxb->skb, (void *)hdr - (void *)rxb->skb->data);\n"
- "-\tskb_put(rxb->skb, len);\n"
- "+\tskb = alloc_skb(IWL_LINK_HDR_MAX, GFP_ATOMIC);\n"
- "+\tif (!skb) {\n"
- "+\t\tIWL_ERR(priv, \"alloc_skb failed\\n\");\n"
- "+\t\treturn;\n"
- "+\t}\n"
- "+\n"
- "+\tskb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);\n"
- "+\n"
- "+\t/* mac80211 currently doesn't support paged SKB. Convert it to\n"
- "+\t * linear SKB for management frame and data frame requires\n"
- "+\t * software decryption or software defragementation. */\n"
- "+\tif (ieee80211_is_mgmt(hdr->frame_control) ||\n"
- "+\t    ieee80211_has_protected(hdr->frame_control) ||\n"
- "+\t    ieee80211_has_morefrags(hdr->frame_control) ||\n"
- "+\t    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)\n"
- "+\t\tret = skb_linearize(skb);\n"
- "+\telse\n"
- "+\t\tret = __pskb_pull_tail(skb, min_t(u16, IWL_LINK_HDR_MAX, len)) ?\n"
- "+\t\t\t 0 : -ENOMEM;\n"
- "+\n"
- "+\tif (ret) {\n"
- "+\t\tkfree_skb(skb);\n"
- "+\t\tgoto out;\n"
- "+\t}\n"
- " \n"
- " \tiwl_update_stats(priv, false, hdr->frame_control, len);\n"
- "-\tmemcpy(IEEE80211_SKB_RXCB(rxb->skb), stats, sizeof(*stats));\n"
- "-\tieee80211_rx_irqsafe(priv->hw, rxb->skb);\n"
- "-\tpriv->alloc_rxb_skb--;\n"
- "-\trxb->skb = NULL;\n"
- "+\tmemcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));\n"
- "+\n"
- "+\tieee80211_rx(priv->hw, skb);\n"
- "+ out:\n"
- "+\tpriv->alloc_rxb_page--;\n"
- "+\trxb->page = NULL;\n"
- " }\n"
- " \n"
- " /* This is necessary only for a number of statistics, see the caller. */\n"
- "@@ -926,7 +956,7 @@ void iwl_rx_reply_rx(struct iwl_priv *priv,\n"
- " {\n"
- " \tstruct ieee80211_hdr *header;\n"
- " \tstruct ieee80211_rx_status rx_status;\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_rx_phy_res *phy_res;\n"
- " \t__le32 rx_pkt_status;\n"
- " \tstruct iwl4965_rx_mpdu_res_start *amsdu;\n"
- "@@ -1087,7 +1117,7 @@ EXPORT_SYMBOL(iwl_rx_reply_rx);\n"
- " void iwl_rx_reply_rx_phy(struct iwl_priv *priv,\n"
- " \t\t\t\t    struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tpriv->last_phy_res[0] = 1;\n"
- " \tmemcpy(&priv->last_phy_res[1], &(pkt->u.raw[0]),\n"
- " \t       sizeof(struct iwl_rx_phy_res));\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c\n"
- "index 4f3a108..bcccc6f 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-scan.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c\n"
- "@@ -112,7 +112,7 @@ EXPORT_SYMBOL(iwl_scan_cancel_timeout);\n"
- " static int iwl_send_scan_abort(struct iwl_priv *priv)\n"
- " {\n"
- " \tint ret = 0;\n"
- "-\tstruct iwl_rx_packet *res;\n"
- "+\tstruct iwl_rx_packet *pkt;\n"
- " \tstruct iwl_host_cmd cmd = {\n"
- " \t\t.id = REPLY_SCAN_ABORT_CMD,\n"
- " \t\t.flags = CMD_WANT_SKB,\n"
- "@@ -132,21 +132,21 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)\n"
- " \t\treturn ret;\n"
- " \t}\n"
- " \n"
- "-\tres = (struct iwl_rx_packet *)cmd.reply_skb->data;\n"
- "-\tif (res->u.status != CAN_ABORT_STATUS) {\n"
- "+\tpkt = (struct iwl_rx_packet *)cmd.reply_page;\n"
- "+\tif (pkt->u.status != CAN_ABORT_STATUS) {\n"
- " \t\t/* The scan abort will return 1 for success or\n"
- " \t\t * 2 for \"failure\".  A failure condition can be\n"
- " \t\t * due to simply not being in an active scan which\n"
- " \t\t * can occur if we send the scan abort before we\n"
- " \t\t * the microcode has notified us that a scan is\n"
- " \t\t * completed. */\n"
- "-\t\tIWL_DEBUG_INFO(priv, \"SCAN_ABORT returned %d.\\n\", res->u.status);\n"
- "+\t\tIWL_DEBUG_INFO(priv, \"SCAN_ABORT returned %d.\\n\", pkt->u.status);\n"
- " \t\tclear_bit(STATUS_SCAN_ABORTING, &priv->status);\n"
- " \t\tclear_bit(STATUS_SCAN_HW, &priv->status);\n"
- " \t}\n"
- " \n"
- "-\tpriv->alloc_rxb_skb--;\n"
- "-\tdev_kfree_skb_any(cmd.reply_skb);\n"
- "+\tpriv->alloc_rxb_page--;\n"
- "+\tfree_pages(cmd.reply_page, priv->hw_params.rx_page_order);\n"
- " \n"
- " \treturn ret;\n"
- " }\n"
- "@@ -156,7 +156,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,\n"
- " \t\t\t      struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_scanreq_notification *notif =\n"
- " \t    (struct iwl_scanreq_notification *)pkt->u.raw;\n"
- " \n"
- "@@ -168,7 +168,7 @@ static void iwl_rx_reply_scan(struct iwl_priv *priv,\n"
- " static void iwl_rx_scan_start_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t    struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_scanstart_notification *notif =\n"
- " \t    (struct iwl_scanstart_notification *)pkt->u.raw;\n"
- " \tpriv->scan_start_tsf = le32_to_cpu(notif->tsf_low);\n"
- "@@ -187,7 +187,7 @@ static void iwl_rx_scan_results_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t      struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_scanresults_notification *notif =\n"
- " \t    (struct iwl_scanresults_notification *)pkt->u.raw;\n"
- " \n"
- "@@ -214,7 +214,7 @@ static void iwl_rx_scan_complete_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t       struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;\n"
- " \n"
- " \tIWL_DEBUG_SCAN(priv, \"Scan complete: %d channels (TSF 0x%08X:%08X) - %d\\n\",\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-spectrum.c b/drivers/net/wireless/iwlwifi/iwl-spectrum.c\n"
- "index 022bcf1..1ea5cd3 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-spectrum.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-spectrum.c\n"
- "@@ -177,7 +177,7 @@ static int iwl_get_measurement(struct iwl_priv *priv,\n"
- " static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t\t  struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);\n"
- " \n"
- " \tif (!report->state) {\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-sta.c b/drivers/net/wireless/iwlwifi/iwl-sta.c\n"
- "index c6633fe..dc74c16 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-sta.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-sta.c\n"
- "@@ -99,32 +99,25 @@ static void iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)\n"
- " \n"
- " static void iwl_add_sta_callback(struct iwl_priv *priv,\n"
- " \t\t\t\t struct iwl_device_cmd *cmd,\n"
- "-\t\t\t\t struct sk_buff *skb)\n"
- "+\t\t\t\t struct iwl_rx_packet *pkt)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *res = NULL;\n"
- " \tstruct iwl_addsta_cmd *addsta =\n"
- " \t\t(struct iwl_addsta_cmd *)cmd->cmd.payload;\n"
- " \tu8 sta_id = addsta->sta.sta_id;\n"
- " \n"
- "-\tif (!skb) {\n"
- "-\t\tIWL_ERR(priv, \"Error: Response NULL in REPLY_ADD_STA.\\n\");\n"
- "-\t\treturn;\n"
- "-\t}\n"
- "-\n"
- "-\tres = (struct iwl_rx_packet *)skb->data;\n"
- "-\tif (res->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- "+\tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from REPLY_ADD_STA (0x%08X)\\n\",\n"
- "-\t\t\t  res->hdr.flags);\n"
- "+\t\t\t  pkt->hdr.flags);\n"
- " \t\treturn;\n"
- " \t}\n"
- " \n"
- "-\tswitch (res->u.add_sta.status) {\n"
- "+\tswitch (pkt->u.add_sta.status) {\n"
- " \tcase ADD_STA_SUCCESS_MSK:\n"
- " \t\tiwl_sta_ucode_activate(priv, sta_id);\n"
- " \t\t /* fall through */\n"
- " \tdefault:\n"
- " \t\tIWL_DEBUG_HC(priv, \"Received REPLY_ADD_STA:(0x%08X)\\n\",\n"
- "-\t\t\t     res->u.add_sta.status);\n"
- "+\t\t\t     pkt->u.add_sta.status);\n"
- " \t\tbreak;\n"
- " \t}\n"
- " }\n"
- "@@ -132,7 +125,7 @@ static void iwl_add_sta_callback(struct iwl_priv *priv,\n"
- " int iwl_send_add_sta(struct iwl_priv *priv,\n"
- " \t\t     struct iwl_addsta_cmd *sta, u8 flags)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *res = NULL;\n"
- "+\tstruct iwl_rx_packet *pkt = NULL;\n"
- " \tint ret = 0;\n"
- " \tu8 data[sizeof(*sta)];\n"
- " \tstruct iwl_host_cmd cmd = {\n"
- "@@ -152,15 +145,15 @@ int iwl_send_add_sta(struct iwl_priv *priv,\n"
- " \tif (ret || (flags & CMD_ASYNC))\n"
- " \t\treturn ret;\n"
- " \n"
- "-\tres = (struct iwl_rx_packet *)cmd.reply_skb->data;\n"
- "-\tif (res->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- "+\tpkt = (struct iwl_rx_packet *)cmd.reply_page;\n"
- "+\tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from REPLY_ADD_STA (0x%08X)\\n\",\n"
- "-\t\t\t  res->hdr.flags);\n"
- "+\t\t\t  pkt->hdr.flags);\n"
- " \t\tret = -EIO;\n"
- " \t}\n"
- " \n"
- " \tif (ret == 0) {\n"
- "-\t\tswitch (res->u.add_sta.status) {\n"
- "+\t\tswitch (pkt->u.add_sta.status) {\n"
- " \t\tcase ADD_STA_SUCCESS_MSK:\n"
- " \t\t\tiwl_sta_ucode_activate(priv, sta->sta.sta_id);\n"
- " \t\t\tIWL_DEBUG_INFO(priv, \"REPLY_ADD_STA PASSED\\n\");\n"
- "@@ -172,8 +165,8 @@ int iwl_send_add_sta(struct iwl_priv *priv,\n"
- " \t\t}\n"
- " \t}\n"
- " \n"
- "-\tpriv->alloc_rxb_skb--;\n"
- "-\tdev_kfree_skb_any(cmd.reply_skb);\n"
- "+\tpriv->alloc_rxb_page--;\n"
- "+\tfree_pages(cmd.reply_page, priv->hw_params.rx_page_order);\n"
- " \n"
- " \treturn ret;\n"
- " }\n"
- "@@ -324,26 +317,19 @@ static void iwl_sta_ucode_deactivate(struct iwl_priv *priv, const char *addr)\n"
- " \n"
- " static void iwl_remove_sta_callback(struct iwl_priv *priv,\n"
- " \t\t\t\t    struct iwl_device_cmd *cmd,\n"
- "-\t\t\t\t    struct sk_buff *skb)\n"
- "+\t\t\t\t    struct iwl_rx_packet *pkt)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *res = NULL;\n"
- " \tstruct iwl_rem_sta_cmd *rm_sta =\n"
- "-\t\t (struct iwl_rem_sta_cmd *)cmd->cmd.payload;\n"
- "+\t\t\t(struct iwl_rem_sta_cmd *)cmd->cmd.payload;\n"
- " \tconst char *addr = rm_sta->addr;\n"
- " \n"
- "-\tif (!skb) {\n"
- "-\t\tIWL_ERR(priv, \"Error: Response NULL in REPLY_REMOVE_STA.\\n\");\n"
- "-\t\treturn;\n"
- "-\t}\n"
- "-\n"
- "-\tres = (struct iwl_rx_packet *)skb->data;\n"
- "-\tif (res->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- "+\tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from REPLY_REMOVE_STA (0x%08X)\\n\",\n"
- "-\t\tres->hdr.flags);\n"
- "+\t\tpkt->hdr.flags);\n"
- " \t\treturn;\n"
- " \t}\n"
- " \n"
- "-\tswitch (res->u.rem_sta.status) {\n"
- "+\tswitch (pkt->u.rem_sta.status) {\n"
- " \tcase REM_STA_SUCCESS_MSK:\n"
- " \t\tiwl_sta_ucode_deactivate(priv, addr);\n"
- " \t\tbreak;\n"
- "@@ -356,7 +342,7 @@ static void iwl_remove_sta_callback(struct iwl_priv *priv,\n"
- " static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,\n"
- " \t\t\t\t   u8 flags)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *res = NULL;\n"
- "+\tstruct iwl_rx_packet *pkt;\n"
- " \tint ret;\n"
- " \n"
- " \tstruct iwl_rem_sta_cmd rm_sta_cmd;\n"
- "@@ -381,15 +367,15 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,\n"
- " \tif (ret || (flags & CMD_ASYNC))\n"
- " \t\treturn ret;\n"
- " \n"
- "-\tres = (struct iwl_rx_packet *)cmd.reply_skb->data;\n"
- "-\tif (res->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- "+\tpkt = (struct iwl_rx_packet *)cmd.reply_page;\n"
- "+\tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from REPLY_REMOVE_STA (0x%08X)\\n\",\n"
- "-\t\t\t  res->hdr.flags);\n"
- "+\t\t\t  pkt->hdr.flags);\n"
- " \t\tret = -EIO;\n"
- " \t}\n"
- " \n"
- " \tif (!ret) {\n"
- "-\t\tswitch (res->u.rem_sta.status) {\n"
- "+\t\tswitch (pkt->u.rem_sta.status) {\n"
- " \t\tcase REM_STA_SUCCESS_MSK:\n"
- " \t\t\tiwl_sta_ucode_deactivate(priv, addr);\n"
- " \t\t\tIWL_DEBUG_ASSOC(priv, \"REPLY_REMOVE_STA PASSED\\n\");\n"
- "@@ -401,8 +387,8 @@ static int iwl_send_remove_station(struct iwl_priv *priv, const u8 *addr,\n"
- " \t\t}\n"
- " \t}\n"
- " \n"
- "-\tpriv->alloc_rxb_skb--;\n"
- "-\tdev_kfree_skb_any(cmd.reply_skb);\n"
- "+\tpriv->alloc_rxb_page--;\n"
- "+\tfree_pages(cmd.reply_page, priv->hw_params.rx_page_order);\n"
- " \n"
- " \treturn ret;\n"
- " }\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c\n"
- "index fb9bcfa..a98d60d 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-tx.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c\n"
- "@@ -1132,7 +1132,7 @@ static void iwl_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,\n"
- "  */\n"
- " void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu16 sequence = le16_to_cpu(pkt->hdr.sequence);\n"
- " \tint txq_id = SEQ_TO_QUEUE(sequence);\n"
- " \tint index = SEQ_TO_INDEX(sequence);\n"
- "@@ -1159,10 +1159,10 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)\n"
- " \n"
- " \t/* Input error checking is done when commands are added to queue. */\n"
- " \tif (meta->flags & CMD_WANT_SKB) {\n"
- "-\t\tmeta->source->reply_skb = rxb->skb;\n"
- "-\t\trxb->skb = NULL;\n"
- "+\t\tmeta->source->reply_page = (unsigned long)rxb_addr(rxb);\n"
- "+\t\trxb->page = NULL;\n"
- " \t} else if (meta->callback)\n"
- "-\t\tmeta->callback(priv, cmd, rxb->skb);\n"
- "+\t\tmeta->callback(priv, cmd, pkt);\n"
- " \n"
- " \tiwl_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);\n"
- " \n"
- "@@ -1421,7 +1421,7 @@ static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,\n"
- " void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,\n"
- " \t\t\t\t\t   struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;\n"
- " \tstruct iwl_tx_queue *txq = NULL;\n"
- " \tstruct iwl_ht_agg *agg;\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c\n"
- "index d00a803..e20690d 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c\n"
- "@@ -758,7 +758,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,\n"
- " \t\t\t       u8 type)\n"
- " {\n"
- " \tstruct iwl_spectrum_cmd spectrum;\n"
- "-\tstruct iwl_rx_packet *res;\n"
- "+\tstruct iwl_rx_packet *pkt;\n"
- " \tstruct iwl_host_cmd cmd = {\n"
- " \t\t.id = REPLY_SPECTRUM_MEASUREMENT_CMD,\n"
- " \t\t.data = (void *)&spectrum,\n"
- "@@ -803,18 +803,18 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,\n"
- " \tif (rc)\n"
- " \t\treturn rc;\n"
- " \n"
- "-\tres = (struct iwl_rx_packet *)cmd.reply_skb->data;\n"
- "-\tif (res->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- "+\tpkt = (struct iwl_rx_packet *)cmd.reply_page;\n"
- "+\tif (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {\n"
- " \t\tIWL_ERR(priv, \"Bad return from REPLY_RX_ON_ASSOC command\\n\");\n"
- " \t\trc = -EIO;\n"
- " \t}\n"
- " \n"
- "-\tspectrum_resp_status = le16_to_cpu(res->u.spectrum.status);\n"
- "+\tspectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);\n"
- " \tswitch (spectrum_resp_status) {\n"
- " \tcase 0:\t\t/* Command will be handled */\n"
- "-\t\tif (res->u.spectrum.id != 0xff) {\n"
- "+\t\tif (pkt->u.spectrum.id != 0xff) {\n"
- " \t\t\tIWL_DEBUG_INFO(priv, \"Replaced existing measurement: %d\\n\",\n"
- "-\t\t\t\t\t\tres->u.spectrum.id);\n"
- "+\t\t\t\t\t\tpkt->u.spectrum.id);\n"
- " \t\t\tpriv->measurement_status &= ~MEASUREMENT_READY;\n"
- " \t\t}\n"
- " \t\tpriv->measurement_status |= MEASUREMENT_ACTIVE;\n"
- "@@ -826,7 +826,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,\n"
- " \t\tbreak;\n"
- " \t}\n"
- " \n"
- "-\tdev_kfree_skb_any(cmd.reply_skb);\n"
- "+\tfree_pages(cmd.reply_page, priv->hw_params.rx_page_order);\n"
- " \n"
- " \treturn rc;\n"
- " }\n"
- "@@ -835,7 +835,7 @@ static int iwl3945_get_measurement(struct iwl_priv *priv,\n"
- " static void iwl3945_rx_reply_alive(struct iwl_priv *priv,\n"
- " \t\t\t       struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl_alive_resp *palive;\n"
- " \tstruct delayed_work *pwork;\n"
- " \n"
- "@@ -872,7 +872,7 @@ static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,\n"
- " \t\t\t\t struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " #endif\n"
- " \n"
- " \tIWL_DEBUG_RX(priv, \"Received REPLY_ADD_STA: 0x%02X\\n\", pkt->u.status);\n"
- "@@ -908,7 +908,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,\n"
- " \t\t\t\tstruct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- " #ifdef CONFIG_IWLWIFI_DEBUG\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tstruct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);\n"
- " \tu8 rate = beacon->beacon_notify_hdr.rate;\n"
- " \n"
- "@@ -931,7 +931,7 @@ static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,\n"
- " static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,\n"
- " \t\t\t\t    struct iwl_rx_mem_buffer *rxb)\n"
- " {\n"
- "-\tstruct iwl_rx_packet *pkt = (void *)rxb->skb->data;\n"
- "+\tstruct iwl_rx_packet *pkt = rxb_addr(rxb);\n"
- " \tu32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);\n"
- " \tunsigned long status = priv->status;\n"
- " \n"
- "@@ -1095,7 +1095,7 @@ static int iwl3945_rx_queue_restock(struct iwl_priv *priv)\n"
- " \t\tlist_del(element);\n"
- " \n"
- " \t\t/* Point to Rx buffer via next RBD in circular buffer */\n"
- "-\t\trxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->real_dma_addr);\n"
- "+\t\trxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);\n"
- " \t\trxq->queue[rxq->write] = rxb;\n"
- " \t\trxq->write = (rxq->write + 1) & RX_QUEUE_MASK;\n"
- " \t\trxq->free_count--;\n"
- "@@ -1135,7 +1135,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \tstruct iwl_rx_queue *rxq = &priv->rxq;\n"
- " \tstruct list_head *element;\n"
- " \tstruct iwl_rx_mem_buffer *rxb;\n"
- "-\tstruct sk_buff *skb;\n"
- "+\tstruct page *page;\n"
- " \tunsigned long flags;\n"
- " \n"
- " \twhile (1) {\n"
- "@@ -1149,9 +1149,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \n"
- " \t\tif (rxq->free_count > RX_LOW_WATERMARK)\n"
- " \t\t\tpriority |= __GFP_NOWARN;\n"
- "+\n"
- "+\t\tif (priv->hw_params.rx_page_order > 0)\n"
- "+\t\t\tpriority |= __GFP_COMP;\n"
- "+\n"
- " \t\t/* Alloc a new receive buffer */\n"
- "-\t\tskb = alloc_skb(priv->hw_params.rx_buf_size, priority);\n"
- "-\t\tif (!skb) {\n"
- "+\t\tpage = alloc_pages(priority, priv->hw_params.rx_page_order);\n"
- "+\t\tif (!page) {\n"
- " \t\t\tif (net_ratelimit())\n"
- " \t\t\t\tIWL_DEBUG_INFO(priv, \"Failed to allocate SKB buffer.\\n\");\n"
- " \t\t\tif ((rxq->free_count <= RX_LOW_WATERMARK) &&\n"
- "@@ -1168,7 +1172,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- " \t\tif (list_empty(&rxq->rx_used)) {\n"
- " \t\t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- "-\t\t\tdev_kfree_skb_any(skb);\n"
- "+\t\t\t__free_pages(page, priv->hw_params.rx_page_order);\n"
- " \t\t\treturn;\n"
- " \t\t}\n"
- " \t\telement = rxq->rx_used.next;\n"
- "@@ -1176,26 +1180,18 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \t\tlist_del(element);\n"
- " \t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " \n"
- "-\t\trxb->skb = skb;\n"
- "-\n"
- "-\t\t/* If radiotap head is required, reserve some headroom here.\n"
- "-\t\t * The physical head count is a variable rx_stats->phy_count.\n"
- "-\t\t * We reserve 4 bytes here. Plus these extra bytes, the\n"
- "-\t\t * headroom of the physical head should be enough for the\n"
- "-\t\t * radiotap head that iwl3945 supported. See iwl3945_rt.\n"
- "-\t\t */\n"
- "-\t\tskb_reserve(rxb->skb, 4);\n"
- "-\n"
- "+\t\trxb->page = page;\n"
- " \t\t/* Get physical address of RB/SKB */\n"
- "-\t\trxb->real_dma_addr = pci_map_single(priv->pci_dev,\n"
- "-\t\t\t\t\t\trxb->skb->data,\n"
- "-\t\t\t\t\t\tpriv->hw_params.rx_buf_size,\n"
- "-\t\t\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "+\t\trxb->page_dma = pci_map_page(priv->pci_dev, page, 0,\n"
- "+\t\t\t\tPAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- " \n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- "+\n"
- " \t\tlist_add_tail(&rxb->list, &rxq->rx_free);\n"
- "-\t\tpriv->alloc_rxb_skb++;\n"
- " \t\trxq->free_count++;\n"
- "+\t\tpriv->alloc_rxb_page++;\n"
- "+\n"
- " \t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " \t}\n"
- " }\n"
- "@@ -1211,14 +1207,14 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)\n"
- " \tfor (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {\n"
- " \t\t/* In the reset function, these buffers may have been allocated\n"
- " \t\t * to an SKB, so we need to unmap and free potential storage */\n"
- "-\t\tif (rxq->pool[i].skb != NULL) {\n"
- "-\t\t\tpci_unmap_single(priv->pci_dev,\n"
- "-\t\t\t\t\t rxq->pool[i].real_dma_addr,\n"
- "-\t\t\t\t\t priv->hw_params.rx_buf_size,\n"
- "-\t\t\t\t\t PCI_DMA_FROMDEVICE);\n"
- "-\t\t\tpriv->alloc_rxb_skb--;\n"
- "-\t\t\tdev_kfree_skb(rxq->pool[i].skb);\n"
- "-\t\t\trxq->pool[i].skb = NULL;\n"
- "+\t\tif (rxq->pool[i].page != NULL) {\n"
- "+\t\t\tpci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,\n"
- "+\t\t\t\tPAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "+\t\t\tpriv->alloc_rxb_page--;\n"
- "+\t\t\t__free_pages(rxq->pool[i].page,\n"
- "+\t\t\t\t     priv->hw_params.rx_page_order);\n"
- "+\t\t\trxq->pool[i].page = NULL;\n"
- " \t\t}\n"
- " \t\tlist_add_tail(&rxq->pool[i].list, &rxq->rx_used);\n"
- " \t}\n"
- "@@ -1226,8 +1222,8 @@ void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)\n"
- " \t/* Set us so that we have processed and used all buffers, but have\n"
- " \t * not restocked the Rx queue with fresh buffers */\n"
- " \trxq->read = rxq->write = 0;\n"
- "-\trxq->free_count = 0;\n"
- " \trxq->write_actual = 0;\n"
- "+\trxq->free_count = 0;\n"
- " \tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " }\n"
- " \n"
- "@@ -1260,12 +1256,14 @@ static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rx\n"
- " {\n"
- " \tint i;\n"
- " \tfor (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {\n"
- "-\t\tif (rxq->pool[i].skb != NULL) {\n"
- "-\t\t\tpci_unmap_single(priv->pci_dev,\n"
- "-\t\t\t\t\t rxq->pool[i].real_dma_addr,\n"
- "-\t\t\t\t\t priv->hw_params.rx_buf_size,\n"
- "-\t\t\t\t\t PCI_DMA_FROMDEVICE);\n"
- "-\t\t\tdev_kfree_skb(rxq->pool[i].skb);\n"
- "+\t\tif (rxq->pool[i].page != NULL) {\n"
- "+\t\t\tpci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,\n"
- "+\t\t\t\tPAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "+\t\t\t__free_pages(rxq->pool[i].page,\n"
- "+\t\t\t\t     priv->hw_params.rx_page_order);\n"
- "+\t\t\trxq->pool[i].page = NULL;\n"
- "+\t\t\tpriv->alloc_rxb_page--;\n"
- " \t\t}\n"
- " \t}\n"
- " \n"
- "@@ -1401,10 +1399,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)\n"
- " \n"
- " \t\trxq->queue[i] = NULL;\n"
- " \n"
- "-\t\tpci_unmap_single(priv->pci_dev, rxb->real_dma_addr,\n"
- "-\t\t\t\tpriv->hw_params.rx_buf_size,\n"
- "-\t\t\t\tPCI_DMA_FROMDEVICE);\n"
- "-\t\tpkt = (struct iwl_rx_packet *)rxb->skb->data;\n"
- "+\t\tpci_unmap_page(priv->pci_dev, rxb->page_dma,\n"
- "+\t\t\t       PAGE_SIZE << priv->hw_params.rx_page_order,\n"
- "+\t\t\t       PCI_DMA_FROMDEVICE);\n"
- "+\t\tpkt = rxb_addr(rxb);\n"
- " \n"
- " \t\t/* Reclaim a command buffer only if this packet is a response\n"
- " \t\t *   to a (driver-originated) command.\n"
- "@@ -1426,16 +1424,17 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)\n"
- " \t\t\tpriv->isr_stats.rx_handlers[pkt->hdr.cmd]++;\n"
- " \t\t} else {\n"
- " \t\t\t/* No handling needed */\n"
- "-\t\t\tIWL_DEBUG_RX(priv, \"r %d i %d No handler needed for %s, 0x%02x\\n\",\n"
- "+\t\t\tIWL_DEBUG_RX(priv,\n"
- "+\t\t\t\t\"r %d i %d No handler needed for %s, 0x%02x\\n\",\n"
- " \t\t\t\tr, i, get_cmd_string(pkt->hdr.cmd),\n"
- " \t\t\t\tpkt->hdr.cmd);\n"
- " \t\t}\n"
- " \n"
- " \t\tif (reclaim) {\n"
- "-\t\t\t/* Invoke any callbacks, transfer the skb to caller, and\n"
- "-\t\t\t * fire off the (possibly) blocking iwl_send_cmd()\n"
- "+\t\t\t/* Invoke any callbacks, transfer the buffer to caller,\n"
- "+\t\t\t * and fire off the (possibly) blocking iwl_send_cmd()\n"
- " \t\t\t * as we reclaim the driver command queue */\n"
- "-\t\t\tif (rxb && rxb->skb)\n"
- "+\t\t\tif (rxb && rxb->page)\n"
- " \t\t\t\tiwl_tx_cmd_complete(priv, rxb);\n"
- " \t\t\telse\n"
- " \t\t\t\tIWL_WARN(priv, \"Claim null rxb?\\n\");\n"
- "@@ -1444,10 +1443,10 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)\n"
- " \t\t/* For now we just don't re-use anything.  We can tweak this\n"
- " \t\t * later to try and re-use notification packets and SKBs that\n"
- " \t\t * fail to Rx correctly */\n"
- "-\t\tif (rxb->skb != NULL) {\n"
- "-\t\t\tpriv->alloc_rxb_skb--;\n"
- "-\t\t\tdev_kfree_skb_any(rxb->skb);\n"
- "-\t\t\trxb->skb = NULL;\n"
- "+\t\tif (rxb->page != NULL) {\n"
- "+\t\t\tpriv->alloc_rxb_page--;\n"
- "+\t\t\t__free_pages(rxb->page, priv->hw_params.rx_page_order);\n"
- "+\t\t\trxb->page = NULL;\n"
- " \t\t}\n"
- " \n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- "@@ -1685,6 +1684,8 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)\n"
- " \t}\n"
- " #endif\n"
- " \n"
- "+\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "+\n"
- " \t/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not\n"
- " \t * atomic, make sure that inta covers all the interrupts that\n"
- " \t * we've discovered, even if FH interrupt came in just after\n"
- "@@ -1706,8 +1707,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)\n"
- " \n"
- " \t\thandled |= CSR_INT_BIT_HW_ERR;\n"
- " \n"
- "-\t\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- "-\n"
- " \t\treturn;\n"
- " \t}\n"
- " \n"
- "@@ -1799,7 +1798,6 @@ static void iwl3945_irq_tasklet(struct iwl_priv *priv)\n"
- " \t\t\t\"flags 0x%08lx\\n\", inta, inta_mask, inta_fh, flags);\n"
- " \t}\n"
- " #endif\n"
- "-\tspin_unlock_irqrestore(&priv->lock, flags);\n"
- " }\n"
- " \n"
- " static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,\n"
- "-- \n"
- 1.5.6.3
- "\01:3\0"
- "fn\00002-iwlwifi-fix-use-after-free-bug-for-paged-rx.patch\0"
- "b\0"
- "From 000c60eef9bf7a579c02ccb7deee447a2231d2b0 Mon Sep 17 00:00:00 2001\n"
- "From: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "Date: Thu, 15 Oct 2009 20:00:57 -0700\n"
- "Subject: [PATCH 2/2] iwlwifi: fix use after free bug for paged rx\n"
- "\n"
- "In the paged rx patch (4854fde2), I introduced a bug that could possibly\n"
- "touch an already freed page. It is fixed by avoiding the access in this\n"
- "patch. I've also added some comments so that other people touching the\n"
- "code won't make the same mistake. In the future, if we cannot avoid\n"
- "access the page after being handled to the upper layer, we can use\n"
- "get_page/put_page to handle it. For now, it's just not necessary.\n"
- "\n"
- "It also fixed a debug message print bug reported by Stanislaw Gruszka\n"
- "<sgruszka-H+wXaHxf7aLQT0dZR+AlfA@public.gmane.org>.\n"
- "\n"
- "Signed-off-by: Zhu Yi <yi.zhu-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "Signed-off-by: Reinette Chatre <reinette.chatre-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>\n"
- "---\n"
- " drivers/net/wireless/iwlwifi/iwl-3945.c     |   16 +++++++++++-----\n"
- " drivers/net/wireless/iwlwifi/iwl-agn.c      |   11 +++++++++--\n"
- " drivers/net/wireless/iwlwifi/iwl-rx.c       |   21 ++++++++++++++-------\n"
- " drivers/net/wireless/iwlwifi/iwl3945-base.c |   18 +++++++++++++-----\n"
- " 4 files changed, 47 insertions(+), 19 deletions(-)\n"
- "\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c\n"
- "index 7d5962d..4406650 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-3945.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c\n"
- "@@ -552,6 +552,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \tu16 len = le16_to_cpu(rx_hdr->len);\n"
- " \tstruct sk_buff *skb;\n"
- " \tint ret;\n"
- "+\t__le16 fc = hdr->frame_control;\n"
- " \n"
- " \t/* We received data from the HW, so stop the watchdog */\n"
- " \tif (unlikely(len + IWL39_RX_FRAME_SIZE >\n"
- "@@ -584,9 +585,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t/* mac80211 currently doesn't support paged SKB. Convert it to\n"
- " \t * linear SKB for management frame and data frame requires\n"
- " \t * software decryption or software defragementation. */\n"
- "-\tif (ieee80211_is_mgmt(hdr->frame_control) ||\n"
- "-\t    ieee80211_has_protected(hdr->frame_control) ||\n"
- "-\t    ieee80211_has_morefrags(hdr->frame_control) ||\n"
- "+\tif (ieee80211_is_mgmt(fc) ||\n"
- "+\t    ieee80211_has_protected(fc) ||\n"
- "+\t    ieee80211_has_morefrags(fc) ||\n"
- " \t    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)\n"
- " \t\tret = skb_linearize(skb);\n"
- " \telse\n"
- "@@ -598,11 +599,16 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t\tgoto out;\n"
- " \t}\n"
- " \n"
- "+\t/*\n"
- "+\t * XXX: We cannot touch the page and its virtual memory (pkt) after\n"
- "+\t * here. It might have already been freed by the above skb change.\n"
- "+\t */\n"
- "+\n"
- " #ifdef CONFIG_IWLWIFI_LEDS\n"
- "-\tif (ieee80211_is_data(hdr->frame_control))\n"
- "+\tif (ieee80211_is_data(fc))\n"
- " \t\tpriv->rxtxpackets += len;\n"
- " #endif\n"
- "-\tiwl_update_stats(priv, false, hdr->frame_control, len);\n"
- "+\tiwl_update_stats(priv, false, fc, len);\n"
- " \n"
- " \tmemcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));\n"
- " \tieee80211_rx(priv->hw, skb);\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c\n"
- "index c5ff7c0..475f677 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-agn.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c\n"
- "@@ -808,8 +808,8 @@ void iwl_rx_handle(struct iwl_priv *priv)\n"
- " \t\tif (priv->rx_handlers[pkt->hdr.cmd]) {\n"
- " \t\t\tIWL_DEBUG_RX(priv, \"r = %d, i = %d, %s, 0x%02x\\n\", r,\n"
- " \t\t\t\ti, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);\n"
- "-\t\t\tpriv->rx_handlers[pkt->hdr.cmd] (priv, rxb);\n"
- " \t\t\tpriv->isr_stats.rx_handlers[pkt->hdr.cmd]++;\n"
- "+\t\t\tpriv->rx_handlers[pkt->hdr.cmd] (priv, rxb);\n"
- " \t\t} else {\n"
- " \t\t\t/* No handling needed */\n"
- " \t\t\tIWL_DEBUG_RX(priv,\n"
- "@@ -818,11 +818,18 @@ void iwl_rx_handle(struct iwl_priv *priv)\n"
- " \t\t\t\tpkt->hdr.cmd);\n"
- " \t\t}\n"
- " \n"
- "+\t\t/*\n"
- "+\t\t * XXX: After here, we should always check rxb->page\n"
- "+\t\t * against NULL before touching it or its virtual\n"
- "+\t\t * memory (pkt). Because some rx_handler might have\n"
- "+\t\t * already taken or freed the pages.\n"
- "+\t\t */\n"
- "+\n"
- " \t\tif (reclaim) {\n"
- " \t\t\t/* Invoke any callbacks, transfer the buffer to caller,\n"
- " \t\t\t * and fire off the (possibly) blocking iwl_send_cmd()\n"
- " \t\t\t * as we reclaim the driver command queue */\n"
- "-\t\t\tif (rxb && rxb->page)\n"
- "+\t\t\tif (rxb->page)\n"
- " \t\t\t\tiwl_tx_cmd_complete(priv, rxb);\n"
- " \t\t\telse\n"
- " \t\t\t\tIWL_WARN(priv, \"Claim null rxb?\\n\");\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c\n"
- "index 5e56857..2663689 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl-rx.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl-rx.c\n"
- "@@ -241,6 +241,7 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \tstruct iwl_rx_mem_buffer *rxb;\n"
- " \tstruct page *page;\n"
- " \tunsigned long flags;\n"
- "+\tgfp_t gfp_mask = priority;\n"
- " \n"
- " \twhile (1) {\n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- "@@ -251,13 +252,13 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " \n"
- " \t\tif (rxq->free_count > RX_LOW_WATERMARK)\n"
- "-\t\t\tpriority |= __GFP_NOWARN;\n"
- "+\t\t\tgfp_mask |= __GFP_NOWARN;\n"
- " \n"
- " \t\tif (priv->hw_params.rx_page_order > 0)\n"
- "-\t\t\tpriority |= __GFP_COMP;\n"
- "+\t\t\tgfp_mask |= __GFP_COMP;\n"
- " \n"
- " \t\t/* Alloc a new receive buffer */\n"
- "-\t\tpage = alloc_pages(priority, priv->hw_params.rx_page_order);\n"
- "+\t\tpage = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);\n"
- " \t\tif (!page) {\n"
- " \t\t\tif (net_ratelimit())\n"
- " \t\t\t\tIWL_DEBUG_INFO(priv, \"alloc_pages failed, \"\n"
- "@@ -884,6 +885,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " {\n"
- " \tstruct sk_buff *skb;\n"
- " \tint ret = 0;\n"
- "+\t__le16 fc = hdr->frame_control;\n"
- " \n"
- " \t/* We only process data packets if the interface is open */\n"
- " \tif (unlikely(!priv->is_open)) {\n"
- "@@ -908,9 +910,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t/* mac80211 currently doesn't support paged SKB. Convert it to\n"
- " \t * linear SKB for management frame and data frame requires\n"
- " \t * software decryption or software defragementation. */\n"
- "-\tif (ieee80211_is_mgmt(hdr->frame_control) ||\n"
- "-\t    ieee80211_has_protected(hdr->frame_control) ||\n"
- "-\t    ieee80211_has_morefrags(hdr->frame_control) ||\n"
- "+\tif (ieee80211_is_mgmt(fc) ||\n"
- "+\t    ieee80211_has_protected(fc) ||\n"
- "+\t    ieee80211_has_morefrags(fc) ||\n"
- " \t    le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)\n"
- " \t\tret = skb_linearize(skb);\n"
- " \telse\n"
- "@@ -922,7 +924,12 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,\n"
- " \t\tgoto out;\n"
- " \t}\n"
- " \n"
- "-\tiwl_update_stats(priv, false, hdr->frame_control, len);\n"
- "+\t/*\n"
- "+\t * XXX: We cannot touch the page and its virtual memory (hdr) after\n"
- "+\t * here. It might have already been freed by the above skb change.\n"
- "+\t */\n"
- "+\n"
- "+\tiwl_update_stats(priv, false, fc, len);\n"
- " \tmemcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));\n"
- " \n"
- " \tieee80211_rx(priv->hw, skb);\n"
- "diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c\n"
- "index e20690d..5ae8698 100644\n"
- "--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c\n"
- "+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c\n"
- "@@ -1137,6 +1137,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \tstruct iwl_rx_mem_buffer *rxb;\n"
- " \tstruct page *page;\n"
- " \tunsigned long flags;\n"
- "+\tgfp_t gfp_mask = priority;\n"
- " \n"
- " \twhile (1) {\n"
- " \t\tspin_lock_irqsave(&rxq->lock, flags);\n"
- "@@ -1148,13 +1149,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)\n"
- " \t\tspin_unlock_irqrestore(&rxq->lock, flags);\n"
- " \n"
- " \t\tif (rxq->free_count > RX_LOW_WATERMARK)\n"
- "-\t\t\tpriority |= __GFP_NOWARN;\n"
- "+\t\t\tgfp_mask |= __GFP_NOWARN;\n"
- " \n"
- " \t\tif (priv->hw_params.rx_page_order > 0)\n"
- "-\t\t\tpriority |= __GFP_COMP;\n"
- "+\t\t\tgfp_mask |= __GFP_COMP;\n"
- " \n"
- " \t\t/* Alloc a new receive buffer */\n"
- "-\t\tpage = alloc_pages(priority, priv->hw_params.rx_page_order);\n"
- "+\t\tpage = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);\n"
- " \t\tif (!page) {\n"
- " \t\t\tif (net_ratelimit())\n"
- " \t\t\t\tIWL_DEBUG_INFO(priv, \"Failed to allocate SKB buffer.\\n\");\n"
- "@@ -1420,8 +1421,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)\n"
- " \t\tif (priv->rx_handlers[pkt->hdr.cmd]) {\n"
- " \t\t\tIWL_DEBUG_RX(priv, \"r = %d, i = %d, %s, 0x%02x\\n\", r, i,\n"
- " \t\t\t\tget_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);\n"
- "-\t\t\tpriv->rx_handlers[pkt->hdr.cmd] (priv, rxb);\n"
- " \t\t\tpriv->isr_stats.rx_handlers[pkt->hdr.cmd]++;\n"
- "+\t\t\tpriv->rx_handlers[pkt->hdr.cmd] (priv, rxb);\n"
- " \t\t} else {\n"
- " \t\t\t/* No handling needed */\n"
- " \t\t\tIWL_DEBUG_RX(priv,\n"
- "@@ -1430,11 +1431,18 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)\n"
- " \t\t\t\tpkt->hdr.cmd);\n"
- " \t\t}\n"
- " \n"
- "+\t\t/*\n"
- "+\t\t * XXX: After here, we should always check rxb->page\n"
- "+\t\t * against NULL before touching it or its virtual\n"
- "+\t\t * memory (pkt). Because some rx_handler might have\n"
- "+\t\t * already taken or freed the pages.\n"
- "+\t\t */\n"
- "+\n"
- " \t\tif (reclaim) {\n"
- " \t\t\t/* Invoke any callbacks, transfer the buffer to caller,\n"
- " \t\t\t * and fire off the (possibly) blocking iwl_send_cmd()\n"
- " \t\t\t * as we reclaim the driver command queue */\n"
- "-\t\t\tif (rxb && rxb->page)\n"
- "+\t\t\tif (rxb->page)\n"
- " \t\t\t\tiwl_tx_cmd_complete(priv, rxb);\n"
- " \t\t\telse\n"
- " \t\t\t\tIWL_WARN(priv, \"Claim null rxb?\\n\");\n"
- "-- \n"
- 1.5.6.3
 
-99025b4ff234e0365c9a5f712d085ec78b9bfec0a747f8ae86d0864485f7fa1a
+ef2aa04c30b495dd1c668e41a1f0d1ae82720281b109d4ef91e77d2578b94143

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