I am running 2.4.16 on them and I've been testing nbd and the errors
that I have been having MAY be caused by the network going out (as per a
discussion on the ENBD list).
On Tue, 2001-12-04 at 17:57, Tim Hockin wrote:
> This patch was developed here to resolve a number of eepro100 issues we
> were seeing. I'd like to get people to try this on their eepro100 chips and
> beat on it for a while.
> 
> volunteers?
> 
> Tim
> -- 
> Tim Hockin
> Systems Software Engineer
> Sun Microsystems, Cobalt Server Appliances
> thockin@sun.com
> ----
> 
> diff -ruN 2.4.14-orig/drivers/net/eepro100.c 2.4.14-cobalt/drivers/net/eepro100.c
> --- 2.4.14-orig/drivers/net/eepro100.c	Tue Dec  4 14:30:09 2001
> +++ 2.4.14-cobalt/drivers/net/eepro100.c	Tue Dec  4 14:03:35 2001
> @@ -64,8 +64,8 @@
>  
>  /* A few values that may be tweaked. */
>  /* The ring sizes should be a power of two for efficiency. */
> -#define TX_RING_SIZE	32
> -#define RX_RING_SIZE	32
> +#define TX_RING_SIZE	64
> +#define RX_RING_SIZE	1024
>  /* How much slots multicast filter setup may take.
>     Do not descrease without changing set_rx_mode() implementaion. */
>  #define TX_MULTICAST_SIZE   2
> @@ -1067,6 +1071,50 @@
>  	outw(CUStart | SCBMaskEarlyRx | SCBMaskFlowCtl, ioaddr + SCBCmd);
>  }
>  
> +/*
> + * Sometimes the receiver stops making progress.  This routine knows how to
> + * get it going again, without losing packets or being otherwise nasty like
> + * a chip reset would be.  Previously the driver had a whole sequence
> + * of if RxSuspended, if it's no buffers do one thing, if it's no resources,
> + * do another, etc.  But those things don't really matter.  Separate logic
> + * in the ISR provides for allocating buffers--the other half of operation
> + * is just making sure the receiver is active.  speedo_rx_soft_reset does that.
> + * This problem with the old, more involved algorithm is shown up under
> + * ping floods on the order of 60K packets/second on a 100Mbps fdx network.
> + */
> +static void
> +speedo_rx_soft_reset(struct net_device *dev)
> +{
> +	struct speedo_private *sp = dev->priv;
> +	struct RxFD *rfd;
> +	long ioaddr;
> +
> +	ioaddr = dev->base_addr;
> +	wait_for_cmd_done(ioaddr + SCBCmd);
> +	if (inb(ioaddr + SCBCmd) != 0) {
> +		printk("%s: previous command stalled\n", dev->name);
> +		return;
> +	}
> +	/*
> +	* Put the hardware into a known state.
> +	*/
> +	outb(RxAbort, ioaddr + SCBCmd);
> +
> +	rfd = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
> +
> +	rfd->rx_buf_addr = 0xffffffff;
> +
> +	wait_for_cmd_done(ioaddr + SCBCmd);
> +
> +	if (inb(ioaddr + SCBCmd) != 0) {
> +		printk("%s: RxAbort command stalled\n", dev->name);
> +		return;
> +	}
> +	outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
> +		ioaddr + SCBPointer);
> +	outb(RxStart, ioaddr + SCBCmd);
> +}
> +
>  /* Media monitoring and control. */
>  static void speedo_timer(unsigned long data)
>  {
> @@ -1500,82 +1591,37 @@
>  		if ((status & 0xfc00) == 0)
>  			break;
>  
> -		/* Always check if all rx buffers are allocated.  --SAW */
> -		speedo_refill_rx_buffers(dev, 0);
> -
>  		if ((status & 0x5000) ||	/* Packet received, or Rx error. */
>  			(sp->rx_ring_state&(RrNoMem|RrPostponed)) == RrPostponed)
>  									/* Need to gather the postponed packet. */
>  			speedo_rx(dev);
>  
> -		if (status & 0x1000) {
> -			spin_lock(&sp->lock);
> -			if ((status & 0x003c) == 0x0028) {		/* No more Rx buffers. */
> -				struct RxFD *rxf;
> -				printk(KERN_WARNING "%s: card reports no RX buffers.\n",
> -						dev->name);
> -				rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
> -				if (rxf == NULL) {
> -					if (speedo_debug > 2)
> -						printk(KERN_DEBUG
> -								"%s: NULL cur_rx in speedo_interrupt().\n",
> -								dev->name);
> -					sp->rx_ring_state |= RrNoMem|RrNoResources;
> -				} else if (rxf == sp->last_rxf) {
> -					if (speedo_debug > 2)
> -						printk(KERN_DEBUG
> -								"%s: cur_rx is last in speedo_interrupt().\n",
> -								dev->name);
> -					sp->rx_ring_state |= RrNoMem|RrNoResources;
> -				} else
> -					outb(RxResumeNoResources, ioaddr + SCBCmd);
> -			} else if ((status & 0x003c) == 0x0008) { /* No resources. */
> -				struct RxFD *rxf;
> -				printk(KERN_WARNING "%s: card reports no resources.\n",
> -						dev->name);
> -				rxf = sp->rx_ringp[sp->cur_rx % RX_RING_SIZE];
> -				if (rxf == NULL) {
> -					if (speedo_debug > 2)
> -						printk(KERN_DEBUG
> -								"%s: NULL cur_rx in speedo_interrupt().\n",
> -								dev->name);
> -					sp->rx_ring_state |= RrNoMem|RrNoResources;
> -				} else if (rxf == sp->last_rxf) {
> -					if (speedo_debug > 2)
> -						printk(KERN_DEBUG
> -								"%s: cur_rx is last in speedo_interrupt().\n",
> -								dev->name);
> -					sp->rx_ring_state |= RrNoMem|RrNoResources;
> -				} else {
> -					/* Restart the receiver. */
> -					outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
> -						 ioaddr + SCBPointer);
> -					outb(RxStart, ioaddr + SCBCmd);
> -				}
> -			}
> -			sp->stats.rx_errors++;
> -			spin_unlock(&sp->lock);
> -		}
> +		/* Always check if all rx buffers are allocated.  --SAW */
> +		speedo_refill_rx_buffers(dev, 0);
>  
> -		if ((sp->rx_ring_state&(RrNoMem|RrNoResources)) == RrNoResources) {
> -			printk(KERN_WARNING
> -					"%s: restart the receiver after a possible hang.\n",
> -					dev->name);
> -			spin_lock(&sp->lock);
> -			/* Restart the receiver.
> -			   I'm not sure if it's always right to restart the receiver
> -			   here but I don't know another way to prevent receiver hangs.
> -			   1999/12/25 SAW */
> -			outl(sp->rx_ring_dma[sp->cur_rx % RX_RING_SIZE],
> -				 ioaddr + SCBPointer);
> -			outb(RxStart, ioaddr + SCBCmd);
> -			sp->rx_ring_state &= ~RrNoResources;
> -			spin_unlock(&sp->lock);
> +		spin_lock(&sp->lock);
> +		/*
> +		 * The chip may have suspended reception for various reasons.
> +		 * Check for that, and re-prime it should this be the case.
> +		 */
> +		switch ((status >> 2) & 0xf) {
> +		case 0: /* Idle */
> +			break;
> +		case 1:	/* Suspended */
> +		case 2:	/* No resources (RxFDs) */
> +		case 9:	/* Suspended with no more RBDs */
> +		case 10: /* No resources due to no RBDs */
> +		case 12: /* Ready with no RBDs */
> +			speedo_rx_soft_reset(dev);
> +			break;
> +		case 3:  case 5:  case 6:  case 7:  case 8:
> +		case 11:  case 13:  case 14:  case 15:
> +			/* these are all reserved values */
> +			break;
>  		}
>  
>  		/* User interrupt, Command/Tx unit interrupt or CU not active. */
>  		if (status & 0xA400) {
> -			spin_lock(&sp->lock);
>  			speedo_tx_buffer_gc(dev);
>  			if (sp->tx_full
>  				&& (int)(sp->cur_tx - sp->dirty_tx) < TX_QUEUE_UNFULL) {
> @@ -1583,8 +1629,8 @@
>  				sp->tx_full = 0;
>  				netif_wake_queue(dev); /* Attention: under a spinlock.  --SAW */
>  			}
> -			spin_unlock(&sp->lock);
>  		}
> +		spin_unlock(&sp->lock);
>  
>  		if (--boguscnt < 0) {
>  			printk(KERN_ERR "%s: Too much work at interrupt, status=0x%4.4x.\n",
> @@ -1702,6 +1748,7 @@
>  	int entry = sp->cur_rx % RX_RING_SIZE;
>  	int rx_work_limit = sp->dirty_rx + RX_RING_SIZE - sp->cur_rx;
>  	int alloc_ok = 1;
> +	int npkts = 0;
>  
>  	if (speedo_debug > 4)
>  		printk(KERN_DEBUG " In speedo_rx().\n");
> @@ -1768,6 +1815,7 @@
>  				memcpy(skb_put(skb, pkt_len), sp->rx_skbuff[entry]->tail,
>  					   pkt_len);
>  #endif
> +				npkts++;
>  			} else {
>  				/* Pass up the already-filled skbuff. */
>  				skb = sp->rx_skbuff[entry];
> @@ -1778,6 +1826,7 @@
>  				}
>  				sp->rx_skbuff[entry] = NULL;
>  				skb_put(skb, pkt_len);
> +				npkts++;
>  				sp->rx_ringp[entry] = NULL;
>  				pci_unmap_single(sp->pdev, sp->rx_ring_dma[entry],
>  						PKT_BUF_SZ + sizeof(struct RxFD), PCI_DMA_FROMDEVICE);
> @@ -1798,7 +1847,8 @@
>  	/* Try hard to refill the recently taken buffers. */
>  	speedo_refill_rx_buffers(dev, 1);
>  
> -	sp->last_rx_time = jiffies;
> +	if (npkts)
> +		sp->last_rx_time = jiffies;
>  
>  	return 0;
>  }
-- ------------------------------- Edward Muller Director of IS973-715-0230 (cell) 212-487-9064 x115 (NYC)
http://www.learningpatterns.com -------------------------------
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/