diff options
Diffstat (limited to 'xpp/xpp_zap.c')
-rw-r--r-- | xpp/xpp_zap.c | 137 |
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>"); |