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) { |