summaryrefslogtreecommitdiff
path: root/drivers/dahdi
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-01-19 13:22:38 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-01-19 13:22:38 +0000
commit05be929535cf887d1d0fb6779148ac022f63793c (patch)
tree96031aee8855f3a3e36b2b916f90b7dce9086ee2 /drivers/dahdi
parenta1e57aaa0ace1d5dd445ea75772b3f00af925026 (diff)
xpp: add driftinfo attributes; pcm sync bugfix
* Add an extra sysfs Astribank attribute for drift information * PCM synchronization bugfix git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@5709 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi')
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.c61
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.h2
-rw-r--r--drivers/dahdi/xpp/xbus-sysfs.c29
3 files changed, 76 insertions, 16 deletions
diff --git a/drivers/dahdi/xpp/xbus-pcm.c b/drivers/dahdi/xpp/xbus-pcm.c
index d89991d..ef1d5e3 100644
--- a/drivers/dahdi/xpp/xbus-pcm.c
+++ b/drivers/dahdi/xpp/xbus-pcm.c
@@ -80,13 +80,26 @@ static unsigned int dahdi_tick_count = 0;
static void send_drift(xbus_t *xbus, int drift);
+static void ticker_set_cycle(struct xpp_ticker *ticker, int cycle)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ticker->lock, flags);
+ if(cycle < SYNC_ADJ_QUICK)
+ cycle = SYNC_ADJ_QUICK;
+ if(cycle > SYNC_ADJ_SLOW)
+ cycle = SYNC_ADJ_SLOW;
+ ticker->cycle = cycle;
+ spin_unlock_irqrestore(&ticker->lock, flags);
+}
+
static void xpp_ticker_init(struct xpp_ticker *ticker)
{
memset(ticker, 0, sizeof(*ticker));
+ spin_lock_init(&ticker->lock);
do_gettimeofday(&ticker->last_sample.tv);
ticker->first_sample = ticker->last_sample;
- ticker->cycle = SYNC_ADJ_QUICK;
- spin_lock_init(&ticker->lock);
+ ticker_set_cycle(ticker, SYNC_ADJ_QUICK);
}
static int xpp_ticker_step(struct xpp_ticker *ticker, const struct timeval *t)
@@ -127,7 +140,7 @@ static inline void xbus_drift_clear(xbus_t *xbus)
driftinfo_recalc(driftinfo);
driftinfo->calc_drift = 0;
- xbus->ticker.cycle = SYNC_ADJ_QUICK;
+ ticker_set_cycle(&xbus->ticker, SYNC_ADJ_QUICK);
}
void xpp_drift_init(xbus_t *xbus)
@@ -180,7 +193,7 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
lost_ticks,
(abs(lost_ticks) > 1) ? "s": "");
}
- ticker->cycle = SYNC_ADJ_QUICK;
+ ticker_set_cycle(ticker, SYNC_ADJ_QUICK);
if(abs(lost_ticks) > 100)
ticker->count = ref_ticker->count;
} else {
@@ -199,13 +212,15 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
*/
if(usec_delta > 0 && xbus->sync_adjustment > -SYNC_ADJ_MAX) {
XBUS_DBG(SYNC, xbus, "Pullback usec_delta=%ld\n", usec_delta);
+ driftinfo->kicks_down++;
send_drift(xbus, -SYNC_ADJ_MAX); /* emergency push */
}
if(usec_delta < 0 && xbus->sync_adjustment < SYNC_ADJ_MAX) {
XBUS_DBG(SYNC, xbus, "Pushback usec_delta=%ld\n", usec_delta);
+ driftinfo->kicks_up++;
send_drift(xbus, SYNC_ADJ_MAX); /* emergency push */
}
- ticker->cycle = SYNC_ADJ_QUICK;
+ ticker_set_cycle(ticker, SYNC_ADJ_QUICK);
nofix = 1;
} else {
/* good data, use it */
@@ -229,15 +244,13 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
offset = driftinfo->calc_drift + factor;
/* for large median, push some more */
if(abs(driftinfo->median) >= 300) { /* more than 2 usb uframes */
- ticker->cycle = SYNC_ADJ_QUICK;
+ ticker_set_cycle(ticker, SYNC_ADJ_QUICK);
XBUS_NOTICE(xbus,
"Back to quick: median=%d\n",
driftinfo->median);
}
} else {
- ticker->cycle += 500;
- if(ticker->cycle >= SYNC_ADJ_SLOW)
- ticker->cycle = SYNC_ADJ_SLOW;
+ //ticker_set_cycle(ticker, ticker->cycle + 500);
}
driftinfo->calc_drift = offset;
XBUS_DBG(SYNC, xbus,
@@ -276,16 +289,30 @@ const char *sync_mode_name(enum sync_mode mode)
static void xpp_set_syncer(xbus_t *xbus, bool on)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&ref_ticker_lock, flags);
+ if(!xbus) { /* Special case, no more syncers */
+ DBG(SYNC, "No more syncers\n");
+ syncer = NULL;
+ if(ref_ticker != &dahdi_ticker)
+ ref_ticker = NULL;
+ goto out;
+ }
if(syncer != xbus && on) {
XBUS_DBG(SYNC, xbus, "New syncer\n");
syncer = xbus;
} else if(syncer == xbus && !on) {
XBUS_DBG(SYNC, xbus, "Lost syncer\n");
syncer = NULL;
+ if(ref_ticker != &dahdi_ticker)
+ ref_ticker = NULL;
} else
XBUS_DBG(SYNC, xbus, "ignore %s (current syncer: %s)\n",
(on)?"ON":"OFF",
(syncer) ? syncer->busname : "NO-SYNC");
+out:
+ spin_unlock_irqrestore(&ref_ticker_lock, flags);
}
static void xbus_command_timer(unsigned long param)
@@ -324,14 +351,14 @@ void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift)
{
unsigned long flags;
- XBUS_DBG(SYNC, xbus, "Mode %s (%d), drift=%d (pcm_rx_counter=%d)\n",
- sync_mode_name(mode), mode, drift, atomic_read(&xbus->pcm_rx_counter));
spin_lock_irqsave(&xbus->lock, flags);
xbus->sync_adjustment = (signed char)drift;
if(xbus->sync_mode == mode) {
- XBUS_DBG(SYNC, xbus, "Already in mode '%s'. Ignored\n", sync_mode_name(mode));
+ /* XBUS_DBG(SYNC, xbus, "Already in mode '%s'. Ignored\n", sync_mode_name(mode)); */
goto out;
}
+ XBUS_DBG(SYNC, xbus, "Mode %s (%d), drift=%d (pcm_rx_counter=%d)\n",
+ sync_mode_name(mode), mode, drift, atomic_read(&xbus->pcm_rx_counter));
switch(mode) {
case SYNC_MODE_AB:
xbus->sync_mode = mode;
@@ -565,8 +592,10 @@ void elect_syncer(const char *msg)
XPD_DBG(SYNC, best_xpd, "%s: elected with priority %d\n", msg, timing_priority);
} else if(the_xbus) {
XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg);
- } else
+ } else {
DBG(SYNC, "%s: No more syncers\n", msg);
+ xpp_set_syncer(NULL, 0);
+ }
if(the_xbus != syncer)
update_sync_master(the_xbus, force_dahdi_sync);
}
@@ -1071,16 +1100,16 @@ int exec_sync_command(const char *buf, size_t count)
xbus_t *xbus;
if(strncmp("DAHDI", buf, 6) == 0) { /* Ignore the newline */
- DBG(SYNC, "DAHDI\n");
+ DBG(SYNC, "DAHDI");
update_sync_master(NULL, 1);
- } else if(sscanf(buf, "SYNC=%d\n", &xbusno) == 1) {
+ } else if(sscanf(buf, "SYNC=%d", &xbusno) == 1) {
DBG(SYNC, "SYNC=%d\n", xbusno);
if((xbus = xbus_num(xbusno)) == NULL) {
ERR("No bus %d exists\n", xbusno);
return -ENXIO;
}
update_sync_master(xbus, 0);
- } else if(sscanf(buf, "QUERY=%d\n", &xbusno) == 1) {
+ } else if(sscanf(buf, "QUERY=%d", &xbusno) == 1) {
DBG(SYNC, "QUERY=%d\n", xbusno);
if((xbus = xbus_num(xbusno)) == NULL) {
ERR("No bus %d exists\n", xbusno);
diff --git a/drivers/dahdi/xpp/xbus-pcm.h b/drivers/dahdi/xpp/xbus-pcm.h
index be33044..093ea60 100644
--- a/drivers/dahdi/xpp/xbus-pcm.h
+++ b/drivers/dahdi/xpp/xbus-pcm.h
@@ -80,6 +80,8 @@ struct xpp_drift {
int median; /* (max + min) / 2 */
int jitter; /* max - min */
int calc_drift;
+ int kicks_up;
+ int kicks_down;
spinlock_t lock;
};
diff --git a/drivers/dahdi/xpp/xbus-sysfs.c b/drivers/dahdi/xpp/xbus-sysfs.c
index 566bc0f..1094a19 100644
--- a/drivers/dahdi/xpp/xbus-sysfs.c
+++ b/drivers/dahdi/xpp/xbus-sysfs.c
@@ -207,6 +207,34 @@ static DEVICE_ATTR_READER(waitfor_xpds_show, dev, buf)
return len;
}
+static DEVICE_ATTR_READER(driftinfo_show, dev, buf)
+{
+ xbus_t *xbus;
+ struct xpp_drift *di;
+ struct xpp_ticker *ticker;
+ int len = 0;
+
+ xbus = dev_to_xbus(dev);
+ di = &xbus->drift;
+ ticker = &xbus->ticker;
+#define SHOW(ptr,item) len += snprintf(buf + len, PAGE_SIZE - len, "%-15s: %d\n", #item, (ptr)->item)
+ SHOW(xbus, sync_adjustment);
+ SHOW(di, wanted_offset);
+ SHOW(di, delta_tick);
+ SHOW(di, lost_ticks);
+ SHOW(di, kicks_up);
+ SHOW(di, kicks_down);
+ SHOW(di, delta_min);
+ SHOW(di, delta_max);
+ SHOW(di, median);
+ SHOW(di, jitter);
+ SHOW(di, calc_drift);
+ SHOW(ticker, cycle);
+ SHOW(ticker, tick_period);
+#undef SHOW
+ return len;
+}
+
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
#define xbus_attr(field, format_string) \
static ssize_t \
@@ -238,6 +266,7 @@ static struct device_attribute xbus_dev_attrs[] = {
__ATTR_RO(status),
__ATTR_RO(timing),
__ATTR_RO(waitfor_xpds),
+ __ATTR_RO(driftinfo),
__ATTR(cls, S_IWUSR, NULL, cls_store),
__ATTR(xbus_state, S_IRUGO | S_IWUSR, xbus_state_show, xbus_state_store),
#ifdef SAMPLE_TICKS