summaryrefslogtreecommitdiff
path: root/xpp/xpp_zap.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/xpp_zap.c')
-rw-r--r--xpp/xpp_zap.c137
1 files changed, 87 insertions, 50 deletions
diff --git a/xpp/xpp_zap.c b/xpp/xpp_zap.c
index 77f3437..1fc7b37 100644
--- a/xpp/xpp_zap.c
+++ b/xpp/xpp_zap.c
@@ -168,7 +168,7 @@ static void external_sync(xbus_t *the_xbus)
{
int i;
- DBG("%s\n", (the_xbus) ? the_xbus->busname : "HOST");
+ DBG(SYNC, "%s\n", (the_xbus) ? the_xbus->busname : "HOST");
// Shut all down
for(i = 0; i < MAX_BUSES; i++) {
xbus_t *xbus = xbus_of(i);
@@ -185,7 +185,7 @@ static void external_sync(xbus_t *the_xbus)
/*
* Change sync_master. May block. Cannot be called from atomic context
*/
-static void sync_master_is(xbus_t *xbus)
+static void sync_master_is(const char *msg, xbus_t *xbus)
{
xpd_t *xpd = (xbus)? xpd_of(xbus, 0) : NULL;
@@ -193,7 +193,8 @@ static void sync_master_is(xbus_t *xbus)
XBUS_NOTICE(xbus, "Cannot set sync master (has no XPD #0).\n");
xbus = NULL; /* Fallback to HOST */
}
- DBG("SYNC MASTER CHANGING: %s => %s\n",
+ DBG(SYNC, "SYNC MASTER CHANGING(%s): %s => %s\n",
+ msg,
(sync_master) ? sync_master->xbus->busname : "HOST",
(xbus) ? xbus->busname : "HOST");
/* First stop all generators */
@@ -216,6 +217,41 @@ static void sync_master_is(xbus_t *xbus)
}
}
+void elect_syncer(const char *msg)
+{
+ int i;
+ int j;
+ uint timing_priority = 0;
+ xpd_t *best_xpd = NULL;
+
+ for(i = 0; i < MAX_BUSES; i++) {
+ xbus_t *xbus = xbus_of(i);
+ if(!xbus)
+ continue;
+ if (!xbus->hardware_exists)
+ continue;
+ for(j = 0; j < MAX_XPDS; j++) {
+ xpd_t *xpd = xpd_of(xbus, j);
+
+ if(!xpd)
+ continue;
+ if(SPAN_REGISTERED(xpd)) {
+ if(xpd->timing_priority > timing_priority) {
+ timing_priority = xpd->timing_priority;
+ best_xpd = xpd;
+ }
+ }
+ }
+ }
+ if(!best_xpd) {
+ INFO("%s: elected HOST\n", msg);
+ sync_master_is(msg, NULL);
+ } else if(!sync_master || (timing_priority > sync_master->timing_priority)) {
+ XPD_INFO(best_xpd, "%s: elected with priority %d\n", msg, timing_priority);
+ sync_master_is(msg, best_xpd->xbus);
+ }
+}
+
static inline void send_pcm_frame(xbus_t *xbus, xframe_t *xframe)
{
unsigned long flags;
@@ -230,7 +266,7 @@ static inline void send_pcm_frame(xbus_t *xbus, xframe_t *xframe)
sec_diff = now.tv_sec - xbus->last_tx_sync.tv_sec;
usec_diff = sec_diff * 1000000 + (now.tv_usec - xbus->last_tx_sync.tv_usec);
if(unlikely(abs(sec_diff) > 2)) {
- XBUS_DBG(xbus, "PCM TX timing restart (sec_diff=%ld)\n", sec_diff);
+ XBUS_DBG(SYNC, xbus, "PCM TX timing restart (sec_diff=%ld)\n", sec_diff);
xbus->last_tx_sync = now;
goto dropit;
}
@@ -238,7 +274,7 @@ static inline void send_pcm_frame(xbus_t *xbus, xframe_t *xframe)
static int rate_limit;
if((rate_limit++ % 5003) == 0)
- XBUS_DBG(xbus, "Bad PCM TX timing(%d): usec_diff=%ld.\n",
+ XBUS_DBG(SYNC, xbus, "Bad PCM TX timing(%d): usec_diff=%ld.\n",
rate_limit, usec_diff);
}
if(usec_diff > xbus->max_tx_sync)
@@ -435,7 +471,7 @@ void xpp_tick(unsigned long param)
if (!xbus->hardware_exists)
continue;
if(!down_read_trylock(&xbus->in_use)) {
- XBUS_DBG(xbus, "Dropped packet. Is in_use\n");
+ XBUS_DBG(GENERAL, xbus, "Dropped packet. Is in_use\n");
continue;
}
/* Reset sync LEDs once in a while */
@@ -460,7 +496,7 @@ void got_sync_from(xpd_t *xpd)
static int rate_limit;
if((rate_limit++ % 1003) == 0)
- XPD_DBG(xpd, "is not SYNC master. Go away! (%d)\n", rate_limit);
+ XPD_DBG(SYNC, xpd, "is not SYNC master. Go away! (%d)\n", rate_limit);
return;
}
atomic_inc(&missed_ticks);
@@ -488,7 +524,7 @@ static void send_drift(int drift)
msg = "up";
else
msg = "down";
- XBUS_DBG(xbus, "DRIFT adjust %s (%d) (last update %ld seconds ago)\n",
+ XBUS_DBG(SYNC, xbus, "DRIFT adjust %s (%d) (last update %ld seconds ago)\n",
msg, drift, now.tv_sec - xbus->pll_updated_at);
CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_PLL, drift);
xbus->pll_updated_at = now.tv_sec;
@@ -534,7 +570,7 @@ int zaptel_sync_tick(struct zt_span *span, int is_master)
static int rate_limit;
if((rate_limit++ % 1003) == 0)
- DBG("Big lag of Xpp ticks relative to zaptel ticks: %ld\n", usec_lag_curr);
+ DBG(SYNC, "Big lag of Xpp ticks relative to zaptel ticks: %ld\n", usec_lag_curr);
}
sigma_lag += usec_lag_curr;
if((zaptel_tick_count % SYNC_ADJ_INTERVAL) == 0) {
@@ -569,25 +605,25 @@ static void xpd_free(xpd_t *xpd)
xbus = xpd->xbus;
if(!xbus)
return;
- XPD_DBG(xpd, "\n");
+ XPD_DBG(GENERAL, xpd, "\n");
#ifdef CONFIG_PROC_FS
if(xpd->proc_xpd_dir) {
if(xpd->proc_xpd_summary) {
- XPD_DBG(xpd, "Removing proc '%s'\n", PROC_XPD_SUMMARY);
+ XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_SUMMARY);
remove_proc_entry(PROC_XPD_SUMMARY, xpd->proc_xpd_dir);
xpd->proc_xpd_summary = NULL;
}
if(xpd->proc_xpd_ztregister) {
- XPD_DBG(xpd, "Removing proc '%s'\n", PROC_XPD_ZTREGISTER);
+ XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_ZTREGISTER);
remove_proc_entry(PROC_XPD_ZTREGISTER, xpd->proc_xpd_dir);
xpd->proc_xpd_ztregister = NULL;
}
if(xpd->proc_xpd_blink) {
- XPD_DBG(xpd, "Removing proc '%s'\n", PROC_XPD_BLINK);
+ XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_BLINK);
remove_proc_entry(PROC_XPD_BLINK, xpd->proc_xpd_dir);
xpd->proc_xpd_blink = NULL;
}
- XPD_DBG(xpd, "Removing proc directory\n");
+ XPD_DBG(PROC, xpd, "Removing proc directory\n");
remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir);
xpd->proc_xpd_dir = NULL;
}
@@ -687,7 +723,7 @@ void card_detected(struct card_desc_struct *card_desc)
if(!xpd) {
XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n",
unit, subunit, proto_table->type, subtype, rev);
- xproto_put(xpd->xproto);
+ xproto_put(proto_table);
goto err;
}
xpd->addr = card_desc->xpd_addr;
@@ -707,7 +743,7 @@ void card_detected(struct card_desc_struct *card_desc)
}
xbus_register_xpd(xbus, xpd);
#ifdef CONFIG_PROC_FS
- XPD_DBG(xpd, "Creating proc directory\n");
+ XPD_DBG(PROC, xpd, "Creating proc directory\n");
xpd->proc_xpd_dir = proc_mkdir(xpd->xpdname, xbus->proc_xbus_dir);
if(!xpd->proc_xpd_dir) {
XPD_ERR(xpd, "Failed to create proc directory\n");
@@ -904,7 +940,7 @@ xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channel
size_t alloc_size = sizeof(xpd_t) + privsize;
int type = proto_table->type;
- DBG("type=%d channels=%d\n", type, channels);
+ DBG(GENERAL, "type=%d channels=%d\n", type, channels);
if(channels > CHANNELS_PERXPD) {
ERR("%s: type=%d: too many channels %d\n",
__FUNCTION__, type, channels);
@@ -973,11 +1009,13 @@ void xpd_disconnect(xpd_t *xpd)
BUG_ON(!xpd);
// TODO: elect a new sync master
- if(sync_master == xpd)
- sync_master_is(NULL);
+ if(sync_master == xpd) {
+ sync_master_is("DISCONNECT", NULL);
+ elect_syncer("DISCONNECT");
+ }
spin_lock_irqsave(&xpd->lock, flags);
- XPD_DBG(xpd, "(%p)\n", xpd->xproto);
+ XPD_DBG(GENERAL, xpd, "(%p)\n", xpd->xproto);
if(!xpd->card_present) /* Multiple reports */
goto out;
xpd->card_present = 0;
@@ -986,7 +1024,7 @@ void xpd_disconnect(xpd_t *xpd)
update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
/* TODO: Should this be done before releasing the spinlock? */
- XPD_DBG(xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n");
+ XPD_DBG(GENERAL, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n");
for (i=0; i<xpd->span.channels; i++)
zt_qevent_lock(&xpd->chans[i],ZT_EVENT_REMOVED);
}
@@ -1026,7 +1064,7 @@ void update_xpd_status(xpd_t *xpd, int alarm_flag)
return;
span->alarms = alarm_flag;
zt_alarm_notify(span);
- XPD_DBG(xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag);
+ XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag);
}
void update_line_status(xpd_t *xpd, int pos, bool to_offhook)
@@ -1047,7 +1085,7 @@ void update_line_status(xpd_t *xpd, int pos, bool to_offhook)
* it may call back into our xpp_hooksig() and cause
* a nested spinlock scenario
*/
- LINE_DBG(xpd, pos, "rxsig=%s\n", (rxsig == ZT_RXSIG_ONHOOK) ? "ONHOOK" : "OFFHOOK");
+ LINE_DBG(GENERAL, xpd, pos, "rxsig=%s\n", (rxsig == ZT_RXSIG_ONHOOK) ? "ONHOOK" : "OFFHOOK");
if(SPAN_REGISTERED(xpd))
zt_hooksig(&xpd->chans[pos], rxsig);
}
@@ -1130,23 +1168,23 @@ static int proc_sync_write(struct file *file, const char __user *buffer, unsigne
int xpd_num;
xbus_t *xbus;
- // DBG("%s: count=%ld\n", __FUNCTION__, count);
+ // DBG(SYNC, "%s: count=%ld\n", __FUNCTION__, count);
if(count >= MAX_PROC_WRITE)
return -EINVAL;
if(copy_from_user(buf, buffer, count))
return -EFAULT;
buf[count] = '\0';
if(strncmp("HOST", buf, 4) == 0) {
- sync_master_is(NULL);
+ sync_master_is("PROC", NULL);
} else if(sscanf(buf, "SYNC=%d", &xbus_num) == 1) {
- DBG("SYNC=%d\n", xbus_num);
+ DBG(SYNC, "SYNC=%d\n", xbus_num);
if((xbus = xbus_of(xbus_num)) == NULL) {
ERR("No bus %d exists\n", xbus_num);
return -ENXIO;
}
- sync_master_is(xbus);
+ sync_master_is("PROC", xbus);
} else if(sscanf(buf, "QUERY=%d", &xbus_num) == 1) {
- DBG("QUERY=%d\n", xbus_num);
+ DBG(SYNC, "QUERY=%d\n", xbus_num);
if((xbus = xbus_of(xbus_num)) == NULL) {
ERR("No bus %d exists\n", xbus_num);
return -ENXIO;
@@ -1163,7 +1201,7 @@ static int proc_sync_write(struct file *file, const char __user *buffer, unsigne
ERR("No bus %d exists\n", xbus_num);
return -ENXIO;
}
- sync_master_is(xbus);
+ sync_master_is("PROC", xbus);
} else {
ERR("%s: cannot parse '%s'\n", __FUNCTION__, buf);
count = -EINVAL;
@@ -1209,7 +1247,7 @@ static int proc_xpd_ztregister_write(struct file *file, const char __user *buffe
ret = sscanf(buf, "%d", &zt_reg);
if(ret != 1)
return -EINVAL;
- XPD_DBG(xpd, "%s\n", (zt_reg) ? "register" : "unregister");
+ XPD_DBG(GENERAL, xpd, "%s\n", (zt_reg) ? "register" : "unregister");
if(zt_reg)
ret = zaptel_register_xpd(xpd);
else
@@ -1255,7 +1293,7 @@ static int proc_xpd_blink_write(struct file *file, const char __user *buffer, un
ret = sscanf(buf, "%d", &blink);
if(ret != 1)
return -EINVAL;
- XPD_DBG(xpd, "%s\n", (blink) ? "blink" : "unblink");
+ XPD_DBG(GENERAL, xpd, "%s\n", (blink) ? "blink" : "unblink");
xpd->blink_mode = blink;
return count;
}
@@ -1377,7 +1415,7 @@ static void xpp_receiveprep(xpd_t *xpd)
spin_lock_irqsave(&xpd->lock, flags);
// if((xpd->timer_count % 1000) == 0)
- // XPD_DBG(xpd, "%d\n", xpd->timer_count);
+ // XPD_DBG(GENERAL, xpd, "%d\n", xpd->timer_count);
if (xpd->timer_count & 1) {
/* First part */
@@ -1426,7 +1464,7 @@ int xpp_open(struct zt_chan *chan)
atomic_inc(&xpd->open_counter);
if(IS_SET(xpd->digital_signalling, pos)) /* D-chan offhook */
BIT_SET(xpd->offhook, pos);
- DBG("chan=%d (open_counter=%d)\n", pos, xbus->open_counter);
+ DBG(GENERAL, "chan=%d (open_counter=%d)\n", pos, xbus->open_counter);
spin_unlock_irqrestore(&xbus->lock, flags);
if(xpd->xops->card_open)
xpd->xops->card_open(xpd, pos);
@@ -1451,9 +1489,9 @@ int xpp_close(struct zt_chan *chan)
spin_unlock_irqrestore(&xbus->lock, flags);
if(xpd->xops->card_close)
xpd->xops->card_close(xpd, pos);
- DBG("chan=%d (open_counter=%d, should_remove=%d)\n", pos, xbus->open_counter, should_remove);
+ DBG(GENERAL, "chan=%d (open_counter=%d, should_remove=%d)\n", pos, xbus->open_counter, should_remove);
if(should_remove) {
- XBUS_DBG(xbus, "Going to remove\n");
+ XBUS_DBG(GENERAL, xbus, "Going to remove\n");
xbus_remove(xbus);
}
return 0;
@@ -1473,11 +1511,11 @@ int xpp_ioctl(struct zt_chan *chan, unsigned int cmd, unsigned long arg)
if (ret != -ENOTTY)
return ret;
}
- DBG("ENOTTY: chan=%d cmd=0x%x\n", pos, cmd);
- DBG(" IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd));
- DBG(" IOC_DIR=0x%02X\n", _IOC_DIR(cmd));
- DBG(" IOC_NR=0x%02X\n", _IOC_NR(cmd));
- DBG(" IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd));
+ DBG(GENERAL, "ENOTTY: chan=%d cmd=0x%x\n", pos, cmd);
+ DBG(GENERAL, " IOC_TYPE=0x%02X\n", _IOC_TYPE(cmd));
+ DBG(GENERAL, " IOC_DIR=0x%02X\n", _IOC_DIR(cmd));
+ DBG(GENERAL, " IOC_NR=0x%02X\n", _IOC_NR(cmd));
+ DBG(GENERAL, " IOC_SIZE=0x%02X\n", _IOC_SIZE(cmd));
return -ENOTTY;
}
return 0;
@@ -1492,7 +1530,7 @@ static int xpp_hooksig(struct zt_chan *chan, zt_txsig_t txsig)
BUG_ON(!xpd);
xbus = xpd->xbus;
BUG_ON(!xbus);
- DBG("Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
+ DBG(GENERAL, "Setting %s to %s (%d)\n", chan->name, txsig2str(txsig), txsig);
return CALL_XMETHOD(card_hooksig, xbus, xpd, pos, txsig);
}
@@ -1510,7 +1548,7 @@ int xpp_maint(struct zt_span *span, int cmd)
#endif
BUG_ON(!xpd);
- DBG("span->mainttimer=%d\n", span->mainttimer);
+ DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer);
switch(cmd) {
case ZT_MAINT_NONE:
printk("XXX Turn off local and remote loops XXX\n");
@@ -1596,7 +1634,7 @@ static int xpp_watchdog(struct zt_span *span, int cause)
static int rate_limit = 0;
if((rate_limit++ % 1000) == 0)
- DBG("\n");
+ DBG(GENERAL, "\n");
return 0;
}
#endif
@@ -1624,8 +1662,6 @@ static int zaptel_unregister_xpd(xpd_t *xpd)
spin_unlock_irqrestore(&xpd->lock, flags);
return -EIDRM;
}
- if(sync_master == xpd)
- sync_master_is(NULL); // FIXME: it's better to elect a new prince
update_xpd_status(xpd, ZT_ALARM_NOTOPEN);
if(atomic_read(&xpd->open_counter)) {
XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&xpd->open_counter));
@@ -1662,7 +1698,7 @@ static int zaptel_register_xpd(xpd_t *xpd)
return -EEXIST;
}
cn = xpd->channels;
- XPD_DBG(xpd, "Initializing span: %d channels.\n", cn);
+ XPD_DBG(GENERAL, xpd, "Initializing span: %d channels.\n", cn);
memset(xpd->chans, 0, sizeof(struct zt_chan)*cn);
memset(&xpd->span, 0, sizeof(struct zt_span));
@@ -1691,7 +1727,7 @@ static int zaptel_register_xpd(xpd_t *xpd)
snprintf(xpd->span.desc, MAX_SPANDESC, "Xorcom XPD #%02d/%1d%1d: %s",
xbus->num, xpd->addr.unit, xpd->addr.subunit, xpd->type_name);
- XPD_DBG(xpd, "Registering span '%s'\n", xpd->span.desc);
+ XPD_DBG(GENERAL, xpd, "Registering span '%s'\n", xpd->span.desc);
xpd->xops->card_zaptel_preregistration(xpd, 1);
if(zt_register(&xpd->span, prefmaster)) {
XPD_ERR(xpd, "Failed to zt_register span\n");
@@ -1743,10 +1779,10 @@ static void do_cleanup(void)
del_timer_sync(&xpp_timer);
tasklet_kill(&tasklet_tick);
#ifdef CONFIG_PROC_FS
- DBG("Removing '%s' from proc\n", PROC_SYNC);
+ DBG(GENERAL, "Removing '%s' from proc\n", PROC_SYNC);
remove_proc_entry(PROC_SYNC, xpp_proc_toplevel);
if(xpp_proc_toplevel) {
- DBG("Removing '%s' from proc\n", PROC_DIR);
+ DBG(GENERAL, "Removing '%s' from proc\n", PROC_DIR);
remove_proc_entry(PROC_DIR, NULL);
xpp_proc_toplevel = NULL;
}
@@ -1806,7 +1842,7 @@ int __init xpp_zap_init(void)
/* Only timer init. We add it only *after* zt_register */
init_timer(&xpp_timer);
- sync_master_is(NULL); /* Internal ticking */
+ sync_master_is("INIT", NULL); /* Internal ticking */
return 0;
err:
do_cleanup();
@@ -1833,6 +1869,7 @@ EXPORT_SYMBOL(xpp_open);
EXPORT_SYMBOL(xpp_close);
EXPORT_SYMBOL(xpp_ioctl);
EXPORT_SYMBOL(xpp_maint);
+EXPORT_SYMBOL(elect_syncer);
MODULE_DESCRIPTION("XPP Zaptel Driver");
MODULE_AUTHOR("Oron Peled <oron@actcom.co.il>");