--- ./drivers/net/sis900.c.sis900 2005-08-29 03:41:01.000000000 +0400
+++ ./drivers/net/sis900.c 2005-09-19 14:34:42.000000000 +0400
@@ -1696,6 +1696,14 @@ static int sis900_rx(struct net_device *
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;
+ /*
+ * If cur > dirty, then limit = NUM_RX_DESC - cur + dirty =
+ * NUM_RX_DESC + (dirty - cur)
+ * If cur < dirty (cur overflowed, dirty - not), then
+ * limit = dirty - cur
+ */
+ int rx_work_limit =
+ (sis_priv->dirty_rx - sis_priv->cur_rx) % NUM_RX_DESC;
if (netif_msg_rx_status(sis_priv))
printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
@@ -1705,6 +1713,8 @@ static int sis900_rx(struct net_device *
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)) {
@@ -1770,6 +1780,7 @@ static int sis900_rx(struct net_device *
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;
@@ -1787,7 +1798,7 @@ static int sis900_rx(struct net_device *
/* 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;
#
# Patch solves following problems:
# 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 avaliable.
# 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 <[email protected]>
# Signed-off-by: Vasily Averin <[email protected]>
Il giorno 26/set/05, alle ore 14:19, Konstantin Khorenko ha scritto:
> Hope, you'll check this changes and find them usefull. :)
> Kernels with patches compile but untested.
> This patch is against mainstream 2.6.13.1 kernel.
> --- ./drivers/net/sis900.c.sis900 2005-08-29 03:41:01.000000000
> +0400
> +++ ./drivers/net/sis900.c 2005-09-19 14:34:42.000000000 +0400
Please create the diff one directory above the root sources directory
so that it is possible to apply with 'patch -p1'.
> @@ -1696,6 +1696,14 @@ static int sis900_rx(struct net_device *
> 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;
> + /*
> + * If cur > dirty, then limit = NUM_RX_DESC - cur + dirty =
> + * NUM_RX_DESC + (dirty - cur)
> + * If cur < dirty (cur overflowed, dirty - not), then
> + * limit = dirty - cur
> + */
> + int rx_work_limit =
> + (sis_priv->dirty_rx - sis_priv->cur_rx) % NUM_RX_DESC;
Remove this comment, or move it to the description of the function
above the sis900_rx() declaration.
>
> if (netif_msg_rx_status(sis_priv))
> printk(KERN_DEBUG "sis900_rx, cur_rx:%4.4d, dirty_rx:%4.4d "
> @@ -1705,6 +1713,8 @@ static int sis900_rx(struct net_device *
> 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)) {
> @@ -1770,6 +1780,7 @@ static int sis900_rx(struct net_device *
> 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;
> @@ -1787,7 +1798,7 @@ static int sis900_rx(struct net_device *
>
> /* 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;
With those corrections, the patch should be resent to me, to Jeff
Garzik and to the netdev mailing list for review and possibly inclusion.
Thanks for the contribution.
--
Daniele Venzano
http://www.brownhat.org