]> bbs.cooldavid.org Git - net-next-2.6.git/blobdiff - drivers/net/sis900.c
sis900: Allocate rx replacement buffer before rx operation
[net-next-2.6.git] / drivers / net / sis900.c
index b3750f28427926d29e101b5a0bbd5f58a619e3e6..b2a3b19d773a8c8979bcb066dc9e1059c880cb2d 100644 (file)
@@ -1755,6 +1755,24 @@ static int sis900_rx(struct net_device *net_dev)
                } else {
                        struct sk_buff * skb;
 
+                       pci_unmap_single(sis_priv->pci_dev,
+                               sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE,
+                               PCI_DMA_FROMDEVICE);
+
+                       /* refill the Rx buffer, what if there is not enought
+                        * memory for new socket buffer ?? */
+                       if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
+                               /*
+                                * Not enough memory to refill the buffer
+                                * so we need to recycle the old one so
+                                * as to avoid creating a memory hole
+                                * in the rx ring
+                                */
+                               skb = sis_priv->rx_skbuff[entry];
+                               sis_priv->stats.rx_dropped++;
+                               goto refill_rx_ring;
+                       }       
+
                        /* This situation should never happen, but due to
                           some unknow bugs, it is possible that
                           we are working on NULL sk_buff :-( */
@@ -1768,9 +1786,6 @@ static int sis900_rx(struct net_device *net_dev)
                                break;
                        }
 
-                       pci_unmap_single(sis_priv->pci_dev,
-                               sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE,
-                               PCI_DMA_FROMDEVICE);
                        /* give the socket buffer to upper layers */
                        skb = sis_priv->rx_skbuff[entry];
                        skb_put(skb, rx_size);
@@ -1783,33 +1798,14 @@ static int sis900_rx(struct net_device *net_dev)
                        net_dev->last_rx = jiffies;
                        sis_priv->stats.rx_bytes += rx_size;
                        sis_priv->stats.rx_packets++;
-
-                       /* refill the Rx buffer, what if there is not enought
-                        * memory for new socket buffer ?? */
-                       if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
-                               /* not enough memory for skbuff, this makes a
-                                * "hole" on the buffer ring, it is not clear
-                                * how the hardware will react to this kind
-                                * of degenerated buffer */
-                               if (netif_msg_rx_status(sis_priv))
-                                       printk(KERN_INFO "%s: Memory squeeze,"
-                                               "deferring packet.\n",
-                                               net_dev->name);
-                               sis_priv->rx_skbuff[entry] = NULL;
-                               /* reset buffer descriptor state */
-                               sis_priv->rx_ring[entry].cmdsts = 0;
-                               sis_priv->rx_ring[entry].bufptr = 0;
-                               sis_priv->stats.rx_dropped++;
-                               sis_priv->cur_rx++;
-                               break;
-                       }
+                       sis_priv->dirty_rx++;
+refill_rx_ring:
                        skb->dev = net_dev;
                        sis_priv->rx_skbuff[entry] = skb;
                        sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
                        sis_priv->rx_ring[entry].bufptr =
                                pci_map_single(sis_priv->pci_dev, skb->data,
                                        RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
-                       sis_priv->dirty_rx++;
                }
                sis_priv->cur_rx++;
                entry = sis_priv->cur_rx % NUM_RX_DESC;