aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-3945.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-rx.c21
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c18
4 files changed, 46 insertions, 19 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c
index 269b9889e39e..f5d75288bd27 100644
--- a/drivers/net/wireless/iwlwifi/iwl-3945.c
+++ b/drivers/net/wireless/iwlwifi/iwl-3945.c
@@ -548,6 +548,7 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
548 u16 len = le16_to_cpu(rx_hdr->len); 548 u16 len = le16_to_cpu(rx_hdr->len);
549 struct sk_buff *skb; 549 struct sk_buff *skb;
550 int ret; 550 int ret;
551 __le16 fc = hdr->frame_control;
551 552
552 /* We received data from the HW, so stop the watchdog */ 553 /* We received data from the HW, so stop the watchdog */
553 if (unlikely(len + IWL39_RX_FRAME_SIZE > 554 if (unlikely(len + IWL39_RX_FRAME_SIZE >
@@ -580,9 +581,9 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
580 /* mac80211 currently doesn't support paged SKB. Convert it to 581 /* mac80211 currently doesn't support paged SKB. Convert it to
581 * linear SKB for management frame and data frame requires 582 * linear SKB for management frame and data frame requires
582 * software decryption or software defragementation. */ 583 * software decryption or software defragementation. */
583 if (ieee80211_is_mgmt(hdr->frame_control) || 584 if (ieee80211_is_mgmt(fc) ||
584 ieee80211_has_protected(hdr->frame_control) || 585 ieee80211_has_protected(fc) ||
585 ieee80211_has_morefrags(hdr->frame_control) || 586 ieee80211_has_morefrags(fc) ||
586 le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) 587 le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
587 ret = skb_linearize(skb); 588 ret = skb_linearize(skb);
588 else 589 else
@@ -594,11 +595,15 @@ static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
594 goto out; 595 goto out;
595 } 596 }
596 597
597 iwl_update_stats(priv, false, hdr->frame_control, len); 598 /*
599 * XXX: We cannot touch the page and its virtual memory (pkt) after
600 * here. It might have already been freed by the above skb change.
601 */
598 602
603 iwl_update_stats(priv, false, fc, len);
599 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); 604 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
600 ieee80211_rx(priv->hw, skb);
601 605
606 ieee80211_rx(priv->hw, skb);
602 out: 607 out:
603 priv->alloc_rxb_page--; 608 priv->alloc_rxb_page--;
604 rxb->page = NULL; 609 rxb->page = NULL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index a34acb7e44c3..0d3886505205 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -814,8 +814,8 @@ void iwl_rx_handle(struct iwl_priv *priv)
814 if (priv->rx_handlers[pkt->hdr.cmd]) { 814 if (priv->rx_handlers[pkt->hdr.cmd]) {
815 IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, 815 IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
816 i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); 816 i, get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
817 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
818 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; 817 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
818 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
819 } else { 819 } else {
820 /* No handling needed */ 820 /* No handling needed */
821 IWL_DEBUG_RX(priv, 821 IWL_DEBUG_RX(priv,
@@ -824,11 +824,18 @@ void iwl_rx_handle(struct iwl_priv *priv)
824 pkt->hdr.cmd); 824 pkt->hdr.cmd);
825 } 825 }
826 826
827 /*
828 * XXX: After here, we should always check rxb->page
829 * against NULL before touching it or its virtual
830 * memory (pkt). Because some rx_handler might have
831 * already taken or freed the pages.
832 */
833
827 if (reclaim) { 834 if (reclaim) {
828 /* Invoke any callbacks, transfer the buffer to caller, 835 /* Invoke any callbacks, transfer the buffer to caller,
829 * and fire off the (possibly) blocking iwl_send_cmd() 836 * and fire off the (possibly) blocking iwl_send_cmd()
830 * as we reclaim the driver command queue */ 837 * as we reclaim the driver command queue */
831 if (rxb && rxb->page) 838 if (rxb->page)
832 iwl_tx_cmd_complete(priv, rxb); 839 iwl_tx_cmd_complete(priv, rxb);
833 else 840 else
834 IWL_WARN(priv, "Claim null rxb?\n"); 841 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 cfc31ae4712b..e5339c9ad13e 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)
241 struct iwl_rx_mem_buffer *rxb; 241 struct iwl_rx_mem_buffer *rxb;
242 struct page *page; 242 struct page *page;
243 unsigned long flags; 243 unsigned long flags;
244 gfp_t gfp_mask = priority;
244 245
245 while (1) { 246 while (1) {
246 spin_lock_irqsave(&rxq->lock, flags); 247 spin_lock_irqsave(&rxq->lock, flags);
@@ -251,13 +252,13 @@ void iwl_rx_allocate(struct iwl_priv *priv, gfp_t priority)
251 spin_unlock_irqrestore(&rxq->lock, flags); 252 spin_unlock_irqrestore(&rxq->lock, flags);
252 253
253 if (rxq->free_count > RX_LOW_WATERMARK) 254 if (rxq->free_count > RX_LOW_WATERMARK)
254 priority |= __GFP_NOWARN; 255 gfp_mask |= __GFP_NOWARN;
255 256
256 if (priv->hw_params.rx_page_order > 0) 257 if (priv->hw_params.rx_page_order > 0)
257 priority |= __GFP_COMP; 258 gfp_mask |= __GFP_COMP;
258 259
259 /* Alloc a new receive buffer */ 260 /* Alloc a new receive buffer */
260 page = alloc_pages(priority, priv->hw_params.rx_page_order); 261 page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
261 if (!page) { 262 if (!page) {
262 if (net_ratelimit()) 263 if (net_ratelimit())
263 IWL_DEBUG_INFO(priv, "alloc_pages failed, " 264 IWL_DEBUG_INFO(priv, "alloc_pages failed, "
@@ -922,6 +923,7 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
922{ 923{
923 struct sk_buff *skb; 924 struct sk_buff *skb;
924 int ret = 0; 925 int ret = 0;
926 __le16 fc = hdr->frame_control;
925 927
926 /* We only process data packets if the interface is open */ 928 /* We only process data packets if the interface is open */
927 if (unlikely(!priv->is_open)) { 929 if (unlikely(!priv->is_open)) {
@@ -946,9 +948,9 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
946 /* mac80211 currently doesn't support paged SKB. Convert it to 948 /* mac80211 currently doesn't support paged SKB. Convert it to
947 * linear SKB for management frame and data frame requires 949 * linear SKB for management frame and data frame requires
948 * software decryption or software defragementation. */ 950 * software decryption or software defragementation. */
949 if (ieee80211_is_mgmt(hdr->frame_control) || 951 if (ieee80211_is_mgmt(fc) ||
950 ieee80211_has_protected(hdr->frame_control) || 952 ieee80211_has_protected(fc) ||
951 ieee80211_has_morefrags(hdr->frame_control) || 953 ieee80211_has_morefrags(fc) ||
952 le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) 954 le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG)
953 ret = skb_linearize(skb); 955 ret = skb_linearize(skb);
954 else 956 else
@@ -960,7 +962,12 @@ static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
960 goto out; 962 goto out;
961 } 963 }
962 964
963 iwl_update_stats(priv, false, hdr->frame_control, len); 965 /*
966 * XXX: We cannot touch the page and its virtual memory (hdr) after
967 * here. It might have already been freed by the above skb change.
968 */
969
970 iwl_update_stats(priv, false, fc, len);
964 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats)); 971 memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
965 972
966 ieee80211_rx(priv->hw, skb); 973 ieee80211_rx(priv->hw, skb);
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 5977a57a234c..8b08bdc10bc9 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -1124,6 +1124,7 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
1124 struct iwl_rx_mem_buffer *rxb; 1124 struct iwl_rx_mem_buffer *rxb;
1125 struct page *page; 1125 struct page *page;
1126 unsigned long flags; 1126 unsigned long flags;
1127 gfp_t gfp_mask = priority;
1127 1128
1128 while (1) { 1129 while (1) {
1129 spin_lock_irqsave(&rxq->lock, flags); 1130 spin_lock_irqsave(&rxq->lock, flags);
@@ -1135,13 +1136,13 @@ static void iwl3945_rx_allocate(struct iwl_priv *priv, gfp_t priority)
1135 spin_unlock_irqrestore(&rxq->lock, flags); 1136 spin_unlock_irqrestore(&rxq->lock, flags);
1136 1137
1137 if (rxq->free_count > RX_LOW_WATERMARK) 1138 if (rxq->free_count > RX_LOW_WATERMARK)
1138 priority |= __GFP_NOWARN; 1139 gfp_mask |= __GFP_NOWARN;
1139 1140
1140 if (priv->hw_params.rx_page_order > 0) 1141 if (priv->hw_params.rx_page_order > 0)
1141 priority |= __GFP_COMP; 1142 gfp_mask |= __GFP_COMP;
1142 1143
1143 /* Alloc a new receive buffer */ 1144 /* Alloc a new receive buffer */
1144 page = alloc_pages(priority, priv->hw_params.rx_page_order); 1145 page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
1145 if (!page) { 1146 if (!page) {
1146 if (net_ratelimit()) 1147 if (net_ratelimit())
1147 IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n"); 1148 IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
@@ -1410,8 +1411,8 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
1410 if (priv->rx_handlers[pkt->hdr.cmd]) { 1411 if (priv->rx_handlers[pkt->hdr.cmd]) {
1411 IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i, 1412 IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
1412 get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd); 1413 get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
1413 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
1414 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++; 1414 priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
1415 priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
1415 } else { 1416 } else {
1416 /* No handling needed */ 1417 /* No handling needed */
1417 IWL_DEBUG_RX(priv, 1418 IWL_DEBUG_RX(priv,
@@ -1420,11 +1421,18 @@ static void iwl3945_rx_handle(struct iwl_priv *priv)
1420 pkt->hdr.cmd); 1421 pkt->hdr.cmd);
1421 } 1422 }
1422 1423
1424 /*
1425 * XXX: After here, we should always check rxb->page
1426 * against NULL before touching it or its virtual
1427 * memory (pkt). Because some rx_handler might have
1428 * already taken or freed the pages.
1429 */
1430
1423 if (reclaim) { 1431 if (reclaim) {
1424 /* Invoke any callbacks, transfer the buffer to caller, 1432 /* Invoke any callbacks, transfer the buffer to caller,
1425 * and fire off the (possibly) blocking iwl_send_cmd() 1433 * and fire off the (possibly) blocking iwl_send_cmd()
1426 * as we reclaim the driver command queue */ 1434 * as we reclaim the driver command queue */
1427 if (rxb && rxb->page) 1435 if (rxb->page)
1428 iwl_tx_cmd_complete(priv, rxb); 1436 iwl_tx_cmd_complete(priv, rxb);
1429 else 1437 else
1430 IWL_WARN(priv, "Claim null rxb?\n"); 1438 IWL_WARN(priv, "Claim null rxb?\n");