diff options
Diffstat (limited to 'drivers/dahdi')
-rw-r--r-- | drivers/dahdi/dahdi-base.c | 326 | ||||
-rw-r--r-- | drivers/dahdi/tor2.c | 2 | ||||
-rw-r--r-- | drivers/dahdi/wct4xxp/base.c | 8 | ||||
-rw-r--r-- | drivers/dahdi/wcte11xp.c | 7 | ||||
-rw-r--r-- | drivers/dahdi/wcte12xp/base.c | 2 |
5 files changed, 237 insertions, 108 deletions
diff --git a/drivers/dahdi/dahdi-base.c b/drivers/dahdi/dahdi-base.c index 4916657..3c8aa18 100644 --- a/drivers/dahdi/dahdi-base.c +++ b/drivers/dahdi/dahdi-base.c @@ -238,6 +238,19 @@ static struct { int dst; /* dst conf number */ } conf_links[DAHDI_MAX_CONF + 1]; +#ifdef CONFIG_DAHDI_CORE_TIMER + +static struct core_timer { + struct timer_list timer; + struct timespec start_interval; + atomic_t count; + atomic_t shutdown; + atomic_t last_count; +} core_timer; + +#endif /* CONFIG_DAHDI_CORE_TIMER */ + + /* There are three sets of conference sum accumulators. One for the current sample chunk (conf_sums), one for the next sample chunk (conf_sums_next), and @@ -2671,12 +2684,22 @@ static int dahdi_specchan_release(struct inode *node, struct file *file, int uni return res; } +static int can_open_timer(void) +{ +#ifdef CONFIG_DAHDI_CORE_TIMER + return 1; +#else + return maxspans > 0; +#endif +} + static struct dahdi_chan *dahdi_alloc_pseudo(void) { struct dahdi_chan *pseudo; - /* Don't allow /dev/dahdi/pseudo to open if there are no spans */ - if (maxspans < 1) + /* Don't allow /dev/dahdi/pseudo to open if there is not a timing + * source. */ + if (!can_open_timer()) return NULL; if (!(pseudo = kzalloc(sizeof(*pseudo), GFP_KERNEL))) @@ -2734,7 +2757,7 @@ static int dahdi_open(struct inode *inode, struct file *file) return -ENXIO; } if (unit == 253) { - if (maxspans) { + if (can_open_timer()) { return dahdi_timing_open(inode, file); } else { return -ENXIO; @@ -2743,16 +2766,13 @@ static int dahdi_open(struct inode *inode, struct file *file) if (unit == 254) return dahdi_chan_open(inode, file); if (unit == 255) { - if (maxspans) { - chan = dahdi_alloc_pseudo(); - if (chan) { - file->private_data = chan; - return dahdi_specchan_open(inode, file, chan->channo); - } else { - return -ENXIO; - } - } else + chan = dahdi_alloc_pseudo(); + if (chan) { + file->private_data = chan; + return dahdi_specchan_open(inode, file, chan->channo); + } else { return -ENXIO; + } } return dahdi_specchan_open(inode, file, unit); } @@ -7748,12 +7768,207 @@ int dahdi_transmit(struct dahdi_span *span) return 0; } +static void process_masterspan(void) +{ + unsigned long flags; + int x, y, z; + +#ifdef CONFIG_DAHDI_CORE_TIMER + /* We increment the calls since start here, so that if we switch over + * to the core timer, we know how many times we need to call + * process_masterspan in order to catch up since this function needs + * to be called 1000 times per second. */ + atomic_inc(&core_timer.count); +#endif + /* Hold the big zap lock for the duration of major + activities which touch all sorts of channels */ + spin_lock_irqsave(&bigzaplock, flags); + read_lock(&chan_lock); + /* Process any timers */ + process_timers(); + /* If we have dynamic stuff, call the ioctl with 0,0 parameters to + make it run */ + if (dahdi_dynamic_ioctl) + dahdi_dynamic_ioctl(0, 0); + + for (x = 1; x < maxchans; x++) { + if (chans[x] && chans[x]->confmode && + !(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { + u_char *data; + spin_lock(&chans[x]->lock); + data = __buf_peek(&chans[x]->confin); + __dahdi_receive_chunk(chans[x], data); + if (data) { + __buf_pull(&chans[x]->confin, NULL, chans[x], + "confreceive"); + } + spin_unlock(&chans[x]->lock); + } + } + /* This is the master channel, so make things switch over */ + rotate_sums(); + /* do all the pseudo and/or conferenced channel receives (getbuf's) */ + for (x = 1; x < maxchans; x++) { + if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { + spin_lock(&chans[x]->lock); + __dahdi_transmit_chunk(chans[x], NULL); + spin_unlock(&chans[x]->lock); + } + } + if (maxlinks) { +#ifdef CONFIG_DAHDI_MMX + dahdi_kernel_fpu_begin(); +#endif + /* process all the conf links */ + for (x = 1; x <= maxlinks; x++) { + /* if we have a destination conf */ + z = confalias[conf_links[x].dst]; + if (z) { + y = confalias[conf_links[x].src]; + if (y) + ACSS(conf_sums[z], conf_sums[y]); + } + } +#ifdef CONFIG_DAHDI_MMX + dahdi_kernel_fpu_end(); +#endif + } + /* do all the pseudo/conferenced channel transmits (putbuf's) */ + for (x = 1; x < maxchans; x++) { + if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { + unsigned char tmp[DAHDI_CHUNKSIZE]; + spin_lock(&chans[x]->lock); + __dahdi_getempty(chans[x], tmp); + __dahdi_receive_chunk(chans[x], tmp); + spin_unlock(&chans[x]->lock); + } + } + for (x = 1; x < maxchans; x++) { + if (chans[x] && chans[x]->confmode && + !(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { + u_char *data; + spin_lock(&chans[x]->lock); + data = __buf_pushpeek(&chans[x]->confout); + __dahdi_transmit_chunk(chans[x], data); + if (data) + __buf_push(&chans[x]->confout, NULL, + "conftransmit"); + spin_unlock(&chans[x]->lock); + } + } +#ifdef DAHDI_SYNC_TICK + for (x = 0; x < maxspans; x++) { + struct dahdi_span *const s = spans[x]; + if (s && s->sync_tick) + s->sync_tick(s, s == master); + } +#endif + read_unlock(&chan_lock); + spin_unlock_irqrestore(&bigzaplock, flags); +} + +#ifndef CONFIG_DAHDI_CORE_TIMER + +static void coretimer_init(void) +{ + return; +} + +static void coretimer_cleanup(void) +{ + return; +} + +#else + +static unsigned long core_diff_ms(struct timespec *t0, struct timespec *t1) +{ + long nanosec, sec; + unsigned long ms; + sec = (t1->tv_sec - t0->tv_sec); + nanosec = (t1->tv_nsec - t0->tv_nsec); + while (nanosec >= NSEC_PER_SEC) { + nanosec -= NSEC_PER_SEC; + ++sec; + } + while (nanosec < 0) { + nanosec += NSEC_PER_SEC; + --sec; + } + ms = (sec * 1000) + (nanosec / 1000000L); + return ms; +} + +static void coretimer_func(unsigned long param) +{ + unsigned long ms_since_start; + struct timespec now; + const unsigned long MAX_INTERVAL = 100000L; + const unsigned long FOURMS_INTERVAL = HZ/250; + const unsigned long ONESEC_INTERVAL = HZ; + + now = current_kernel_time(); + + if (atomic_read(&core_timer.count) == + atomic_read(&core_timer.last_count)) { + + /* This is the code path if a board driver is not calling + * dahdi_receive, and therefore the core of dahdi needs to + * perform the master span processing itself. */ + + if (!atomic_read(&core_timer.shutdown)) + mod_timer(&core_timer.timer, jiffies + FOURMS_INTERVAL); + + ms_since_start = core_diff_ms(&core_timer.start_interval, &now); + while (ms_since_start > atomic_read(&core_timer.count)) + process_masterspan(); + + if (ms_since_start > MAX_INTERVAL) { + atomic_set(&core_timer.count, 0); + atomic_set(&core_timer.last_count, 0); + core_timer.start_interval = now; + } else { + atomic_set(&core_timer.last_count, + atomic_read(&core_timer.count)); + } + + } else { + + /* It looks like a board driver is calling dahdi_receive. We + * will just check again in a second. */ + atomic_set(&core_timer.count, 0); + atomic_set(&core_timer.last_count, 0); + core_timer.start_interval = now; + if (!atomic_read(&core_timer.shutdown)) + mod_timer(&core_timer.timer, jiffies + ONESEC_INTERVAL); + } +} + +static void coretimer_init(void) +{ + init_timer(&core_timer.timer); + core_timer.timer.function = coretimer_func; + core_timer.start_interval = current_kernel_time(); + core_timer.timer.expires = jiffies + HZ; + atomic_set(&core_timer.count, 0); + atomic_set(&core_timer.shutdown, 0); + add_timer(&core_timer.timer); +} + +static void coretimer_cleanup(void) +{ + atomic_set(&core_timer.shutdown, 1); + del_timer_sync(&core_timer.timer); +} + +#endif /* CONFIG_DAHDI_CORE_TIMER */ + + int dahdi_receive(struct dahdi_span *span) { int x,y,z; unsigned long flags; -#if 1 #ifdef CONFIG_DAHDI_WATCHDOG span->watchcounter--; #endif @@ -7833,87 +8048,9 @@ int dahdi_receive(struct dahdi_span *span) } } - if (span == master) { - /* Hold the big zap lock for the duration of major - activities which touch all sorts of channels */ - spin_lock_irqsave(&bigzaplock, flags); - read_lock(&chan_lock); - /* Process any timers */ - process_timers(); - /* If we have dynamic stuff, call the ioctl with 0,0 parameters to - make it run */ - if (dahdi_dynamic_ioctl) - dahdi_dynamic_ioctl(0,0); - for (x=1;x<maxchans;x++) { - if (chans[x] && chans[x]->confmode && !(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { - u_char *data; - spin_lock(&chans[x]->lock); - data = __buf_peek(&chans[x]->confin); - __dahdi_receive_chunk(chans[x], data); - if (data) - __buf_pull(&chans[x]->confin, NULL,chans[x], "confreceive"); - spin_unlock(&chans[x]->lock); - } - } - /* This is the master channel, so make things switch over */ - rotate_sums(); - /* do all the pseudo and/or conferenced channel receives (getbuf's) */ - for (x=1;x<maxchans;x++) { - if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { - spin_lock(&chans[x]->lock); - __dahdi_transmit_chunk(chans[x], NULL); - spin_unlock(&chans[x]->lock); - } - } - if (maxlinks) { -#ifdef CONFIG_DAHDI_MMX - dahdi_kernel_fpu_begin(); -#endif - /* process all the conf links */ - for(x = 1; x <= maxlinks; x++) { - /* if we have a destination conf */ - if (((z = confalias[conf_links[x].dst]) > 0) && - ((y = confalias[conf_links[x].src]) > 0)) { - ACSS(conf_sums[z], conf_sums[y]); - } - } -#ifdef CONFIG_DAHDI_MMX - kernel_fpu_end(); -#endif - } - /* do all the pseudo/conferenced channel transmits (putbuf's) */ - for (x=1;x<maxchans;x++) { - if (chans[x] && (chans[x]->flags & DAHDI_FLAG_PSEUDO)) { - unsigned char tmp[DAHDI_CHUNKSIZE]; - spin_lock(&chans[x]->lock); - __dahdi_getempty(chans[x], tmp); - __dahdi_receive_chunk(chans[x], tmp); - spin_unlock(&chans[x]->lock); - } - } - for (x=1;x<maxchans;x++) { - if (chans[x] && chans[x]->confmode && !(chans[x]->flags & DAHDI_FLAG_PSEUDO)) { - u_char *data; - spin_lock(&chans[x]->lock); - data = __buf_pushpeek(&chans[x]->confout); - __dahdi_transmit_chunk(chans[x], data); - if (data) - __buf_push(&chans[x]->confout, NULL, "conftransmit"); - spin_unlock(&chans[x]->lock); - } - } -#ifdef DAHDI_SYNC_TICK - for (x=0;x<maxspans;x++) { - struct dahdi_span *s = spans[x]; + if (span == master) + process_masterspan(); - if (s && s->sync_tick) - s->sync_tick(s, s == master); - } -#endif - read_unlock(&chan_lock); - spin_unlock_irqrestore(&bigzaplock, flags); - } -#endif return 0; } @@ -8045,6 +8182,7 @@ static int __init dahdi_init(void) #ifdef CONFIG_DAHDI_WATCHDOG watchdog_init(); #endif + coretimer_init(); return res; } @@ -8052,6 +8190,8 @@ static void __exit dahdi_cleanup(void) { int x; + coretimer_cleanup(); + CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 253)); /* timer */ CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 254)); /* channel */ CLASS_DEV_DESTROY(dahdi_class, MKDEV(DAHDI_MAJOR, 255)); /* pseudo */ diff --git a/drivers/dahdi/tor2.c b/drivers/dahdi/tor2.c index 9ae8169..3aa6ed6 100644 --- a/drivers/dahdi/tor2.c +++ b/drivers/dahdi/tor2.c @@ -200,7 +200,7 @@ static int tor2_spanconfig(struct dahdi_span *span, struct dahdi_lineconfig *lc) if (debug) printk(KERN_INFO "Tor2: Configuring span %d\n", span->spanno); - if ((lc->sync < 0) || (lc->sync >= SPANS_PER_CARD)) { + if ((lc->sync < 0) || (lc->sync > SPANS_PER_CARD)) { printk(KERN_WARNING "%s %d: invalid span timing value %d.\n", THIS_MODULE->name, span->spanno, lc->sync); return -EINVAL; diff --git a/drivers/dahdi/wct4xxp/base.c b/drivers/dahdi/wct4xxp/base.c index 6558de8..96fabde 100644 --- a/drivers/dahdi/wct4xxp/base.c +++ b/drivers/dahdi/wct4xxp/base.c @@ -6,7 +6,7 @@ * written by Jim Dixon <jim@lambdatel.com>. * * Copyright (C) 2001 Jim Dixon / Zapata Telephony. - * Copyright (C) 2001-2009, Digium, Inc. + * Copyright (C) 2001-2005, Digium, Inc. * * All rights reserved. * @@ -3547,12 +3547,6 @@ static int __devinit t4_launch(struct t4 *wc) __t4_set_timing_source(wc,4, 0, 0); spin_unlock_irqrestore(&wc->reglock, flags); tasklet_init(&wc->t4_tlet, t4_isr_bh, (unsigned long)wc); - - /* Start the first span on the card with the default configuration so - * that it may provide timing to Asterisk before being properly - * configured. */ - t4_startup(&wc->tspans[0]->span); - return 0; } diff --git a/drivers/dahdi/wcte11xp.c b/drivers/dahdi/wcte11xp.c index 26f47fa..390c834 100644 --- a/drivers/dahdi/wcte11xp.c +++ b/drivers/dahdi/wcte11xp.c @@ -5,7 +5,7 @@ * Matthew Fredrickson <creslin@digium.com> * William Meadows <wmeadows@digium.com> * - * Copyright (C) 2004-2009, Digium, Inc. + * Copyright (C) 2004, Digium, Inc. * * All rights reserved. */ @@ -1013,11 +1013,6 @@ static int t1xxp_software_init(struct t1 *wc) printk(KERN_NOTICE "Unable to register span with DAHDI\n"); return -1; } - - /* Start off with the defaults so this card can provide timing to - * Asterisk before being properly configured. */ - t1xxp_startup(&wc->span); - return 0; } diff --git a/drivers/dahdi/wcte12xp/base.c b/drivers/dahdi/wcte12xp/base.c index 83b87a8..7dd8cde 100644 --- a/drivers/dahdi/wcte12xp/base.c +++ b/drivers/dahdi/wcte12xp/base.c @@ -1317,7 +1317,7 @@ static void setchanconfig_from_state(struct vpmadt032 *vpm, int channel, GpakCha chanconfig->MuteToneB = Disabled; chanconfig->FaxCngDetB = Disabled; - chanconfig->SoftwareCompand = cmpPCMU; + chanconfig->SoftwareCompand = cmpNone; chanconfig->FrameRate = rate10ms; |