Skip to content

Commit

Permalink
staging: rtl8192e: Fix kernel panics due to RX skb allocation failures
Browse files Browse the repository at this point in the history
This driver uses RX skb's of O(2), thus it is possible for memory fragmentation
to prevent the allocation of a new one to replace a newly-received buffer.
When such a failure occurs, the kernel panics.

The fix is to drop an incoming packet whenever such an allocation fails. This
fix matches the one done in rtlwifi for other Realtek PCI devices.

Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
  • Loading branch information
Larry Finger authored and Larry Finger committed Aug 24, 2011
1 parent b1d5ee7 commit 82a7fc6
Showing 1 changed file with 19 additions and 25 deletions.
44 changes: 19 additions & 25 deletions drivers/staging/rtl8192e/rtl_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -2550,12 +2550,18 @@ void rtl8192_rx_normal(struct net_device *dev)
rx_desc *pdesc = &priv->rx_ring[rx_queue_idx][priv->rx_idx[rx_queue_idx]];
struct sk_buff *skb = priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]];

if (pdesc->OWN){
if (pdesc->OWN) {
return;
} else {
struct sk_buff *new_skb;

struct sk_buff *new_skb = NULL;
if (!priv->ops->rx_query_status_descriptor(dev, &stats, pdesc, skb))
if (!priv->ops->rx_query_status_descriptor(dev, &stats,
pdesc, skb))
goto done;
new_skb = dev_alloc_skb(priv->rxbuffersize);
/* if allocation of new skb failed - drop current packet
* and reuse skb */
if (unlikely(!new_skb))
goto done;

pci_unmap_single(priv->pdev,
Expand All @@ -2564,24 +2570,24 @@ void rtl8192_rx_normal(struct net_device *dev)
PCI_DMA_FROMDEVICE);

skb_put(skb, pdesc->Length);
skb_reserve(skb, stats.RxDrvInfoSize + stats.RxBufShift);
skb_reserve(skb, stats.RxDrvInfoSize +
stats.RxBufShift);
skb_trim(skb, skb->len - 4/*sCrcLng*/);
rtllib_hdr = (struct rtllib_hdr_1addr *)skb->data;
if (is_broadcast_ether_addr(rtllib_hdr->addr1)) {
}else if (is_multicast_ether_addr(rtllib_hdr->addr1)){
}else {
if (!is_broadcast_ether_addr(rtllib_hdr->addr1) &&
!is_multicast_ether_addr(rtllib_hdr->addr1)) {
/* unicast packet */
unicast_packet = true;
}
fc = le16_to_cpu(rtllib_hdr->frame_ctl);
type = WLAN_FC_GET_TYPE(fc);
if (type == RTLLIB_FTYPE_MGMT)
{
bLedBlinking = false;
}

if (bLedBlinking)
if (priv->rtllib->LedControlHandler)
priv->rtllib->LedControlHandler(dev, LED_CTL_RX);
priv->rtllib->LedControlHandler(dev,
LED_CTL_RX);

if (stats.bCRC) {
if (type != RTLLIB_FTYPE_MGMT)
Expand All @@ -2592,28 +2598,16 @@ void rtl8192_rx_normal(struct net_device *dev)

skb_len = skb->len;

if (1)
{
if (!rtllib_rx(priv->rtllib, skb, &stats)){
dev_kfree_skb_any(skb);
} else {
priv->stats.rxok++;
if (unicast_packet) {
if (unicast_packet)
priv->stats.rxbytesunicast += skb_len;
}
}
}else{
dev_kfree_skb_any(skb);
}

new_skb = dev_alloc_skb(priv->rxbuffersize);
if (unlikely(!new_skb))
{
printk("==========>can't alloc skb for rx\n");
goto done;
}
skb=new_skb;
skb->dev = dev;
skb = new_skb;
skb->dev = dev;

priv->rx_buf[rx_queue_idx][priv->rx_idx[rx_queue_idx]] = skb;
*((dma_addr_t *) skb->cb) = pci_map_single(priv->pdev, skb_tail_pointer_rsl(skb), priv->rxbuffersize, PCI_DMA_FROMDEVICE);
Expand Down

0 comments on commit 82a7fc6

Please sign in to comment.