summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/dahdi/dahdi-base.c326
-rw-r--r--drivers/dahdi/tor2.c2
-rw-r--r--drivers/dahdi/wct4xxp/base.c8
-rw-r--r--drivers/dahdi/wcte11xp.c7
-rw-r--r--drivers/dahdi/wcte12xp/base.c2
-rw-r--r--include/dahdi/dahdi_config.h8
6 files changed, 245 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;
diff --git a/include/dahdi/dahdi_config.h b/include/dahdi/dahdi_config.h
index 865439d..68547f1 100644
--- a/include/dahdi/dahdi_config.h
+++ b/include/dahdi/dahdi_config.h
@@ -115,6 +115,12 @@
*/
/* #define CONFIG_CAC_GROUNDSTART */
+/*
+ * Define CONFIG_DAHDI_CORE_TIMER if you would like dahdi to always provide a
+ * timing source regardless of which spans / drivers are configured.
+ */
+/* #define CONFIG_DAHDI_CORE_TIMER */
+
/*
* Uncomment if you happen have an early TDM400P Rev H which
* sometimes forgets its PCI ID to have wcfxs match essentially all
@@ -167,4 +173,6 @@
*/
/* #define OPTIMIZE_CHANMUTE */
+
+
#endif