summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2010-07-13 18:35:20 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2010-07-13 18:35:20 +0000
commitce0d2d4620f49e6ac0ec697733c786369ad8c822 (patch)
treefe0bea6d4a2430fc1302db9564fc61974fcff863 /drivers
parentdfa545814b61b3e1d527e842dd883b153277c4b4 (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')
-rw-r--r--drivers/dahdi/xpp/card_bri.c1
-rw-r--r--drivers/dahdi/xpp/card_fxo.c1
-rw-r--r--drivers/dahdi/xpp/card_fxs.c1
-rw-r--r--drivers/dahdi/xpp/card_pri.c15
-rw-r--r--drivers/dahdi/xpp/xbus-core.c1
-rw-r--r--drivers/dahdi/xpp/xbus-core.h2
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.c62
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.h1
-rw-r--r--drivers/dahdi/xpp/xpp_dahdi.c2
-rw-r--r--drivers/dahdi/xpp/xproto.h1
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);