diff options
author | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2010-07-13 18:35:20 +0000 |
---|---|---|
committer | Tzafrir Cohen <tzafrir.cohen@xorcom.com> | 2010-07-13 18:35:20 +0000 |
commit | bfc9917e6888fc8f38a7c2b95ce3939cf2a9805e (patch) | |
tree | fe0bea6d4a2430fc1302db9564fc61974fcff863 /drivers/dahdi/xpp | |
parent | f96ad0b72056f9bee53d19951211f0271795f1e2 (diff) |
PRI Astribanks always sync AB (and independent)
* PRI devices always get SYNC-AB (never PLL, not even for NT)
* Fix Timing priority calculation accordingly.
* On PRI layer1 changes, elect_syncer() is called, so we have
re-election.
git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@8909 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/xpp')
-rw-r--r-- | drivers/dahdi/xpp/card_bri.c | 1 | ||||
-rw-r--r-- | drivers/dahdi/xpp/card_fxo.c | 1 | ||||
-rw-r--r-- | drivers/dahdi/xpp/card_fxs.c | 1 | ||||
-rw-r--r-- | drivers/dahdi/xpp/card_pri.c | 15 | ||||
-rw-r--r-- | drivers/dahdi/xpp/xbus-core.c | 1 | ||||
-rw-r--r-- | drivers/dahdi/xpp/xbus-core.h | 2 | ||||
-rw-r--r-- | drivers/dahdi/xpp/xbus-pcm.c | 62 | ||||
-rw-r--r-- | drivers/dahdi/xpp/xbus-pcm.h | 1 | ||||
-rw-r--r-- | drivers/dahdi/xpp/xpp_dahdi.c | 2 | ||||
-rw-r--r-- | drivers/dahdi/xpp/xproto.h | 1 |
10 files changed, 76 insertions, 11 deletions
diff --git a/drivers/dahdi/xpp/card_bri.c b/drivers/dahdi/xpp/card_bri.c index 75a8940..7d3e652 100644 --- a/drivers/dahdi/xpp/card_bri.c +++ b/drivers/dahdi/xpp/card_bri.c @@ -1671,6 +1671,7 @@ static xproto_table_t PROTO_TABLE(BRI) = { .card_pcm_recompute = BRI_card_pcm_recompute, .card_pcm_fromspan = BRI_card_pcm_fromspan, .card_pcm_tospan = BRI_card_pcm_tospan, + .card_timing_priority = generic_timing_priority, .card_ioctl = BRI_card_ioctl, .card_open = BRI_card_open, .card_close = BRI_card_close, diff --git a/drivers/dahdi/xpp/card_fxo.c b/drivers/dahdi/xpp/card_fxo.c index c8b08fa..474e217 100644 --- a/drivers/dahdi/xpp/card_fxo.c +++ b/drivers/dahdi/xpp/card_fxo.c @@ -1133,6 +1133,7 @@ static xproto_table_t PROTO_TABLE(FXO) = { .card_pcm_recompute = generic_card_pcm_recompute, .card_pcm_fromspan = generic_card_pcm_fromspan, .card_pcm_tospan = generic_card_pcm_tospan, + .card_timing_priority = generic_timing_priority, .card_ioctl = FXO_card_ioctl, .card_open = FXO_card_open, .card_register_reply = FXO_card_register_reply, diff --git a/drivers/dahdi/xpp/card_fxs.c b/drivers/dahdi/xpp/card_fxs.c index 4d7cbfd..be62469 100644 --- a/drivers/dahdi/xpp/card_fxs.c +++ b/drivers/dahdi/xpp/card_fxs.c @@ -1409,6 +1409,7 @@ static xproto_table_t PROTO_TABLE(FXS) = { .card_pcm_recompute = generic_card_pcm_recompute, .card_pcm_fromspan = generic_card_pcm_fromspan, .card_pcm_tospan = generic_card_pcm_tospan, + .card_timing_priority = generic_timing_priority, .card_open = FXS_card_open, .card_close = FXS_card_close, .card_ioctl = FXS_card_ioctl, diff --git a/drivers/dahdi/xpp/card_pri.c b/drivers/dahdi/xpp/card_pri.c index b03ad02..4cdbe6f 100644 --- a/drivers/dahdi/xpp/card_pri.c +++ b/drivers/dahdi/xpp/card_pri.c @@ -1193,6 +1193,7 @@ static xpd_t *PRI_card_new(xbus_t *xbus, int unit, int subunit, const xproto_tab return NULL; } #endif + xbus->sync_mode_default = SYNC_MODE_AB; return xpd; } @@ -1827,6 +1828,18 @@ static void PRI_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack) spin_unlock_irqrestore(&xpd->lock, flags); } +int PRI_timing_priority(xbus_t *xbus, xpd_t *xpd) +{ + struct PRI_priv_data *priv; + + priv = xpd->priv; + BUG_ON(!priv); + if (priv->layer1_up) + return xpd->timing_priority; + XPD_DBG(SYNC, xpd, "No timing priority (no layer1)\n"); + return -ENOENT; +} + /*---------------- PRI: HOST COMMANDS -------------------------------------*/ static /* 0x0F */ HOSTCMD(PRI, XPD_STATE, bool on) @@ -1917,6 +1930,7 @@ static void layer1_state(xpd_t *xpd, byte data_low) send_idlebits(xpd, 1); } xpd->span.alarms = alarms; + elect_syncer("LAYER1"); dahdi_alarm_notify(&xpd->span); set_clocking(xpd); } @@ -2140,6 +2154,7 @@ static xproto_table_t PROTO_TABLE(PRI) = { .card_pcm_recompute = PRI_card_pcm_recompute, .card_pcm_fromspan = PRI_card_pcm_fromspan, .card_pcm_tospan = PRI_card_pcm_tospan, + .card_timing_priority = PRI_timing_priority, .card_ioctl = PRI_card_ioctl, .card_close = PRI_card_close, .card_register_reply = PRI_card_register_reply, diff --git a/drivers/dahdi/xpp/xbus-core.c b/drivers/dahdi/xpp/xbus-core.c index 3acf2d9..6b331e0 100644 --- a/drivers/dahdi/xpp/xbus-core.c +++ b/drivers/dahdi/xpp/xbus-core.c @@ -1475,6 +1475,7 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, struct device *tran worker_init(xbus); atomic_set(&xbus->num_xpds, 0); xbus->sync_mode = SYNC_MODE_NONE; + xbus->sync_mode_default = SYNC_MODE_PLL; err = xbus_sysfs_create(xbus); if(err) { XBUS_ERR(xbus, "SYSFS creation failed: %d\n", err); diff --git a/drivers/dahdi/xpp/xbus-core.h b/drivers/dahdi/xpp/xbus-core.h index 15312c6..4fbc57b 100644 --- a/drivers/dahdi/xpp/xbus-core.h +++ b/drivers/dahdi/xpp/xbus-core.h @@ -194,6 +194,8 @@ struct xbus { bool self_ticking; enum sync_mode sync_mode; + /* Managed by low-level drivers: */ + enum sync_mode sync_mode_default; struct timer_list command_timer; unsigned int xbus_frag_count; struct xframe_queue pcm_tospan; diff --git a/drivers/dahdi/xpp/xbus-pcm.c b/drivers/dahdi/xpp/xbus-pcm.c index 283d857..ca722cf 100644 --- a/drivers/dahdi/xpp/xbus-pcm.c +++ b/drivers/dahdi/xpp/xbus-pcm.c @@ -56,6 +56,7 @@ static struct xpp_ticker dahdi_ticker; */ static struct xpp_ticker *ref_ticker = NULL; static spinlock_t ref_ticker_lock = SPIN_LOCK_UNLOCKED; +static spinlock_t elect_syncer_lock = SPIN_LOCK_UNLOCKED; static bool force_dahdi_sync = 0; /* from /sys/bus/astribanks/drivers/xppdrv/sync */ static xbus_t *global_ticker; static struct xpp_ticker global_ticks_series; @@ -305,17 +306,17 @@ const char *sync_mode_name(enum sync_mode mode) return sync_mode_names[mode]; } +/* + * Caller must aquire/release the 'ref_ticker_lock' spinlock + */ 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; + return; } if(syncer != xbus && on) { XBUS_DBG(SYNC, xbus, "New syncer\n"); @@ -329,8 +330,6 @@ static void xpp_set_syncer(xbus_t *xbus, bool on) 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) @@ -369,11 +368,14 @@ void xbus_set_command_timer(xbus_t *xbus, bool on) void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift) { unsigned long flags; + unsigned long flags2; spin_lock_irqsave(&xbus->lock, flags); + spin_lock_irqsave(&ref_ticker_lock, flags2); 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", @@ -402,15 +404,32 @@ void got_new_syncer(xbus_t *xbus, enum sync_mode mode, int drift) XBUS_ERR(xbus, "%s: unknown mode=0x%X\n", __FUNCTION__, mode); } out: + spin_unlock_irqrestore(&ref_ticker_lock, flags2); spin_unlock_irqrestore(&xbus->lock, flags); } void xbus_request_sync(xbus_t *xbus, enum sync_mode mode) { + unsigned long flags; + BUG_ON(!xbus); XBUS_DBG(SYNC, xbus, "sent request (mode=%d)\n", mode); CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, mode, 0); if(mode == SYNC_MODE_NONE) { + /* + * We must deselect the syncer *now* and not wait for the + * reply from the AB. Otherwise, a disconnect of the syncing + * AB would result in a corrupted 'syncer'. + */ + spin_lock_irqsave(&ref_ticker_lock, flags); + xpp_set_syncer(xbus, 0); + spin_unlock_irqrestore(&ref_ticker_lock, flags); + /* + * We must activate timer now since the commands go to + * the command queue, and we should maintain something to + * "tick" meanwhile until the AB get these commands and + * start being "self_ticking". + */ xbus_set_command_timer(xbus, 1); } } @@ -559,6 +578,7 @@ static void update_sync_master(xbus_t *new_syncer, bool force_dahdi) force_dahdi_sync = 0; ref_ticker = &new_syncer->ticker; xbus_drift_clear(new_syncer); /* Clean new data */ + xpp_set_syncer(new_syncer, 1); xbus_request_sync(new_syncer, SYNC_MODE_AB); } else if(force_dahdi_sync) { ref_ticker = &dahdi_ticker; @@ -574,7 +594,8 @@ static void update_sync_master(xbus_t *new_syncer, bool force_dahdi) continue; if(XBUS_FLAGS(xbus, CONNECTED) && xbus != new_syncer) { if(xbus->self_ticking) - xbus_request_sync(xbus, SYNC_MODE_PLL); + xbus_request_sync(xbus, + xbus->sync_mode_default); else XBUS_DBG(SYNC, xbus, "Not self_ticking yet. Ignore\n"); } @@ -588,7 +609,9 @@ void elect_syncer(const char *msg) uint timing_priority = INT_MAX; xpd_t *best_xpd = NULL; xbus_t *the_xbus = NULL; + unsigned long flags; + spin_lock_irqsave(&elect_syncer_lock, flags); for(i = 0; i < MAX_BUSES; i++) { xbus_t *xbus = xbus_num(i); if(!xbus) @@ -598,11 +621,19 @@ void elect_syncer(const char *msg) the_xbus = xbus; /* First candidate */ for(j = 0; j < MAX_XPDS; j++) { xpd_t *xpd = xpd_of(xbus, j); + int prio; if(!xpd || !xpd->card_present) continue; - if(xpd->timing_priority > 0 && xpd->timing_priority < timing_priority) { - timing_priority = xpd->timing_priority; + prio = CALL_XMETHOD(card_timing_priority, + xbus, xpd); + if (prio < 0) { + DBG(SYNC, "%s/%s: skip sync\n", + xbus->busname, xpd->xpdname); + continue; + } + if (prio > 0 && prio < timing_priority) { + timing_priority = prio; best_xpd = xpd; } } @@ -614,12 +645,17 @@ void elect_syncer(const char *msg) } else if(the_xbus) { XBUS_DBG(SYNC, the_xbus, "%s: elected\n", msg); } else { + unsigned long flags; + DBG(SYNC, "%s: No more syncers\n", msg); + spin_lock_irqsave(&ref_ticker_lock, flags); xpp_set_syncer(NULL, 0); + spin_unlock_irqrestore(&ref_ticker_lock, flags); the_xbus = NULL; } if(the_xbus != syncer) update_sync_master(the_xbus, force_dahdi_sync); + spin_unlock_irqrestore(&elect_syncer_lock, flags); } /* @@ -962,6 +998,11 @@ out: return ret; } +int generic_timing_priority(xbus_t *xbus, xpd_t *xpd) +{ + return xpd->timing_priority; +} + static void xbus_tick(xbus_t *xbus) { int i; @@ -1290,6 +1331,7 @@ EXPORT_SYMBOL(update_wanted_pcm_mask); EXPORT_SYMBOL(generic_card_pcm_recompute); EXPORT_SYMBOL(generic_card_pcm_tospan); EXPORT_SYMBOL(generic_card_pcm_fromspan); +EXPORT_SYMBOL(generic_timing_priority); #ifdef DEBUG_PCMTX EXPORT_SYMBOL(pcmtx); EXPORT_SYMBOL(pcmtx_chan); diff --git a/drivers/dahdi/xpp/xbus-pcm.h b/drivers/dahdi/xpp/xbus-pcm.h index 3b91489..37a1ce4 100644 --- a/drivers/dahdi/xpp/xbus-pcm.h +++ b/drivers/dahdi/xpp/xbus-pcm.h @@ -108,6 +108,7 @@ void update_wanted_pcm_mask(xpd_t *xpd, xpp_line_t new_mask, uint new_pcm_len); void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask); void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); +int generic_timing_priority(xbus_t *xbus, xpd_t *xpd); void fill_beep(u_char *buf, int num, int duration); const char *sync_mode_name(enum sync_mode mode); void xbus_set_command_timer(xbus_t *xbus, bool on); diff --git a/drivers/dahdi/xpp/xpp_dahdi.c b/drivers/dahdi/xpp/xpp_dahdi.c index 07041fc..cc92710 100644 --- a/drivers/dahdi/xpp/xpp_dahdi.c +++ b/drivers/dahdi/xpp/xpp_dahdi.c @@ -130,7 +130,7 @@ static void xpd_destroy(struct kref *kref) xpd_t *xpd; xpd = kref_to_xpd(kref); - XPD_NOTICE(xpd, "%s\n", __func__); + XPD_DBG(DEVICES, xpd, "%s\n", __func__); xpd_device_unregister(xpd); } diff --git a/drivers/dahdi/xpp/xproto.h b/drivers/dahdi/xpp/xproto.h index efa5e88..765cc68 100644 --- a/drivers/dahdi/xpp/xproto.h +++ b/drivers/dahdi/xpp/xproto.h @@ -226,6 +226,7 @@ struct xops { void (*card_pcm_recompute)(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask); void (*card_pcm_fromspan)(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); void (*card_pcm_tospan)(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack); + int (*card_timing_priority)(xbus_t *xbus, xpd_t *xpd); int (*card_dahdi_preregistration)(xpd_t *xpd, bool on); int (*card_dahdi_postregistration)(xpd_t *xpd, bool on); int (*card_hooksig)(xbus_t *xbus, xpd_t *xpd, int pos, enum dahdi_txsig txsig); |