Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 171061
b: refs/heads/master
c: 29b1b26
h: refs/heads/master
i:
  171059: 9a11052
v: v3
  • Loading branch information
Zhu Yi authored and John W. Linville committed Oct 27, 2009
1 parent 66d9d75 commit 9aa6799
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 52aa081c40324ecb04a47864e4e56dafc5a72a34
refs/heads/master: 29b1b2688fd71346f78f175d9669c006686b6dc3
15 changes: 10 additions & 5 deletions trunk/drivers/net/wireless/iwlwifi/iwl-3945.c
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,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 >
Expand Down Expand Up @@ -580,9 +581,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
Expand All @@ -594,11 +595,15 @@ static void iwl3945_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 (pkt) 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);

ieee80211_rx(priv->hw, skb);
out:
priv->alloc_rxb_page--;
rxb->page = NULL;
Expand Down
11 changes: 9 additions & 2 deletions trunk/drivers/net/wireless/iwlwifi/iwl-agn.c
Original file line number Diff line number Diff line change
Expand Up @@ -814,8 +814,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,
Expand All @@ -824,11 +824,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");
Expand Down
21 changes: 14 additions & 7 deletions trunk/drivers/net/wireless/iwlwifi/iwl-rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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, "
Expand Down Expand Up @@ -922,6 +923,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)) {
Expand All @@ -946,9 +948,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
Expand All @@ -960,7 +962,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);
Expand Down
18 changes: 13 additions & 5 deletions trunk/drivers/net/wireless/iwlwifi/iwl3945-base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1124,6 +1124,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);
Expand All @@ -1135,13 +1136,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");
Expand Down Expand Up @@ -1410,8 +1411,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,
Expand All @@ -1420,11 +1421,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");
Expand Down

0 comments on commit 9aa6799

Please sign in to comment.