Token Ring Patch

Paul P. Norton (pnorton@grumpy.biomed.com)
Tue, 20 Aug 1996 11:28:29 -0700


This patch fixes:

1. Most (maybe all) token-ring lockups due to the Arrg problem.

2. "Unknown command in asb 08" errors.

3. Incorrect open error code handling.

Thanks to Michael Madore, Christopher A. Smith, James Walter Martin III,
Joe Hindsley and Harald Becker for their assistance in debugging this
problem.

Please email me at pnorton@cts.com with any problems, questions or
comments regarding this patch.

Paul

---- cut here ----

--- v2.0.12/linux/drivers/net/ibmtr.c Mon May 6 02:26:08 1996
+++ linux/drivers/net/ibmtr.c Thu Aug 15 10:58:13 1996
@@ -50,6 +50,11 @@
- detecting PCMCIA Card Removal in interrupt handler. if
ISRP is FF, then a PCMCIA card has been removed

+ Changes by Paul Norton (pnorton@cts.com) :
+ - restructured the READ.LOG logic to prevent the transmit SRB
+ from being rudely overwritten before the transmit cycle is
+ complete. (August 15 1996)
+
Warnings !!!!!!!!!!!!!!
This driver is only partially sanitized for support of multiple
adapters. It will almost definitely fail if more than one
@@ -168,6 +173,7 @@
static int tok_close(struct device *dev);
static int tok_send_packet(struct sk_buff *skb, struct device *dev);
static struct enet_statistics * tok_get_stats(struct device *dev);
+void tr_readlog(struct device *dev);

static struct timer_list tr_timer={NULL,NULL,0,0L,tok_open_adapter};

@@ -331,6 +337,7 @@
memset(ti, 0, sizeof(struct tok_info));

ti->mmio= t_mmio;
+ ti->readlog_pending = 0;

dev->priv = ti; /* this seems like the logical use of the
field ... let's try some empirical tests
@@ -730,6 +737,7 @@
ti->current_skb=NULL;
}
dev->tbusy=0;
+ if (ti->readlog_pending) tr_readlog(dev);
}
}
break;
@@ -746,6 +754,7 @@
ti->current_skb=NULL;
}
dev->tbusy=0;
+ if (ti->readlog_pending) tr_readlog(dev);
}
}
break;
@@ -761,7 +770,7 @@
ti->current_skb=NULL;

open_ret_code = readb(ti->init_srb +offsetof(struct srb_open_response, ret_code));
- open_error_code = readw(ti->init_srb +offsetof(struct srb_open_response, error_code));
+ open_error_code = ntohs(readw(ti->init_srb +offsetof(struct srb_open_response, error_code)));

if (open_ret_code==7) {

@@ -774,7 +783,7 @@
DPRINTK("retrying open to adjust to ring speed\n");
else if ((open_error_code==0x2d) && ti->auto_ringspeedsave)
DPRINTK("No signal detected for Auto Speed Detection\n");
- else DPRINTK("Unrecoverable error: error code = %02X\n",
+ else DPRINTK("Unrecoverable error: error code = %04x\n",
open_error_code);

} else if (!open_ret_code) {
@@ -887,10 +896,6 @@
case REC_DATA:
case XMIT_UI_FRAME:
case XMIT_DIR_FRAME:
- if (readb(ti->asb+2)!=0xff) /* checks ret_code */
- DPRINTK("ASB error %02X in cmd %02X\n",
- (int)readb(ti->asb+2),
- (int)readb(ti->asb));
break;

default:
@@ -899,6 +904,9 @@

} /* ASB command check */

+ if (readb(ti->asb+2)!=0xff) /* checks ret_code */
+ DPRINTK("ASB error %02X in cmd %02X\n",
+ (int)readb(ti->asb+2),(int)readb(ti->asb));
writeb(~ASB_FREE_INT, ti->mmio + ACA_OFFSET + ACA_RESET + ISRP_ODD);

} /* ASB response */
@@ -938,14 +946,10 @@
DPRINTK("New ring status: %02X\n", ring_status);

if (ring_status & LOG_OVERFLOW) {
-
- writeb(DIR_READ_LOG, ti->srb);
- writeb(INT_ENABLE,
- ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
- writeb(CMD_IN_SRB,
- ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
- dev->tbusy=1; /* really srb busy... */
-
+ if (dev->tbusy)
+ ti->readlog_pending = 1;
+ else
+ tr_readlog(dev);
}
}
break;
@@ -1269,6 +1273,7 @@
dev_kfree_skb(ti->current_skb,FREE_WRITE);
ti->current_skb=NULL;
mark_bh(NET_BH);
+ if (ti->readlog_pending) tr_readlog(dev);
}

static void tr_rx(struct device *dev)
@@ -1468,7 +1473,18 @@
}

return 0;
-}
+}
+
+void tr_readlog(struct device *dev) {
+ struct tok_info *ti;
+ ti=(struct tok_info *) dev->priv;
+
+ ti->readlog_pending = 0;
+ writeb(DIR_READ_LOG, ti->srb);
+ writeb(INT_ENABLE, ti->mmio + ACA_OFFSET + ACA_SET + ISRP_EVEN);
+ writeb(CMD_IN_SRB, ti->mmio + ACA_OFFSET + ACA_SET + ISRA_ODD);
+ dev->tbusy=1; /* really srb busy... */
+}

/* tok_get_stats(): Basically a scaffold routine which will return
the address of the tr_statistics structure associated with
--- v2.0.12/linux/drivers/net/ibmtr.h Thu Apr 11 23:49:38 1996
+++ linux/drivers/net/ibmtr.h Thu Aug 15 10:06:06 1996
@@ -206,6 +206,7 @@
struct tr_statistics tr_stats;
unsigned char auto_ringspeedsave;
open_state open_status;
+ unsigned char readlog_pending;
};

/* token ring adapter commands */