diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2000-07-09 02:54:55 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2000-07-09 02:54:55 +0000 |
commit | 493c987f7a352ca64fdb4dc03a21e24cbaf46f55 (patch) | |
tree | 184cddc0925e082c0500afd042f92e9f340fe890 /drivers/atm | |
parent | 2d25612a92c62b5708d6d43f38d28c6141173328 (diff) |
Merge with Linux 2.4.0-pre3-test6.
Diffstat (limited to 'drivers/atm')
-rw-r--r-- | drivers/atm/ambassador.c | 14 | ||||
-rw-r--r-- | drivers/atm/eni.c | 24 | ||||
-rw-r--r-- | drivers/atm/eni.h | 1 | ||||
-rw-r--r-- | drivers/atm/fore200e.c | 4 | ||||
-rw-r--r-- | drivers/atm/horizon.c | 3 | ||||
-rw-r--r-- | drivers/atm/idt77105.c | 10 | ||||
-rw-r--r-- | drivers/atm/nicstar.c | 218 | ||||
-rw-r--r-- | drivers/atm/nicstar.h | 17 |
8 files changed, 192 insertions, 99 deletions
diff --git a/drivers/atm/ambassador.c b/drivers/atm/ambassador.c index acf2c194c..b860253d3 100644 --- a/drivers/atm/ambassador.c +++ b/drivers/atm/ambassador.c @@ -373,16 +373,16 @@ static inline u32 rd_mem (const amb_dev * dev, size_t addr) { static inline void dump_registers (const amb_dev * dev) { #ifdef DEBUG_AMBASSADOR if (debug & DBG_REGS) { - u32 * i; + size_t i; PRINTD (DBG_REGS, "reading PLX control: "); - for (i = (u32 *) 0x00; i < (u32 *) 0x30; ++i) - rd_mem (dev, (size_t)i); + for (i = 0x00; i < 0x30; i += sizeof(u32)) + rd_mem (dev, i); PRINTD (DBG_REGS, "reading mailboxes: "); - for (i = (u32 *) 0x40; i < (u32 *) 0x60; ++i) - rd_mem (dev, (size_t)i); + for (i = 0x40; i < 0x60; i += sizeof(u32)) + rd_mem (dev, i); PRINTD (DBG_REGS, "reading doorb irqev irqen reset:"); - for (i = (u32 *) 0x60; i < (u32 *) 0x70; ++i) - rd_mem (dev, (size_t)i); + for (i = 0x60; i < 0x70; i += sizeof(u32)) + rd_mem (dev, i); } #else (void) dev; diff --git a/drivers/atm/eni.c b/drivers/atm/eni.c index 5a2ba1521..174873f72 100644 --- a/drivers/atm/eni.c +++ b/drivers/atm/eni.c @@ -1187,14 +1187,12 @@ static void poll_tx(struct atm_dev *dev) if (tx->send) while ((skb = skb_dequeue(&tx->backlog))) { res = do_tx(skb); - if (res == enq_ok) atomic_dec(&tx->backlog_len); - else { - DPRINTK("re-queuing TX PDU\n"); - skb_queue_head(&tx->backlog,skb); + if (res == enq_ok) continue; + DPRINTK("re-queuing TX PDU\n"); + skb_queue_head(&tx->backlog,skb); requeued++; - if (res == enq_jam) return; - else break; - } + if (res == enq_jam) return; + break; } } } @@ -1326,7 +1324,6 @@ static int reserve_or_set_tx(struct atm_vcc *vcc,struct atm_trafprm *txtp, tx->send = mem; tx->words = size >> 2; skb_queue_head_init(&tx->backlog); - atomic_set(&tx->backlog_len,0); for (order = 0; size > (1 << (order+10)); order++); eni_out((order << MID_SIZE_SHIFT) | ((tx->send-eni_dev->ram) >> (MID_LOC_SKIP+2)), @@ -2064,6 +2061,8 @@ static int eni_setsockopt(struct atm_vcc *vcc,int level,int optname, static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb) { + enum enq_res res; + DPRINTK(">eni_send\n"); if (!ENI_VCC(vcc)->tx) { if (vcc->pop) vcc->pop(vcc,skb); @@ -2085,8 +2084,11 @@ static int eni_send(struct atm_vcc *vcc,struct sk_buff *skb) } submitted++; ATM_SKB(skb)->vcc = vcc; + tasklet_disable(&ENI_DEV(vcc->dev)->task); + res = do_tx(skb); + tasklet_enable(&ENI_DEV(vcc->dev)->task); + if (res == enq_ok) return 0; skb_queue_tail(&ENI_VCC(vcc)->tx->backlog,skb); - atomic_inc(&ENI_VCC(vcc)->tx->backlog_len); backlogged++; tasklet_schedule(&ENI_DEV(vcc->dev)->task); return 0; @@ -2186,8 +2188,8 @@ static int eni_proc_read(struct atm_dev *dev,loff_t *pos,char *page) tx == eni_dev->ubr ? " (UBR)" : ""); } if (--left) continue; - return sprintf(page,"%10sbacklog %d bytes\n","", - atomic_read(&tx->backlog_len)); + return sprintf(page,"%10sbacklog %u packets\n","", + skb_queue_len(&tx->backlog)); } for (vcc = dev->vccs; vcc; vcc = vcc->next) { struct eni_vcc *eni_vcc = ENI_VCC(vcc); diff --git a/drivers/atm/eni.h b/drivers/atm/eni.h index 12a3e196c..e7af66bd8 100644 --- a/drivers/atm/eni.h +++ b/drivers/atm/eni.h @@ -47,7 +47,6 @@ struct eni_tx { int reserved; /* reserved peak cell rate */ int shaping; /* shaped peak cell rate */ struct sk_buff_head backlog; /* queue of waiting TX buffers */ - atomic_t backlog_len; /* length of backlog in bytes */ }; struct eni_vcc { diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 164ef4523..a8bda5927 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c @@ -2599,9 +2599,7 @@ fore200e_detect(void) printk(FORE200E "FORE Systems 200E-series driver - version " FORE200E_VERSION "\n"); -#if 0 /* XXX uncomment this to forbid module unloading */ MOD_INC_USE_COUNT; -#endif /* for each configured bus interface */ for (link = 0, bus = fore200e_bus; bus->model_name; bus++) { @@ -2628,10 +2626,8 @@ fore200e_detect(void) } } -#if 0 /* XXX uncomment this to forbid module unloading */ if (link <= 0) MOD_DEC_USE_COUNT; -#endif return link; } diff --git a/drivers/atm/horizon.c b/drivers/atm/horizon.c index dc39a1ce5..913b6f2ed 100644 --- a/drivers/atm/horizon.c +++ b/drivers/atm/horizon.c @@ -603,7 +603,8 @@ static int make_rate (const hrz_dev * dev, u32 c, rounding r, // note: rounding the rate down means rounding 'p' up - const unsigned long br = test_bit (ultra, &dev->flags) ? BR_ULT : BR_HRZ; + const unsigned long br = test_bit (ultra, (hrz_flags *) &dev->flags) ? + BR_ULT : BR_HRZ; u32 div = CR_MIND; u32 pre; diff --git a/drivers/atm/idt77105.c b/drivers/atm/idt77105.c index 48ba84369..320dd0ac8 100644 --- a/drivers/atm/idt77105.c +++ b/drivers/atm/idt77105.c @@ -48,10 +48,12 @@ static void idt77105_stats_timer_func(unsigned long); static void idt77105_restart_timer_func(unsigned long); -static struct timer_list stats_timer = { NULL, NULL, 0L, 0L, - &idt77105_stats_timer_func }; -static struct timer_list restart_timer = { NULL, NULL, 0L, 0L, - &idt77105_restart_timer_func }; +static struct timer_list stats_timer = { + function: &idt77105_stats_timer_func +}; +static struct timer_list restart_timer = { + function: &idt77105_restart_timer_func +}; static int start_timer = 1; static struct idt77105_priv *idt77105_all = NULL; diff --git a/drivers/atm/nicstar.c b/drivers/atm/nicstar.c index 733487374..3550acd41 100644 --- a/drivers/atm/nicstar.c +++ b/drivers/atm/nicstar.c @@ -21,6 +21,18 @@ ******************************************************************************/ +/**** IMPORTANT INFORMATION *************************************************** + * + * There are currently three types of spinlocks: + * + * 1 - Per card interrupt spinlock (to protect structures and such) + * 2 - Per SCQ scq spinlock + * 3 - Per card resource spinlock (to access registers, etc.) + * + * These must NEVER be grabbed in reverse order. + * + ******************************************************************************/ + /* Header files ***************************************************************/ #include <linux/module.h> @@ -115,6 +127,85 @@ #define ATM_SKB(s) (&(s)->atm) #endif + /* Spinlock debugging stuff */ +#ifdef NS_DEBUG_SPINLOCKS /* See nicstar.h */ +#define ns_grab_int_lock(card,flags) \ + do { \ + unsigned long nsdsf, nsdsf2; \ + local_irq_save(flags); \ + save_flags(nsdsf); cli();\ + if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ + (flags)&(1<<9)?"en":"dis"); \ + if (spin_is_locked(&(card)->int_lock) && \ + (card)->cpu_int == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) int_lock already locked at line %d (cpu %d)\n", \ + __LINE__, smp_processor_id(), (card)->has_int_lock, \ + (card)->cpu_int); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + if (spin_is_locked(&(card)->res_lock) && \ + (card)->cpu_res == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying int)\n", \ + __LINE__, smp_processor_id(), (card)->has_res_lock, \ + (card)->cpu_res); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + spin_lock_irq(&(card)->int_lock); \ + (card)->has_int_lock = __LINE__; \ + (card)->cpu_int = smp_processor_id(); \ + restore_flags(nsdsf); } while (0) +#define ns_grab_res_lock(card,flags) \ + do { \ + unsigned long nsdsf, nsdsf2; \ + local_irq_save(flags); \ + save_flags(nsdsf); cli();\ + if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ + (flags)&(1<<9)?"en":"dis"); \ + if (spin_is_locked(&(card)->res_lock) && \ + (card)->cpu_res == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) res_lock already locked at line %d (cpu %d)\n", \ + __LINE__, smp_processor_id(), (card)->has_res_lock, \ + (card)->cpu_res); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + spin_lock_irq(&(card)->res_lock); \ + (card)->has_res_lock = __LINE__; \ + (card)->cpu_res = smp_processor_id(); \ + restore_flags(nsdsf); } while (0) +#define ns_grab_scq_lock(card,scq,flags) \ + do { \ + unsigned long nsdsf, nsdsf2; \ + local_irq_save(flags); \ + save_flags(nsdsf); cli();\ + if (nsdsf & (1<<9)) printk ("nicstar.c: ints %sabled -> enabled.\n", \ + (flags)&(1<<9)?"en":"dis"); \ + if (spin_is_locked(&(scq)->lock) && \ + (scq)->cpu_lock == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) this scq_lock already locked at line %d (cpu %d)\n", \ + __LINE__, smp_processor_id(), (scq)->has_lock, \ + (scq)->cpu_lock); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + if (spin_is_locked(&(card)->res_lock) && \ + (card)->cpu_res == smp_processor_id()) { \ + printk("nicstar.c: line %d (cpu %d) res_lock locked at line %d (cpu %d)(trying scq)\n", \ + __LINE__, smp_processor_id(), (card)->has_res_lock, \ + (card)->cpu_res); \ + printk("nicstar.c: ints were %sabled.\n", ((flags)&(1<<9)?"en":"dis")); \ + } \ + spin_lock_irq(&(scq)->lock); \ + (scq)->has_lock = __LINE__; \ + (scq)->cpu_lock = smp_processor_id(); \ + restore_flags(nsdsf); } while (0) +#else /* !NS_DEBUG_SPINLOCKS */ +#define ns_grab_int_lock(card,flags) \ + spin_lock_irqsave(&(card)->int_lock,(flags)) +#define ns_grab_res_lock(card,flags) \ + spin_lock_irqsave(&(card)->res_lock,(flags)) +#define ns_grab_scq_lock(card,scq,flags) \ + spin_lock_irqsave(&(scq)->lock,flags) +#endif /* NS_DEBUG_SPINLOCKS */ + /* Version definition *********************************************************/ /* @@ -406,12 +497,12 @@ static u32 ns_read_sram(ns_dev *card, u32 sram_address) sram_address <<= 2; sram_address &= 0x0007FFFC; /* address must be dword aligned */ sram_address |= 0x50000000; /* SRAM read command */ - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); writel(sram_address, card->membase + CMD); while (CMD_BUSY(card)); data = readl(card->membase + DR0); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); return data; } @@ -424,7 +515,7 @@ static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count) count--; /* count range now is 0..3 instead of 1..4 */ c = count; c <<= 2; /* to use increments of 4 */ - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); for (i = 0; i <= c; i += 4) writel(*(value++), card->membase + i); @@ -434,14 +525,14 @@ static void ns_write_sram(ns_dev *card, u32 sram_address, u32 *value, int count) sram_address &= 0x0007FFFC; sram_address |= (0x40000000 | count); writel(sram_address, card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); } static int ns_init_card(int i, struct pci_dev *pcidev) { int j; - struct ns_dev *card=NULL; + struct ns_dev *card = NULL; unsigned short pci_command; unsigned char pci_latency; unsigned error; @@ -468,6 +559,8 @@ static int ns_init_card(int i, struct pci_dev *pcidev) return error; } cards[i] = card; + spin_lock_init(&card->int_lock); + spin_lock_init(&card->res_lock); card->index = i; card->atmdev = NULL; @@ -853,9 +946,6 @@ static int ns_init_card(int i, struct pci_dev *pcidev) card->iovpool.count++; } - - card->in_handler = 0; - card->in_poll = 0; card->intcnt = 0; /* Configure NICStAR */ @@ -1025,6 +1115,7 @@ static scq_info *get_scq(int size, u32 scd) scq->tbd_count = 0; init_waitqueue_head(&scq->scqfull_waitq); scq->full = 0; + spin_lock_init(&scq->lock); for (i = 0; i < scq->num_entries; i++) scq->skb[i] = NULL; @@ -1161,7 +1252,7 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, card->lbfqc += 2; } - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while (CMD_BUSY(card)); writel(addr2, card->membase + DR3); @@ -1170,7 +1261,7 @@ static void push_rxbufs(ns_dev *card, u32 type, u32 handle1, u32 addr1, writel(handle1, card->membase + DR0); writel(NS_CMD_WRITE_FREEBUFQ | (u32) type, card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); XPRINTK("nicstar%d: Pushing %s buffers at 0x%x and 0x%x.\n", card->index, (type == BUF_SM ? "small" : "large"), addr1, addr2); @@ -1193,6 +1284,7 @@ static void ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs) u32 stat_r; ns_dev *card; struct atm_dev *dev; + unsigned long flags; card = (ns_dev *) dev_id; dev = card->atmdev; @@ -1200,19 +1292,7 @@ static void ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs) PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index); - if (card->in_handler) - { - printk("nicstar%d: Re-entering ns_irq_handler()???\n", card->index); - return; - } - card->in_handler = 1; - if (card->in_poll) - { - card->in_handler = 0; - printk("nicstar%d: Called irq handler while in ns_poll()!?\n", - card->index); - return; - } + ns_grab_int_lock(card, flags); stat_r = readl(card->membase + STAT); @@ -1377,7 +1457,7 @@ static void ns_irq_handler(int irq, void *dev_id, struct pt_regs *regs) process_rsq(card); } - card->in_handler = 0; + spin_unlock_irqrestore(&card->int_lock, flags); PRINTK("nicstar%d: end of interrupt service\n", card->index); } @@ -1595,10 +1675,10 @@ static void ns_close(struct atm_vcc *vcc) unsigned long flags; addr = NS_RCT + (vcc->vpi << card->vcibits | vcc->vci) * NS_RCT_ENTRY_SIZE; - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while(CMD_BUSY(card)); writel(NS_CMD_CLOSE_CONNECTION | addr << 2, card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); vc->rx = 0; if (vc->rx_iov != NULL) @@ -1617,9 +1697,9 @@ static void ns_close(struct atm_vcc *vcc) ATM_SKB(iovb)->iovcnt); ATM_SKB(iovb)->iovcnt = 0; ATM_SKB(iovb)->vcc = NULL; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); recycle_iov_buf(card, iovb); - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); vc->rx_iov = NULL; } } @@ -1639,7 +1719,7 @@ static void ns_close(struct atm_vcc *vcc) for (;;) { - save_flags(flags); cli(); + ns_grab_scq_lock(card, scq, flags); scqep = scq->next; if (scqep == scq->base) scqep = scq->last; @@ -1647,7 +1727,7 @@ static void ns_close(struct atm_vcc *vcc) scqep--; if (scqep == scq->tail) { - restore_flags(flags); + spin_unlock_irqrestore(&scq->lock, flags); break; } /* If the last entry is not a TSR, place one in the SCQ in order to @@ -1675,8 +1755,8 @@ static void ns_close(struct atm_vcc *vcc) data = (u32) virt_to_bus(scq->next); ns_write_sram(card, scq->scd, &data, 1); } + spin_unlock_irqrestore(&scq->lock, flags); schedule(); - restore_flags(flags); } /* Free all TST entries */ @@ -1884,19 +1964,22 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, u32 data; int index; - if (scq->tail == scq->next) + ns_grab_scq_lock(card, scq, flags); + while (scq->tail == scq->next) { if (in_interrupt()) { + spin_unlock_irqrestore(&scq->lock, flags); printk("nicstar%d: Error pushing TBD.\n", card->index); return 1; } - save_flags(flags); cli(); scq->full = 1; + spin_unlock_irqrestore(&scq->lock, flags); interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); - restore_flags(flags); + ns_grab_scq_lock(card, scq, flags); if (scq->full) { + spin_unlock_irqrestore(&scq->lock, flags); printk("nicstar%d: Timeout pushing TBD.\n", card->index); return 1; } @@ -1926,19 +2009,23 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, if (vc->tbd_count >= MAX_TBD_PER_VC || scq->tbd_count >= MAX_TBD_PER_SCQ) { - if (scq->tail == scq->next) + int has_run = 0; + + while (scq->tail == scq->next) { if (in_interrupt()) { data = (u32) virt_to_bus(scq->next); ns_write_sram(card, scq->scd, &data, 1); + spin_unlock_irqrestore(&scq->lock, flags); printk("nicstar%d: Error pushing TSR.\n", card->index); return 0; } - save_flags(flags); cli(); scq->full = 1; + if (has_run++) break; + spin_unlock_irqrestore(&scq->lock, flags); interruptible_sleep_on_timeout(&scq->scqfull_waitq, SCQFULL_TIMEOUT); - restore_flags(flags); + ns_grab_scq_lock(card, scq, flags); } if (!scq->full) @@ -1970,10 +2057,11 @@ static int push_scqe(ns_dev *card, vc_map *vc, scq_info *scq, ns_scqe *tbd, else PRINTK("nicstar%d: Timeout pushing TSR.\n", card->index); } - data = (u32) virt_to_bus(scq->next); ns_write_sram(card, scq->scd, &data, 1); + spin_unlock_irqrestore(&scq->lock, flags); + return 0; } @@ -2064,6 +2152,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos) struct atm_vcc *vcc; struct sk_buff *skb; int i; + unsigned long flags; XPRINTK("nicstar%d: drain_scq() called, scq at 0x%x, pos %d.\n", card->index, (u32) scq, pos); @@ -2073,6 +2162,7 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos) return; } + ns_grab_scq_lock(card, scq, flags); i = (int) (scq->tail - scq->base); if (++i == scq->num_entries) i = 0; @@ -2084,16 +2174,18 @@ static void drain_scq(ns_dev *card, scq_info *scq, int pos) if (skb != NULL) { vcc = ATM_SKB(skb)->vcc; - if (vcc->pop != NULL) + if (vcc->pop != NULL) { vcc->pop(vcc, skb); - else - dev_kfree_skb_any(skb); + } else { + dev_kfree_skb_irq(skb); + } scq->skb[i] = NULL; } if (++i == scq->num_entries) i = 0; } scq->tail = scq->base + pos; + spin_unlock_irqrestore(&scq->lock, flags); } @@ -2890,10 +2982,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) { struct sk_buff *hb; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); hb = skb_dequeue(&card->hbpool.queue); card->hbpool.count--; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); if (hb == NULL) printk("nicstar%d: huge buffer count inconsistent.\n", card->index); @@ -2908,10 +3000,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) hb = alloc_skb(NS_HBUFSIZE, GFP_KERNEL); if (hb == NULL) return -ENOMEM; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); skb_queue_tail(&card->hbpool.queue, hb); card->hbpool.count++; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); } break; @@ -2920,10 +3012,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) { struct sk_buff *iovb; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); iovb = skb_dequeue(&card->iovpool.queue); card->iovpool.count--; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); if (iovb == NULL) printk("nicstar%d: iovec buffer count inconsistent.\n", card->index); @@ -2938,10 +3030,10 @@ static int ns_ioctl(struct atm_dev *dev, unsigned int cmd, void *arg) iovb = alloc_skb(NS_IOVBUFSIZE, GFP_KERNEL); if (iovb == NULL) return -ENOMEM; - save_flags(flags); cli(); + ns_grab_int_lock(card, flags); skb_queue_tail(&card->iovpool.queue, iovb); card->iovpool.count++; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); } break; @@ -2986,22 +3078,11 @@ static void ns_poll(unsigned long arg) for (i = 0; i < num_cards; i++) { card = cards[i]; - save_flags(flags); cli(); - if (card->in_poll) - { - printk("nicstar: Re-entering ns_poll()???\n"); - restore_flags(flags); - continue; - } - card->in_poll = 1; - if (card->in_handler) - { - card->in_poll = 0; - printk("nicstar%d: ns_poll called while in interrupt handler!?\n", - card->index); - restore_flags(flags); + if (spin_is_locked(&card->int_lock)) { + /* Probably it isn't worth spinning */ continue; } + ns_grab_int_lock(card, flags); stat_w = 0; stat_r = readl(card->membase + STAT); @@ -3014,8 +3095,7 @@ static void ns_poll(unsigned long arg) process_rsq(card); writel(stat_w, card->membase + STAT); - card->in_poll = 0; - restore_flags(flags); + spin_unlock_irqrestore(&card->int_lock, flags); } mod_timer(&ns_timer, jiffies + NS_POLL_PERIOD); PRINTK("nicstar: Leaving ns_poll().\n"); @@ -3069,12 +3149,12 @@ static void ns_phy_put(struct atm_dev *dev, unsigned char value, unsigned long flags; card = dev->dev_data; - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while(CMD_BUSY(card)); writel((unsigned long) value, card->membase + DR0); writel(NS_CMD_WRITE_UTILITY | 0x00000200 | (addr & 0x000000FF), card->membase + CMD); - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); } @@ -3086,12 +3166,12 @@ static unsigned char ns_phy_get(struct atm_dev *dev, unsigned long addr) unsigned long data; card = dev->dev_data; - save_flags(flags); cli(); + ns_grab_res_lock(card, flags); while(CMD_BUSY(card)); writel(NS_CMD_READ_UTILITY | 0x00000200 | (addr & 0x000000FF), card->membase + CMD); while(CMD_BUSY(card)); data = readl(card->membase + DR0) & 0x000000FF; - restore_flags(flags); + spin_unlock_irqrestore(&card->res_lock, flags); return (unsigned char) data; } diff --git a/drivers/atm/nicstar.h b/drivers/atm/nicstar.h index 4e90650c0..7dfa9ec6f 100644 --- a/drivers/atm/nicstar.h +++ b/drivers/atm/nicstar.h @@ -28,6 +28,8 @@ /* Options ********************************************************************/ +#undef NS_DEBUG_SPINLOCKS + #define NS_MAX_CARDS 4 /* Maximum number of NICStAR based cards controlled by the device driver. Must be <= 5 */ @@ -705,6 +707,11 @@ typedef struct scq_info int tbd_count; /* Only meaningful on variable rate */ wait_queue_head_t scqfull_waitq; volatile char full; /* SCQ full indicator */ + spinlock_t lock; /* SCQ spinlock */ +#ifdef NS_DEBUG_SPINLOCKS + volatile long has_lock; + volatile int cpu_lock; +#endif /* NS_DEBUG_SPINLOCKS */ } scq_info; @@ -779,8 +786,14 @@ typedef struct ns_dev struct sk_buff *rcbuf; /* Current raw cell buffer */ u32 rawch; /* Raw cell queue head */ unsigned intcnt; /* Interrupt counter */ - volatile int in_handler: 1; - volatile int in_poll: 1; + spinlock_t int_lock; /* Interrupt lock */ + spinlock_t res_lock; /* Card resource lock */ +#ifdef NS_DEBUG_SPINLOCKS + volatile long has_int_lock; + volatile int cpu_int; + volatile long has_res_lock; + volatile int cpu_res; +#endif /* NS_DEBUG_SPINLOCKS */ } ns_dev; |