summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorShaun Ruffell <sruffell@digium.com>2009-07-21 18:11:53 +0000
committerShaun Ruffell <sruffell@digium.com>2009-07-21 18:11:53 +0000
commit75ff751f904456c4e92991e005c06307b88c886c (patch)
tree32db9ddf6d6052f95ae61b446315e94a5ddd8c47
parent131eae4b7f1087e2a739ef799985875d6fdc2354 (diff)
Merged revisions 6844,6852,6862-6863 via svnmerge from
https://origsvn.digium.com/svn/dahdi/linux/trunk ........ r6844 | sruffell | 2009-07-16 12:29:53 -0500 (Thu, 16 Jul 2009) | 10 lines wcte12xp: Disable vpmadt032 companding by default. This fixes a regression in 2.2.0 where certain configurations will fail patloop test or have repeated HDLC aborts because the VPMADT032 is modifying the clear channel or d channel data streams. This restores the behavior to how it was in dahdi-linux 2.1.0.4. (closes issue #15498) Reported by: alecdavis Tested by: alecdavis ........ r6852 | tzafrir | 2009-07-19 10:45:40 -0500 (Sun, 19 Jul 2009) | 12 lines tor2: allow using port4 as timing source Fix a silly regression introduced when strict check on the timing parameter was added (sync-1 is the array index, not sync itself. And 0 is a special case). (closes issue #15408) Reported by: dferrer Patches: tor2-4th_sync.patch uploaded by dferrer (license 525) ........ r6862 | sruffell | 2009-07-21 12:52:59 -0500 (Tue, 21 Jul 2009) | 4 lines Revert "wct4xxp, wcte11xp: Use the default configuration by default at startup." This reverts the change introduced by revision 6712. This change can cause problems when there is a VPM module installed on the quad-span digital cards. ........ r6863 | sruffell | 2009-07-21 12:53:02 -0500 (Tue, 21 Jul 2009) | 12 lines dahdi-base: Add support for core timing. This essentially moves the function of dahdi_dummy into the core of DAHDI. It ensures that if DAHDI is loaded, it will always be able to provide timing, regardless of whether there are board drivers loaded, or if the board drivers are properly calling dahdi_receive. If there is a master span loaded which is calling dahdi_receive, then the behavior will be like it is normally. This functionality is off by default, uncomment CONFIG_DAHDI_CORE_TIMER in include/dahdi/config_dahdi.h in order to enable it. ........ git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/branches/2.2@6864 a0bf4364-ded3-4de4-8d8a-66a801d63aff
-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