From 05be929535cf887d1d0fb6779148ac022f63793c Mon Sep 17 00:00:00 2001 From: Tzafrir Cohen Date: Mon, 19 Jan 2009 13:22:38 +0000 Subject: 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 --- drivers/dahdi/xpp/xbus-pcm.c | 61 +++++++++++++++++++++++++++++++----------- drivers/dahdi/xpp/xbus-pcm.h | 2 ++ drivers/dahdi/xpp/xbus-sysfs.c | 29 ++++++++++++++++++++ 3 files changed, 76 insertions(+), 16 deletions(-) (limited to 'drivers') 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 -- cgit v1.2.3