|
From: Kenn H. <ke...@us...> - 2002-08-10 18:20:04
|
Update of /cvsroot/linux-vax/kernel-2.5/drivers/vax/net
In directory usw-pr-cvs1:/tmp/cvs-serv21005
Modified Files:
delqa.c
Log Message:
Add spin lock (should now be safe for SMP/pre-emtive kernel). Split
DELQA reset out from delqa_open into a separate function.
Index: delqa.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.5/drivers/vax/net/delqa.c,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- delqa.c 18 Jul 2002 23:39:33 -0000 1.1
+++ delqa.c 10 Aug 2002 18:20:01 -0000 1.2
@@ -14,8 +14,14 @@
TODO: Allow multiple DELQAs at different base addresses.
- TODO: SMP awareness (is this just a spinlock in delqa_private?)
+ TODO: Reset BELQA on q-bus memory access error (is this the right
+ thing to do?).
+ TODO: Implement delqa_tx_timeout().
+
+ TODO: Handle multicast addresses and PROMISC flag in format_setup_frame().
+
+ TODO: Implement delqa_close().
*/
@@ -57,8 +63,6 @@
struct delqa_bufdesc txdesc[TXDESCS+1];
};
-/* FIXME: add a spinlock to this structure */
-
struct delqa_private {
unsigned char *base;
unsigned int qbus_vector;
@@ -74,6 +78,7 @@
unsigned int next_tx_pending; /* Only written by init and interrupt code */
unsigned int next_rx;
unsigned int last_tdr; /* Last Time Domain Reflectometer value on TX */
+ spinlock_t lock;
};
#define LOWORD(x) ((int)(x) & 0xffff)
@@ -409,6 +414,8 @@
unsigned int csr;
unsigned int newcsr;
+ spin_lock(&priv->lock);
+
csr = read_reg(priv, DELQA_CSR);
#if DELQA_DEBUG_CSR
@@ -445,10 +452,11 @@
this point. */
write_reg(priv, DELQA_CSR, newcsr);
-
#if DELQA_DEBUG_CSR
dump_csr("delqa_interrupt exit", dev);
#endif
+
+ spin_unlock(&priv->lock);
}
static int delqa_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -459,6 +467,7 @@
unsigned int i;
unsigned int busaddr;
unsigned int csr;
+ unsigned int flags;
if (skb->len < ETH_ZLEN) {
struct sk_buff *new_skb;
@@ -480,12 +489,16 @@
skb = new_skb;
}
+ spin_lock_irqsave(&priv->lock, flags);
+
i = priv->next_tx_free;
priv->next_tx_free++;
if (priv->next_tx_free == TXDESCS) {
priv->next_tx_free = 0;
}
+ spin_unlock_irqrestore(&priv->lock, flags);
+
desc = priv->descs->txdesc + i;
/* FIXME: These mapping registers MUST be allocated at init time
@@ -528,6 +541,8 @@
dump_descs(dev);
#endif
+ spin_lock_irqsave(&priv->lock, flags);
+
csr = read_reg(priv, DELQA_CSR);
if (csr & DELQA_CSR_XL_INVALID) {
@@ -546,6 +561,8 @@
netif_stop_queue(dev);
}
+ spin_unlock_irqrestore(&priv->lock, flags);
+
return 0;
}
@@ -607,6 +624,8 @@
/* Point the first available TX descriptor at the setup
frame and enable the transmitter */
+ spin_lock(&priv->lock);
+
i = priv->next_tx_free;
priv->next_tx_free++;
@@ -614,6 +633,8 @@
priv->next_tx_free = 0;
}
+ spin_unlock(&priv->lock);
+
desc = priv->descs->txdesc + i;
priv->tx_map[i] = qbus_alloc_mapregs(priv->setup_frame, priv->setup_frame_len);
@@ -635,6 +656,8 @@
dump_descs(dev);
#endif
+ spin_lock(&priv->lock);
+
csr = read_reg(priv, DELQA_CSR);
if (csr & DELQA_CSR_XL_INVALID) {
@@ -646,23 +669,15 @@
write_reg(priv, DELQA_XMTH, HIWORD(busaddr));
}
+ spin_unlock(&priv->lock);
}
-static int delqa_open(struct net_device *dev)
+static void delqa_reset(struct net_device *dev)
{
struct delqa_private *priv = (struct delqa_private *)dev->priv;
- struct delqa_bufdesc *desc;
unsigned int csr;
- int i;
- unsigned int busaddr;
-
- if (qbus_request_irq(priv->qbus_vector, delqa_interrupt, 0, "delqa", dev)) {
- printk("delqa_open: cannot get qbus irq %d\n", priv->qbus_vector);
- return -EAGAIN;
- }
- /* Reset the hardware */
- printk("Resetting DELQA... ");
+ printk("%s: resetting DELQA... ", dev->name);
write_reg(priv, DELQA_CSR, DELQA_CSR_RESET);
udelay(1000);
@@ -672,6 +687,25 @@
write_reg(priv, DELQA_VECTOR, priv->qbus_vector);
printk("done\n");
+}
+
+static int delqa_open(struct net_device *dev)
+{
+ struct delqa_private *priv = (struct delqa_private *)dev->priv;
+ struct delqa_bufdesc *desc;
+ int i;
+ unsigned int busaddr;
+
+ /* Reset the hardware before hooking the interrupt vector
+ to guarantee that we won't get any interrupts until we
+ enable them. */
+
+ delqa_reset(dev);
+
+ if (qbus_request_irq(priv->qbus_vector, delqa_interrupt, 0, "delqa", dev)) {
+ printk("delqa_open: cannot get qbus irq %d\n", priv->qbus_vector);
+ return -EAGAIN;
+ }
/* Mark the transmit descriptors as not yet owned by
the DELQA (and also not VALID). */
@@ -836,6 +870,8 @@
memset(dev->priv, 0, sizeof(struct delqa_private));
priv = (struct delqa_private *) dev->priv;
+
+ spin_lock_init(&priv->lock);
priv->base = ioremap(DELQA_BASE, 16);
if (priv->base == NULL) {
|