From: Karsten Keil - 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 */ _