Skip to contentSkip to conversation

via-rhine.c

path H.Rosmanith (Kernel Mailing List) 1 participant 1 message Aug 28, 2002 1 message not in the archive

lore
Share & tools
lore

A message that is not in the archive (sent off-list or not yet received): [email protected]

#1 lore raw

hello list,

this patch is agains 1.15 of via-rhine.c
it isn't supposed to be a fix, but a workaround. if you have any better idea why the error is occuring, you are welcome.

regards,
h.rosmanith

via-rhine.c renamed from via-rhine.c.p9-debug +17 -1
@@ -100,6 +100,15 @@
 	- allow selecting backoff algorithm (module parameter)
 	- cosmetic cleanups, remove 3 unused members of struct netdev_private
 
+	preliminary: (Herbert Rosmanith):
+	- for some yet unknown reason (which seems to be collision-related),
+	 TX DMA is off in via_rhine_interrupt in the ChipCmd register. this
+	 leads to an entry in the ringbuffer which is never processed and
+	 therefore blocks the ringbuffer. the hack provided sets the TxRingPtr
+	 in the chip to the entry blocking the ringbuffer, marking it for
+	 being processed again. this error seems to happen only with the VT6103.
+
 */
 
 #define DRV_NAME	"via-rhine"
@@ -474,6 +483,8 @@
 
 #define MAX_MII_CNT	4
 struct netdev_private {
+	// XXX hack hack hack
+	int intr_cmd;
 	/* Descriptor rings */
 	struct rx_desc *rx_ring;
 	struct tx_desc *tx_ring;
@@ -1294,11 +1305,13 @@
 static void via_rhine_interrupt(int irq, void *dev_instance, struct pt_regs *rgs)
 {
 	struct net_device *dev = dev_instance;
+	struct netdev_private *np=dev->priv;
 	long ioaddr;
 	u32 intr_status;
 	int boguscnt = max_interrupt_work;
 
 	ioaddr = dev->base_addr;
+	np->intr_cmd=readw(ioaddr+ChipCmd); // needed later in via_rhine_tx
 	
 	while ((intr_status = readw(ioaddr + IntrStatus))) {
 		/* Acknowledge all of the current interrupt sources ASAP. */
@@ -1350,8 +1363,12 @@
 		if (debug > 6)
 			printk(KERN_DEBUG " Tx scavenge %d status %8.8x.\n",
 				   entry, txstatus);
-		if (txstatus & DescOwn)
+		if (txstatus & DescOwn) {
+			if ((np->intr_cmd&0x0010)==0) // Gack! DMA is off
+				writel(np->tx_ring_dma + entry * sizeof(struct tx_desc),
+					dev->base_addr+TxRingPtr);
 			break;
+		}
 		if (txstatus & 0x8000) {
 			if (debug > 1)
 				printk(KERN_DEBUG "%s: Transmit error, Tx status %8.8x.\n",