Skip to content

Commit

Permalink
sis900: come alive after temporary memory shortage
Browse files Browse the repository at this point in the history
1) Forgotten counter incrementation in sis900_rx() in case
     it doesn't get memory for skb, that leads to whole interface failure.
     Problem is accompanied with messages:
    eth0: Memory squeeze,deferring packet.
    eth0: NULL pointer encountered in Rx ring, skipping

2) If counter cur_rx overflows and there'll be temporary memory problems
     buffer can't be recreated later, when memory IS available.

3) Limit the work in handler to prevent the endless packets processing
   if new packets are generated faster then handled.

Signed-off-by: Konstantin Khorenko <khorenko@sw.ru>
Signed-off-by: Vasily Averin <vvs@sw.ru>
Signed-off-by: Jeff Garzik <jgarzik@pobox.com>
  • Loading branch information
Vasily Averin authored and Jeff Garzik committed Oct 28, 2005
1 parent b2795f5 commit 7380a78
Showing 1 changed file with 12 additions and 4 deletions.
16 changes: 12 additions & 4 deletions drivers/net/sis900.c
Original file line number Diff line number Diff line change
Expand Up @@ -1696,15 +1696,20 @@ static int sis900_rx(struct net_device *net_dev)
long ioaddr = net_dev->base_addr;
unsigned int entry = sis_priv->cur_rx % NUM_RX_DESC;
u32 rx_status = sis_priv->rx_ring[entry].cmdsts;
int rx_work_limit;

if (netif_msg_rx_status(sis_priv))
printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
"status:0x%8.8x\n",
sis_priv->cur_rx, sis_priv->dirty_rx, rx_status);
rx_work_limit = sis_priv->dirty_rx + NUM_RX_DESC - sis_priv->cur_rx;

while (rx_status & OWN) {
unsigned int rx_size;

if (--rx_work_limit < 0)
break;

rx_size = (rx_status & DSIZE) - CRC_SIZE;

if (rx_status & (ABORT|OVERRUN|TOOLONG|RUNT|RXISERR|CRCERR|FAERR)) {
Expand Down Expand Up @@ -1732,9 +1737,11 @@ static int sis900_rx(struct net_device *net_dev)
we are working on NULL sk_buff :-( */
if (sis_priv->rx_skbuff[entry] == NULL) {
if (netif_msg_rx_err(sis_priv))
printk(KERN_INFO "%s: NULL pointer "
"encountered in Rx ring, skipping\n",
net_dev->name);
printk(KERN_WARNING "%s: NULL pointer "
"encountered in Rx ring\n"
"cur_rx:%4.4d, dirty_rx:%4.4d\n",
net_dev->name, sis_priv->cur_rx,
sis_priv->dirty_rx);
break;
}

Expand Down Expand Up @@ -1770,6 +1777,7 @@ static int sis900_rx(struct net_device *net_dev)
sis_priv->rx_ring[entry].cmdsts = 0;
sis_priv->rx_ring[entry].bufptr = 0;
sis_priv->stats.rx_dropped++;
sis_priv->cur_rx++;
break;
}
skb->dev = net_dev;
Expand All @@ -1787,7 +1795,7 @@ static int sis900_rx(struct net_device *net_dev)

/* refill the Rx buffer, what if the rate of refilling is slower
* than consuming ?? */
for (;sis_priv->cur_rx - sis_priv->dirty_rx > 0; sis_priv->dirty_rx++) {
for (; sis_priv->cur_rx != sis_priv->dirty_rx; sis_priv->dirty_rx++) {
struct sk_buff *skb;

entry = sis_priv->dirty_rx % NUM_RX_DESC;
Expand Down

0 comments on commit 7380a78

Please sign in to comment.