aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sis900.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2007-04-26 13:47:36 -0400
committerJeff Garzik <jeff@garzik.org>2007-04-27 20:16:41 -0400
commitdc5a144991ba803bc8afded105c9db1dea0e57ab (patch)
tree81366a449cc3236446f7d84523e35eb260cfb524 /drivers/net/sis900.c
parent1764f15016fea54db723a96234a82646dac9a036 (diff)
sis900: Allocate rx replacement buffer before rx operation
Just found a hole in my last patch. It was reported to me that shortly after we integrated this patch. The report was of an oops that took place inside of netif_rx when using the sis900 driver. Looking at my origional patch I noted that there was a spot between the new skb_alloc and the refill_rx_ring label where skb got reassigned to the pointer currently held in the rx_ring for the purposes of receiveing the frame. The result of this is however that the buffer that gets passed to netif_rx (if it is called), then gets placed right back into the rx_ring. So if you receive frames fast enough the skb being processed by the network stack can get corrupted. The reporter is testing out the fix I've written for this below (I'm not near my hardware at the moment to test myself), but I wanted to post it for review ASAP. I'll post test results when I hear them, but I think this is a pretty straightforward fix. It just uses a separate pointer to do the rx operation, so that we don't improperly reassign the pointer that we use to refill the rx ring. 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.c9
1 files changed, 5 insertions, 4 deletions
diff --git a/drivers/net/sis900.c b/drivers/net/sis900.c
index dea0126723da..2cb2e156c758 100644
--- a/drivers/net/sis900.c
+++ b/drivers/net/sis900.c
@@ -1753,6 +1753,7 @@ static int sis900_rx(struct net_device *net_dev)
1753 sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE; 1753 sis_priv->rx_ring[entry].cmdsts = RX_BUF_SIZE;
1754 } else { 1754 } else {
1755 struct sk_buff * skb; 1755 struct sk_buff * skb;
1756 struct sk_buff * rx_skb;
1756 1757
1757 pci_unmap_single(sis_priv->pci_dev, 1758 pci_unmap_single(sis_priv->pci_dev,
1758 sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE, 1759 sis_priv->rx_ring[entry].bufptr, RX_BUF_SIZE,
@@ -1786,10 +1787,10 @@ static int sis900_rx(struct net_device *net_dev)
1786 } 1787 }
1787 1788
1788 /* give the socket buffer to upper layers */ 1789 /* give the socket buffer to upper layers */
1789 skb = sis_priv->rx_skbuff[entry]; 1790 rx_skb = sis_priv->rx_skbuff[entry];
1790 skb_put(skb, rx_size); 1791 skb_put(rx_skb, rx_size);
1791 skb->protocol = eth_type_trans(skb, net_dev); 1792 rx_skb->protocol = eth_type_trans(rx_skb, net_dev);
1792 netif_rx(skb); 1793 netif_rx(rx_skb);
1793 1794
1794 /* some network statistics */ 1795 /* some network statistics */
1795 if ((rx_status & BCAST) == MCAST) 1796 if ((rx_status & BCAST) == MCAST)