summaryrefslogtreecommitdiffstats
path: root/drivers/net/sonic.c
diff options
context:
space:
mode:
authorThomas Bogendoerfer <tsbogend@alpha.franken.de>1997-08-07 21:40:27 +0000
committerThomas Bogendoerfer <tsbogend@alpha.franken.de>1997-08-07 21:40:27 +0000
commit51be8aeb4460be53526d2e29153adab71b47c3c6 (patch)
tree1119e6204df4ce06df99f91a3fcf19002e0ffd7a /drivers/net/sonic.c
parente2819e52a162873ff5061de81bb749831bdb5de9 (diff)
fixed silly typo
fixed race in packet transmission changed some debug messages bumped up version number to 0.50
Diffstat (limited to 'drivers/net/sonic.c')
-rw-r--r--drivers/net/sonic.c55
1 files changed, 37 insertions, 18 deletions
diff --git a/drivers/net/sonic.c b/drivers/net/sonic.c
index a52b94a91..4a6362c1d 100644
--- a/drivers/net/sonic.c
+++ b/drivers/net/sonic.c
@@ -14,7 +14,7 @@
*/
static const char *version =
- "sonic.c:v0.10 6.7.96 tsbogend@alpha.franken.de\n";
+ "sonic.c:v0.50 7.8.97 tsbogend@alpha.franken.de\n";
/*
* Sources: Olivetti M700-10 Risc Personal Computer hardware handbook,
@@ -435,16 +435,21 @@ static int sonic_send_packet(struct sk_buff *skb, struct device *dev)
lp->tda[entry].tx_frag_ptr_h = laddr >> 16;
lp->tda[entry].tx_frag_size = length;
- /* if there are already packets queued, allow sending serveral packets at once */
- if (lp->dirty_tx != lp->cur_tx)
- lp->tda[(lp->cur_tx-1) % SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
-
- lp->cur_tx++;
+ /* if there are already packets queued, allow sending several packets at once */
+ if (lp->dirty_tx != lp->cur_tx++)
+ lp->tda[(lp->cur_tx-2) & SONIC_TDS_MASK].link &= ~SONIC_END_OF_LINKS;
if (sonic_debug > 2)
- printk("sonic_send_packet: issueing Tx command\n");
-
- SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);
+ printk("sonic_send_packet: issueing Tx command, cur_tx %d, ctda %x\n",
+ lp->cur_tx,SONIC_READ(SONIC_CTDA));
+
+ /*
+ * trigger a new transmission only when there are no outstanding transmits,
+ * otherwise we may trigger a transmission without a valid descriptor which
+ * messes up our dirty_tx
+ */
+ if (lp->dirty_tx == lp->cur_tx-1 && !(SONIC_READ(SONIC_CMD) & SONIC_CR_TXP))
+ SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);
dev->trans_start = jiffies;
@@ -477,7 +482,6 @@ sonic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
lp = (struct sonic_local *)dev->priv;
status = SONIC_READ(SONIC_ISR);
- SONIC_WRITE(SONIC_ISR,0x7fff); /* clear all bits */
if (sonic_debug > 2)
printk("sonic_interrupt: ISR=%x\n",status);
@@ -488,17 +492,27 @@ sonic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
if (status & SONIC_INT_TXDN) {
int dirty_tx = lp->dirty_tx;
-
+
while (dirty_tx < lp->cur_tx) {
int entry = dirty_tx & SONIC_TDS_MASK;
int status = lp->tda[entry].tx_status;
+
+ if (sonic_debug > 2)
+ printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d, ctda %x\n",
+ status,lp->cur_tx,dirty_tx,SONIC_READ(SONIC_CTDA));
- if (sonic_debug > 3)
- printk ("sonic_interrupt: status %d, cur_tx %d, dirty_tx %d\n",
- status,lp->cur_tx,lp->dirty_tx);
-
- if (status == 0)
- break; /* It still hasn't been Txed */
+ if (status == 0) {
+ /*
+ * there is a small race, when we try to send more packets with one
+ * transmission command. To solve this race, we trigger the transmission
+ * again
+ */
+ if (sonic_debug > 1)
+ printk ("triggering lost transmission\n");
+ if (!(SONIC_READ(SONIC_CMD) & SONIC_CR_TXP))
+ SONIC_WRITE(SONIC_CMD,SONIC_CR_TXP);
+ break;
+ }
/* put back EOL and free descriptor */
lp->tda[entry].link |= SONIC_END_OF_LINKS;
@@ -548,7 +562,7 @@ sonic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
}
if (status & SONIC_INT_RBE) {
printk ("%s: receive buffer exhausted\n",dev->name);
- lp->stats.rx_dropped++;
+ lp->stats.rx_dropped++;
}
if (status & SONIC_INT_RBAE) {
printk ("%s: receive buffer area exhausted\n",dev->name);
@@ -736,6 +750,11 @@ static int sonic_init(struct device *dev)
SONIC_WRITE(SONIC_ISR,0x7fff);
SONIC_WRITE(SONIC_IMR,0);
SONIC_WRITE(SONIC_CMD,SONIC_CR_RST);
+
+ /*
+ * write data config register
+ */
+ SONIC_WRITE(SONIC_DCR, 0x2423);
/*
* clear software reset flag, disable receiver, clear and