[PATCH] Fix SMP support on 3c527 net driver
From: Felipe W Damasio
Date: Sat Aug 30 2003 - 22:05:57 EST
Hi Richard,
Patch against 2.6.0-test4
This is a first try to fix SMP support on the 3c527 net driver, by
removing cli/sti and replacing them with proper locking.
Since the critical section that used cli/save_flags to serialize its
access had "sleep_on" in it, I added a per-device semaphore to it, and
used this lock instead. Also, the down/up function doesn't seem to be
used in interrupt context, so I think it will work.
Compile fine, but I don't have the hardware to test it.
Please review this patch and consider applying if it looks good,
Thanks.
Felipe
--
It's most certainly GNU/Linux, not Linux. Read more at
http://www.gnu.org/gnu/why-gnu-linux.html
--- linux-2.6.0-test4/drivers/net/3c527.c Fri Aug 22 20:56:34 2003
+++ linux-2.6.0-test4-fwd/drivers/net/3c527.c Sat Aug 30 23:57:25 2003
@@ -17,8 +17,8 @@
*/
#define DRV_NAME "3c527"
-#define DRV_VERSION "0.6a"
-#define DRV_RELDATE "2001/11/17"
+#define DRV_VERSION "0.6b"
+#define DRV_RELDATE "2003/08/31"
static const char *version =
DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " Richard Proctor (rnp@xxxxxxxxxxxxx)\n";
@@ -174,6 +174,8 @@
struct mc32_ring_desc tx_ring[TX_RING_LEN]; /* Host Transmit ring */
struct mc32_ring_desc rx_ring[RX_RING_LEN]; /* Host Receive ring */
+
+ struct semaphore mc32_sem;
u16 tx_ring_tail; /* index to tx de-queue end */
u16 tx_ring_head; /* index to tx en-queue end */
@@ -615,16 +617,14 @@
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
int ioaddr = dev->base_addr;
- unsigned long flags;
int ret = 0;
/*
* Wait for a command
*/
- save_flags(flags);
- cli();
-
+ down(&lp->mc32_sem);
+
while(lp->exec_pending)
sleep_on(&lp->event);
@@ -634,7 +634,7 @@
lp->exec_pending=1;
- restore_flags(flags);
+ up(&lp->mc32_sem);
lp->exec_box->mbox=0;
lp->exec_box->mbox=cmd;
@@ -645,13 +645,12 @@
while(!(inb(ioaddr+HOST_STATUS)&HOST_STATUS_CRR));
outb(1<<6, ioaddr+HOST_CMD);
- save_flags(flags);
- cli();
+ down(&lp->mc32_sem);
while(lp->exec_pending!=2)
sleep_on(&lp->event);
lp->exec_pending=0;
- restore_flags(flags);
+ up(&lp->mc32_sem);
if(lp->exec_box->mbox&(1<<13))
ret = -1;
@@ -725,7 +724,6 @@
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
int ioaddr = dev->base_addr;
- unsigned long flags;
mc32_ready_poll(dev);
@@ -735,14 +733,13 @@
outb(HOST_CMD_SUSPND_RX, ioaddr+HOST_CMD);
mc32_ready_poll(dev);
outb(HOST_CMD_SUSPND_TX, ioaddr+HOST_CMD);
-
- save_flags(flags);
- cli();
+
+ down(&lp->mc32_sem);
while(lp->xceiver_state!=HALTED)
sleep_on(&lp->event);
- restore_flags(flags);
+ up(&lp->mc32_sem);
}
@@ -1008,6 +1005,7 @@
return -ENOBUFS;
}
+ init_MUTEX(&lp->mc32_sem);
lp->desired_state = RUNNING;
/* And finally, set the ball rolling... */
@@ -1056,18 +1054,16 @@
static int mc32_send_packet(struct sk_buff *skb, struct net_device *dev)
{
struct mc32_local *lp = (struct mc32_local *)dev->priv;
- unsigned long flags;
volatile struct skb_header *p, *np;
netif_stop_queue(dev);
- save_flags(flags);
- cli();
+ down(&lp->mc32_sem);
if(atomic_read(&lp->tx_count)==0)
{
- restore_flags(flags);
+ up(&lp->mc32_sem);
return 1;
}
@@ -1098,7 +1094,7 @@
p->control &= ~CONTROL_EOL; /* Clear EOL on p */
out:
- restore_flags(flags);
+ up(&lp->mc32_sem);
netif_wake_queue(dev);
return 0;