aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sis900.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2007-04-20 09:54:58 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-24 12:43:07 -0400
commitb748d9e3b80dc7e6ce6bf7399f57964b99a4104c (patch)
tree887909e1f735bb444ef0e3e370f34401fa6eee02 /drivers/net/sis900.c
parentd91c088b39e3c66d309938de858775bb90fd1ead (diff)
sis900: Allocate rx replacement buffer before rx operation
The sis900 driver appears to have a bug in which the receive routine passes the skbuff holding the received frame to the network stack before refilling the buffer in the rx ring. If a new skbuff cannot be allocated, the driver simply leaves a hole in the rx ring, which causes the driver to stop receiving frames and become non-recoverable without an rmmod/insmod according to reporters. This patch reverses that order, attempting to allocate a replacement buffer first, and receiving the new frame only if one can be allocated. If no skbuff can be allocated, the current skbuf in the rx ring is recycled, dropping the current frame, but keeping the NIC operational. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sis900.c')
-rw-r--r--drivers/net/sis900.c44
1 files changed, 20 insertions, 24 deletions
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index b3750f284279..b2a3b19d773a 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1755,6 +1755,24 @@ static int sis900_rx(struct net_device *net_dev)
1755 } else { 1755 } else {
1756 struct sk_buff * skb; 1756 struct sk_buff * skb;
1757 1757
1758 pci_unmap_single(sis_priv->pci_dev,
1759 sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE,
1760 PCI_DMA_FROMDEVICE);
1761
1762 /* refill the Rx buffer, what if there is not enought
1763 * memory for new socket buffer ?? */
1764 if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
1765 /*
1766 * Not enough memory to refill the buffer
1767 * so we need to recycle the old one so
1768 * as to avoid creating a memory hole
1769 * in the rx ring
1770 */
1771 skb = sis_priv->rx_skbuff[entry];
1772 sis_priv->stats.rx_dropped++;
1773 goto refill_rx_ring;
1774 }
1775
1758 /* This situation should never happen, but due to 1776 /* This situation should never happen, but due to
1759 some unknow bugs, it is possible that 1777 some unknow bugs, it is possible that
1760 we are working on NULL sk_buff :-( */ 1778 we are working on NULL sk_buff :-( */
@@ -1768,9 +1786,6 @@ static int sis900_rx(struct net_device *net_dev)
1768 break; 1786 break;
1769 } 1787 }
1770 1788
1771 pci_unmap_single(sis_priv->pci_dev,
1772 sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE,
1773 PCI_DMA_FROMDEVICE);
1774 /* give the socket buffer to upper layers */ 1789 /* give the socket buffer to upper layers */
1775 skb = sis_priv->rx_skbuff[entry]; 1790 skb = sis_priv->rx_skbuff[entry];
1776 skb_put(skb, rx_size); 1791 skb_put(skb, rx_size);
@@ -1783,33 +1798,14 @@ static int sis900_rx(struct net_device *net_dev)
1783 net_dev->last_rx = jiffies; 1798 net_dev->last_rx = jiffies;
1784 sis_priv->stats.rx_bytes += rx_size; 1799 sis_priv->stats.rx_bytes += rx_size;
1785 sis_priv->stats.rx_packets++; 1800 sis_priv->stats.rx_packets++;
1786 1801 sis_priv->dirty_rx++;
1787 /* refill the Rx buffer, what if there is not enought 1802refill_rx_ring:
1788 * memory for new socket buffer ?? */
1789 if ((skb = dev_alloc_skb(RX_BUF_SIZE)) == NULL) {
1790 /* not enough memory for skbuff, this makes a
1791 * "hole" on the buffer ring, it is not clear
1792 * how the hardware will react to this kind
1793 * of degenerated buffer */
1794 if (netif_msg_rx_status(sis_priv))
1795 printk(KERN_INFO "%s: Memory squeeze,"
1796 "deferring packet.\n",
1797 net_dev->name);
1798 sis_priv->rx_skbuff[entry] = NULL;
1799 /* reset buffer descriptor state */
1800 sis_priv->rx_ring[entry].cmdsts = 0;
1801 sis_priv->rx_ring[entry].bufptr = 0;
1802 sis_priv->stats.rx_dropped++;
1803 sis_priv->cur_rx++;
1804 break;
1805 }
1806 skb->dev = net_dev; 1803 skb->dev = net_dev;
1807 sis_priv->rx_skbuff[entry] = skb; 1804 sis_priv->rx_skbuff[entry] = skb;
1808 sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; 1805 sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
1809 sis_priv->rx_ring[entry].bufptr = 1806 sis_priv->rx_ring[entry].bufptr =
1810 pci_map_single(sis_priv->pci_dev, skb->data, 1807 pci_map_single(sis_priv->pci_dev, skb->data,
1811 RX_BUF_SIZE, PCI_DMA_FROMDEVICE); 1808 RX_BUF_SIZE, PCI_DMA_FROMDEVICE);
1812 sis_priv->dirty_rx++;
1813 } 1809 }
1814 sis_priv->cur_rx++; 1810 sis_priv->cur_rx++;
1815 entry = sis_priv->cur_rx % NUM_RX_DESC; 1811 entry = sis_priv->cur_rx % NUM_RX_DESC;