Skip to content

Commit a9e1286

Browse files
lwfingerlinvjw
authored andcommitted
rtlwifi: Fix kernel panic resulting from RX buffer allocation failure
To handle amsdu_8k capability, the PCI routine of this driver must allocate receive buffers of order 2. Under heavy load, this causes fragmentation of memory. The present code releases the current buffer before checking to see if a new one is availble. Recovery from allocation failures is not possible, which results in kernel panics. The fix is to reorder the code to check that a new buffer can be allocated before the old one is released. If not possible, the received frame is dropped and the old one is reused. Without this change, it is impossible to transfer a 2 GB file without a kernel panic. Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net> Cc: Stable <stable@vger.kernel.org> [2.6.{37,38,39}] Signed-off-by: John W. Linville <linville@tuxdriver.com>
1 parent 208c72f commit a9e1286

File tree

1 file changed

+15
-13
lines changed
  • drivers/net/wireless/rtlwifi

1 file changed

+15
-13
lines changed

drivers/net/wireless/rtlwifi/pci.c

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -669,11 +669,6 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
669669
&rx_status,
670670
(u8 *) pdesc, skb);
671671

672-
pci_unmap_single(rtlpci->pdev,
673-
*((dma_addr_t *) skb->cb),
674-
rtlpci->rxbuffersize,
675-
PCI_DMA_FROMDEVICE);
676-
677672
skb_put(skb, rtlpriv->cfg->ops->get_desc((u8 *) pdesc,
678673
false,
679674
HW_DESC_RXPKT_LEN));
@@ -690,6 +685,21 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
690685
hdr = rtl_get_hdr(skb);
691686
fc = rtl_get_fc(skb);
692687

688+
/* try for new buffer - if allocation fails, drop
689+
* frame and reuse old buffer
690+
*/
691+
new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
692+
if (unlikely(!new_skb)) {
693+
RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
694+
DBG_DMESG,
695+
("can't alloc skb for rx\n"));
696+
goto done;
697+
}
698+
pci_unmap_single(rtlpci->pdev,
699+
*((dma_addr_t *) skb->cb),
700+
rtlpci->rxbuffersize,
701+
PCI_DMA_FROMDEVICE);
702+
693703
if (!stats.crc || !stats.hwerror) {
694704
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
695705
sizeof(rx_status));
@@ -758,15 +768,7 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw)
758768
rtl_lps_leave(hw);
759769
}
760770

761-
new_skb = dev_alloc_skb(rtlpci->rxbuffersize);
762-
if (unlikely(!new_skb)) {
763-
RT_TRACE(rtlpriv, (COMP_INTR | COMP_RECV),
764-
DBG_DMESG,
765-
("can't alloc skb for rx\n"));
766-
goto done;
767-
}
768771
skb = new_skb;
769-
/*skb->dev = dev; */
770772

771773
rtlpci->rx_ring[rx_queue_idx].rx_buf[rtlpci->
772774
rx_ring

0 commit comments

Comments
 (0)