From: Karsten Keil <kkeil@suse.de>

- SMP in act2000 and pcbit driver

- remove check_region in act2000

- mark hysdn, isdnloop and divert as BROKEN_ON_SMP



---

 25-akpm/drivers/isdn/act2000/act2000.h     |   50 ++++++++++++++-------------
 25-akpm/drivers/isdn/act2000/act2000_isa.c |   23 +++++-------
 25-akpm/drivers/isdn/act2000/capi.c        |   10 ++---
 25-akpm/drivers/isdn/act2000/capi.h        |    5 +-
 25-akpm/drivers/isdn/act2000/module.c      |   52 +++++++++++++----------------
 25-akpm/drivers/isdn/hysdn/Kconfig         |    2 -
 25-akpm/drivers/isdn/i4l/Kconfig           |    3 +
 25-akpm/drivers/isdn/pcbit/drv.c           |    1 
 25-akpm/drivers/isdn/pcbit/edss1.c         |    8 +---
 25-akpm/drivers/isdn/pcbit/layer2.c        |   43 ++++++++---------------
 25-akpm/drivers/isdn/pcbit/pcbit.h         |    2 -
 11 files changed, 89 insertions(+), 110 deletions(-)

diff -puN drivers/isdn/act2000/act2000.h~i4l-fixups drivers/isdn/act2000/act2000.h
--- 25/drivers/isdn/act2000/act2000.h~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/act2000/act2000.h	Tue Feb 10 13:09:53 2004
@@ -147,34 +147,36 @@ typedef union irq_data {
  * Per card driver data
  */
 typedef struct act2000_card {
-        unsigned short port;             /* Base-port-address                */
-        unsigned short irq;              /* Interrupt                        */
-        u_char ptype;                    /* Protocol type (1TR6 or Euro)     */
-        u_char bus;                      /* Cardtype (ISA, MCA, PCMCIA)      */
-        struct act2000_card *next;	 /* Pointer to next device struct    */
-        int myid;                        /* Driver-Nr. assigned by linklevel */
-        unsigned long flags;             /* Statusflags                      */
-        unsigned long ilock;             /* Semaphores for IRQ-Routines      */
-	struct sk_buff_head rcvq;        /* Receive-Message queue            */
-	struct sk_buff_head sndq;        /* Send-Message queue               */
-	struct sk_buff_head ackq;        /* Data-Ack-Message queue           */
-	u_char *ack_msg;                 /* Ptr to User Data in User skb     */
-	__u16 need_b3ack;                /* Flag: Need ACK for current skb   */
-	struct sk_buff *sbuf;            /* skb which is currently sent      */
-	struct timer_list ptimer;        /* Poll timer                       */
-	struct work_struct snd_tq;         /* Task struct for xmit bh          */
-	struct work_struct rcv_tq;         /* Task struct for rcv bh           */
-	struct work_struct poll_tq;        /* Task struct for polled rcv bh    */
+	unsigned short port;		/* Base-port-address                */
+	unsigned short irq;		/* Interrupt                        */
+	u_char ptype;			/* Protocol type (1TR6 or Euro)     */
+	u_char bus;			/* Cardtype (ISA, MCA, PCMCIA)      */
+	struct act2000_card *next;	/* Pointer to next device struct    */
+	spinlock_t lock;		/* protect critical operations      */
+	int myid;			/* Driver-Nr. assigned by linklevel */
+	unsigned long flags;		/* Statusflags                      */
+	unsigned long ilock;		/* Semaphores for IRQ-Routines      */
+	struct sk_buff_head rcvq;	/* Receive-Message queue            */
+	struct sk_buff_head sndq;	/* Send-Message queue               */
+	struct sk_buff_head ackq;	/* Data-Ack-Message queue           */
+	u_char *ack_msg;		/* Ptr to User Data in User skb     */
+	__u16 need_b3ack;		/* Flag: Need ACK for current skb   */
+	struct sk_buff *sbuf;		/* skb which is currently sent      */
+	struct timer_list ptimer;	/* Poll timer                       */
+	struct work_struct snd_tq;	/* Task struct for xmit bh          */
+	struct work_struct rcv_tq;	/* Task struct for rcv bh           */
+	struct work_struct poll_tq;	/* Task struct for polled rcv bh    */
 	msn_entry *msn_list;
-	unsigned short msgnum;           /* Message number fur sending       */
-	act2000_chan bch[ACT2000_BCH];   /* B-Channel status/control         */
-	char   status_buf[256];          /* Buffer for status messages       */
+	unsigned short msgnum;		/* Message number for sending       */
+	spinlock_t mnlock;		/* lock for msgnum                  */
+	act2000_chan bch[ACT2000_BCH];	/* B-Channel status/control         */
+	char   status_buf[256];		/* Buffer for status messages       */
 	char   *status_buf_read;
 	char   *status_buf_write;
 	char   *status_buf_end;
-	irq_data idat;                   /* Data used for IRQ handler        */
-        isdn_if interface;               /* Interface to upper layer         */
-        char regname[35];                /* Name used for request_region     */
+	irq_data idat;			/* Data used for IRQ handler        */
+	isdn_if interface;		/* Interface to upper layer         */
+	char regname[35];		/* Name used for request_region     */
 } act2000_card;
 
 extern __inline__ void act2000_schedule_tx(act2000_card *card)
diff -puN drivers/isdn/act2000/act2000_isa.c~i4l-fixups drivers/isdn/act2000/act2000_isa.c
--- 25/drivers/isdn/act2000/act2000_isa.c~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/act2000/act2000_isa.c	Tue Feb 10 13:09:53 2004
@@ -21,10 +21,8 @@ static act2000_card *irq2card_map[16];
 static void
 act2000_isa_delay(long t)
 {
-        sti();
         set_current_state(TASK_INTERRUPTIBLE);
         schedule_timeout(t);
-        sti();
 }
 
 /*
@@ -64,8 +62,10 @@ act2000_isa_detect(unsigned short portba
 {
         int ret = 0;
 
-        if (!check_region(portbase, ISA_REGION))
+	if (request_region(portbase, ACT2000_PORTLEN, "act2000isa")) {
                 ret = act2000_isa_reset(portbase);
+		release_region(portbase, ISA_REGION);
+	}
         return ret;
 }
 
@@ -177,14 +177,13 @@ act2000_isa_config_port(act2000_card * c
                 release_region(card->port, ISA_REGION);
                 card->flags &= ~ACT2000_FLAGS_PVALID;
         }
-        if (!check_region(portbase, ISA_REGION)) {
-                if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
-			return -EIO;
+	if (request_region(portbase, ACT2000_PORTLEN, card->regname) == NULL)
+		return -EBUSY;
+	else {
                 card->port = portbase;
                 card->flags |= ACT2000_FLAGS_PVALID;
                 return 0;
         }
-        return -EBUSY;
 }
 
 /*
@@ -195,8 +194,7 @@ act2000_isa_release(act2000_card * card)
 {
         unsigned long flags;
 
-        save_flags(flags);
-        cli();
+        spin_lock_irqsave(&card->lock, flags);
         if (card->flags & ACT2000_FLAGS_IVALID) {
                 free_irq(card->irq, NULL);
                 irq2card_map[card->irq] = NULL;
@@ -205,7 +203,7 @@ act2000_isa_release(act2000_card * card)
         if (card->flags & ACT2000_FLAGS_PVALID)
                 release_region(card->port, ISA_REGION);
         card->flags &= ~ACT2000_FLAGS_PVALID;
-        restore_flags(flags);
+        spin_unlock_irqrestore(&card->lock, flags);
 }
 
 static int
@@ -316,8 +314,7 @@ act2000_isa_send(act2000_card * card)
         if (test_and_set_bit(ACT2000_LOCK_TX, (void *) &card->ilock) != 0)
 		return;
 	while (1) {
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&card->lock, flags);
 		if (!(card->sbuf)) {
 			if ((card->sbuf = skb_dequeue(&card->sndq))) {
 				card->ack_msg = card->sbuf->data;
@@ -330,7 +327,7 @@ act2000_isa_send(act2000_card * card)
 				}
 			}
 		}
-		restore_flags(flags);
+		spin_unlock_irqrestore(&card->lock, flags);
 		if (!(card->sbuf)) {
 			/* No more data to send */
 			test_and_clear_bit(ACT2000_LOCK_TX, (void *) &card->ilock);
diff -puN drivers/isdn/act2000/capi.c~i4l-fixups drivers/isdn/act2000/capi.c
--- 25/drivers/isdn/act2000/capi.c~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/act2000/capi.c	Tue Feb 10 13:09:53 2004
@@ -591,10 +591,9 @@ handle_ack(act2000_card *card, act2000_c
 	struct actcapi_msg *m;
 	int ret = 0;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	skb = skb_peek(&card->ackq);
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
         if (!skb) {
 		printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
 		return 0;
@@ -614,10 +613,9 @@ handle_ack(act2000_card *card, act2000_c
 				chan->queued = 0;
                         return ret;
                 }
-		save_flags(flags);
-		cli();
+                spin_lock_irqsave(&card->lock, flags);
                 tmp = skb_peek((struct sk_buff_head *)tmp);
-		restore_flags(flags);
+                spin_unlock_irqrestore(&card->lock, flags);
                 if ((tmp == skb) || (tmp == NULL)) {
 			/* reached end of queue */
 			printk(KERN_WARNING "act2000: handle_ack nothing found!\n");
diff -puN drivers/isdn/act2000/capi.h~i4l-fixups drivers/isdn/act2000/capi.h
--- 25/drivers/isdn/act2000/capi.h~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/act2000/capi.h	Tue Feb 10 13:09:53 2004
@@ -336,12 +336,11 @@ actcapi_nextsmsg(act2000_card *card)
 	unsigned long flags;
 	unsigned short n;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->mnlock, flags);
 	n = card->msgnum;
 	card->msgnum++;
 	card->msgnum &= 0x7fff;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->mnlock, flags);
 	return n;
 }
 #define DEBUG_MSG
diff -puN drivers/isdn/act2000/module.c~i4l-fixups drivers/isdn/act2000/module.c
--- 25/drivers/isdn/act2000/module.c~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/act2000/module.c	Tue Feb 10 13:09:53 2004
@@ -62,19 +62,18 @@ find_channel(act2000_card *card, int cha
 static void
 act2000_clear_msn(act2000_card *card)
 {
-        struct msn_entry *p = card->msn_list;
-        struct msn_entry *q;
+	struct msn_entry *p = card->msn_list;
+	struct msn_entry *q;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
-        card->msn_list = NULL;
-	restore_flags(flags);
-        while (p) {
-                q  = p->next;
-                kfree(p);
-                p = q;
-        }
+	spin_lock_irqsave(&card->lock, flags);
+	card->msn_list = NULL;
+	spin_unlock_irqrestore(&card->lock, flags);
+	while (p) {
+		q  = p->next;
+		kfree(p);
+		p = q;
+	}
 }
 
 /*
@@ -143,13 +142,12 @@ act2000_set_msn(act2000_card *card, char
 		/* Delete a single MSN */
 		while (p) {
 			if (p->eaz == eazmsn[0]) {
-				save_flags(flags);
-				cli();
+				spin_lock_irqsave(&card->lock, flags);
 				if (q)
 					q->next = p->next;
 				else
 					card->msn_list = p->next;
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->lock, flags);
 				kfree(p);
 				printk(KERN_DEBUG
 				       "Mapping for EAZ %c deleted\n",
@@ -165,10 +163,9 @@ act2000_set_msn(act2000_card *card, char
 	while (p) {
 		/* Found in list, replace MSN */
 		if (p->eaz == eazmsn[0]) {
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&card->lock, flags);
 			strcpy(p->msn, &eazmsn[1]);
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->lock, flags);
 			printk(KERN_DEBUG
 			       "Mapping for EAZ %c changed to %s\n",
 			       eazmsn[0],
@@ -184,10 +181,9 @@ act2000_set_msn(act2000_card *card, char
 	p->eaz = eazmsn[0];
 	strcpy(p->msn, &eazmsn[1]);
 	p->next = card->msn_list;
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&card->lock, flags);
 	card->msn_list = p;
-	restore_flags(flags);
+	spin_unlock_irqrestore(&card->lock, flags);
 	printk(KERN_DEBUG
 	       "Mapping %c -> %s added\n",
 	       eazmsn[0],
@@ -232,10 +228,9 @@ act2000_poll(unsigned long data)
 	unsigned long flags;
 
 	act2000_receive(card);
-        save_flags(flags);
-        cli();
-        mod_timer(&card->ptimer, jiffies+3);
-        restore_flags(flags);
+	spin_lock_irqsave(&card->lock, flags);
+	mod_timer(&card->ptimer, jiffies+3);
+	spin_unlock_irqrestore(&card->lock, flags);
 }
 
 static int
@@ -311,10 +306,9 @@ act2000_command(act2000_card * card, isd
 				return -ENODEV;
 			if (!(chan = find_channel(card, c->arg & 0x0f)))
 				break;
-			save_flags(flags);
-			cli();
+			spin_lock_irqsave(&card->lock, flags);
 			if (chan->fsm_state != ACT2000_STATE_NULL) {
-				restore_flags(flags);
+				spin_unlock_irqrestore(&card->lock, flags);
 				printk(KERN_WARNING "Dial on channel with state %d\n",
 					chan->fsm_state);
 				return -EBUSY;
@@ -325,7 +319,7 @@ act2000_command(act2000_card * card, isd
 				tmp[0] = c->parm.setup.eazmsn[0];
 			chan->fsm_state = ACT2000_STATE_OCALL;
 			chan->callref = 0xffff;
-			restore_flags(flags);
+			spin_unlock_irqrestore(&card->lock, flags);
 			ret = actcapi_connect_req(card, chan, c->parm.setup.phone,
 						  tmp[0], c->parm.setup.si1,
 						  c->parm.setup.si2);
@@ -580,6 +574,8 @@ act2000_alloccard(int bus, int port, int
                 return;
         }
         memset((char *) card, 0, sizeof(act2000_card));
+        spin_lock_init(&card->lock);
+        spin_lock_init(&card->mnlock);
 	skb_queue_head_init(&card->sndq);
 	skb_queue_head_init(&card->rcvq);
 	skb_queue_head_init(&card->ackq);
diff -puN drivers/isdn/hysdn/Kconfig~i4l-fixups drivers/isdn/hysdn/Kconfig
--- 25/drivers/isdn/hysdn/Kconfig~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/hysdn/Kconfig	Tue Feb 10 13:09:53 2004
@@ -3,7 +3,7 @@
 #
 config HYSDN
 	tristate "Hypercope HYSDN cards (Champ, Ergo, Metro) support (module only)"
-	depends on m && PROC_FS
+	depends on m && PROC_FS && BROKEN_ON_SMP
 	help
 	  Say Y here if you have one of Hypercope's active PCI ISDN cards
 	  Champ, Ergo and Metro. You will then get a module called hysdn.
diff -puN drivers/isdn/i4l/Kconfig~i4l-fixups drivers/isdn/i4l/Kconfig
--- 25/drivers/isdn/i4l/Kconfig~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/i4l/Kconfig	Tue Feb 10 13:09:53 2004
@@ -78,6 +78,7 @@ menu "ISDN feature submodules"
 
 config ISDN_DRV_LOOP
 	tristate "isdnloop support"
+	depends on BROKEN_ON_SMP
 	help
 	  This driver provides a virtual ISDN card. Its primary purpose is
 	  testing of linklevel features or configuration without getting
@@ -87,7 +88,7 @@ config ISDN_DRV_LOOP
 
 config ISDN_DIVERSION
 	tristate "Support isdn diversion services"
-	depends on BROKEN
+	depends on BROKEN && BROKEN_ON_SMP
 	help
 	  This option allows you to use some supplementary diversion
 	  services in conjunction with the HiSax driver on an EURO/DSS1
diff -puN drivers/isdn/pcbit/drv.c~i4l-fixups drivers/isdn/pcbit/drv.c
--- 25/drivers/isdn/pcbit/drv.c~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/pcbit/drv.c	Tue Feb 10 13:09:53 2004
@@ -84,6 +84,7 @@ int pcbit_init_dev(int board, int mem_ba
 	dev_pcbit[board] = dev;
 	memset(dev, 0, sizeof(struct pcbit_dev));
 	init_waitqueue_head(&dev->set_running_wq);
+	spin_lock_init(&dev->lock);
 
 	if (mem_base >= 0xA0000 && mem_base <= 0xFFFFF ) {
 		dev->ph_mem = mem_base;
diff -puN drivers/isdn/pcbit/edss1.c~i4l-fixups drivers/isdn/pcbit/edss1.c
--- 25/drivers/isdn/pcbit/edss1.c~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/pcbit/edss1.c	Tue Feb 10 13:09:53 2004
@@ -278,9 +278,7 @@ void pcbit_fsm_event(struct pcbit_dev *d
 	struct fsm_timer_entry *tentry;
 	unsigned long flags;
 
-	save_flags(flags);
-	cli();
-
+	spin_lock_irqsave(&dev->lock, flags);
 
         for (action = fsm_table; action->init != 0xff; action++)
                 if (action->init == chan->fsm_state && action->event == event)
@@ -288,9 +286,9 @@ void pcbit_fsm_event(struct pcbit_dev *d
   
 	if (action->init == 0xff) {
 		
+		spin_unlock_irqrestore(&dev->lock, flags);
 		printk(KERN_DEBUG "fsm error: event %x on state %x\n", 
                        event, chan->fsm_state);
-		restore_flags(flags);
 		return;
 	}
 
@@ -315,7 +313,7 @@ void pcbit_fsm_event(struct pcbit_dev *d
                 add_timer(&chan->fsm_timer);
         }
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&dev->lock, flags);
 
 	if (action->callb)
 		action->callb(dev, chan, data);
diff -puN drivers/isdn/pcbit/layer2.c~i4l-fixups drivers/isdn/pcbit/layer2.c
--- 25/drivers/isdn/pcbit/layer2.c~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/pcbit/layer2.c	Tue Feb 10 13:09:53 2004
@@ -121,18 +121,17 @@ pcbit_l2_write(struct pcbit_dev *dev, ul
 
 	frame->next = NULL;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 
 	if (dev->write_queue == NULL) {
 		dev->write_queue = frame;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 		pcbit_transmit(dev);
 	} else {
 		for (ptr = dev->write_queue; ptr->next; ptr = ptr->next);
 		ptr->next = frame;
 
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 	}
 	return 0;
 }
@@ -174,15 +173,14 @@ pcbit_transmit(struct pcbit_dev *dev)
 
 	unacked = (dev->send_seq + (8 - dev->unack_seq)) & 0x07;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 
 	if (dev->free > 16 && dev->write_queue && unacked < 7) {
 
 		if (!dev->w_busy)
 			dev->w_busy = 1;
 		else {
-			restore_flags(flags);
+			spin_unlock_irqrestore(&dev->lock, flags);
 			return;
 		}
 
@@ -190,7 +188,7 @@ pcbit_transmit(struct pcbit_dev *dev)
 		frame = dev->write_queue;
 		free = dev->free;
 
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 
 		if (frame->copied == 0) {
 
@@ -271,9 +269,7 @@ pcbit_transmit(struct pcbit_dev *dev)
 		dev->free -= flen;
 		pcbit_tx_update(dev, flen);
 
-		save_flags(flags);
-		cli();
-
+		spin_lock_irqsave(&dev->lock, flags);
 
 		if (frame->skb == NULL || frame->copied == frame->skb->len) {
 
@@ -286,9 +282,9 @@ pcbit_transmit(struct pcbit_dev *dev)
 			kfree(frame);
 		}
 		dev->w_busy = 0;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 	} else {
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 #ifdef DEBUG
 		printk(KERN_DEBUG "unacked %d free %d write_queue %s\n",
 		     unacked, dev->free, dev->write_queue ? "not empty" :
@@ -309,12 +305,11 @@ pcbit_deliver(void *data)
 	unsigned long flags, msg;
 	struct pcbit_dev *dev = (struct pcbit_dev *) data;
 
-	save_flags(flags);
-	cli();
+	spin_lock_irqsave(&dev->lock, flags);
 
 	while ((frame = dev->read_queue)) {
 		dev->read_queue = frame->next;
-		restore_flags(flags);
+		spin_unlock_irqrestore(&dev->lock, flags);
 
 		SET_MSG_CPU(msg, 0);
 		SET_MSG_PROC(msg, 0);
@@ -331,11 +326,10 @@ pcbit_deliver(void *data)
 
 		kfree(frame);
 
-		save_flags(flags);
-		cli();
+		spin_lock_irqsave(&dev->lock, flags);
 	}
 
-	restore_flags(flags);
+	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 /*
@@ -460,12 +454,9 @@ pcbit_receive(struct pcbit_dev *dev)
 	memcpy_frompcbit(dev, skb_put(frame->skb, tt), tt);
 
 	frame->copied += tt;
-
+	spin_lock_irqsave(&dev->lock, flags);
 	if (frame->copied == frame->hdr_len + frame->dt_len) {
 
-		save_flags(flags);
-		cli();
-
 		if (type1) {
 			dev->read_frame = NULL;
 		}
@@ -476,14 +467,10 @@ pcbit_receive(struct pcbit_dev *dev)
 		} else
 			dev->read_queue = frame;
 
-		restore_flags(flags);
-
 	} else {
-		save_flags(flags);
-		cli();
 		dev->read_frame = frame;
-		restore_flags(flags);
 	}
+	spin_unlock_irqrestore(&dev->lock, flags);
 }
 
 /*
diff -puN drivers/isdn/pcbit/pcbit.h~i4l-fixups drivers/isdn/pcbit/pcbit.h
--- 25/drivers/isdn/pcbit/pcbit.h~i4l-fixups	Tue Feb 10 13:09:53 2004
+++ 25-akpm/drivers/isdn/pcbit/pcbit.h	Tue Feb 10 13:09:53 2004
@@ -51,7 +51,7 @@ struct pcbit_dev {
 	unsigned int id;
 	unsigned int interrupt;			/* set during interrupt 
 						   processing */
-	
+	spinlock_t lock;
 	/* isdn4linux */
 
 	struct msn_entry * msn_list;		/* ISDN address list */

_