summaryrefslogtreecommitdiff
path: root/drivers/dahdi/xpp/xbus-pcm.c
diff options
context:
space:
mode:
authorTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-01-18 09:55:48 +0000
committerTzafrir Cohen <tzafrir.cohen@xorcom.com>2009-01-18 09:55:48 +0000
commitf89c302cbde0ea699009df9e5286be5001f16c20 (patch)
tree41fa4bf87faacf1979e54ac579c5dcc65e1c62aa /drivers/dahdi/xpp/xbus-pcm.c
parent7d1e606f63ae5ce4c4932f3d65e18adf519b9aee (diff)
xpp.r6616: More sysfs migration, FXO enhancements, BRI fixes
* Fix cases where the command_queue overflowed during initialization. * More migrations to sysfs: - Add a 'transport' attribute to our astribank devices which points to the usb device we use. E.g: /sys/bus/astribanks/devices/xbus-00/transport is symlinked to ../../../../../../devices/pci0000:00/0000:00:10.4/usb5/5-4 - Move /proc/xpp/XBUS-??/XPD-??/span to /sys/bus/xpds/devices/??:?:?/span - Migrate from /proc/xpp/sync to: /sys/bus/astribanks/drivers/xppdrv/sync * PRI: change the "timing" priority to match the convention used by other PRI cards -- I.e: lower numbers (not 0) have higher priority. * FXO: - Power denial: create two module parameters instead of hard-coded constants (power_denial_safezone, power_denial_minlen). For sites that get non-standard power-denial signals from central office on offhook. - Don't hangup on power-denial, just notify Dahdi and wait for - Fix caller-id detection for the case central office sends it before first ring without any indication before. Asterisk's desicion. git-svn-id: http://svn.asterisk.org/svn/dahdi/linux/trunk@5663 a0bf4364-ded3-4de4-8d8a-66a801d63aff
Diffstat (limited to 'drivers/dahdi/xpp/xbus-pcm.c')
-rw-r--r--drivers/dahdi/xpp/xbus-pcm.c235
1 files changed, 116 insertions, 119 deletions
diff --git a/drivers/dahdi/xpp/xbus-pcm.c b/drivers/dahdi/xpp/xbus-pcm.c
index 9e6ce8d..d89991d 100644
--- a/drivers/dahdi/xpp/xbus-pcm.c
+++ b/drivers/dahdi/xpp/xbus-pcm.c
@@ -56,7 +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 bool force_dahdi_sync = 0; /* from "/proc/xpp/sync" */
+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;
@@ -170,9 +170,12 @@ static void xpp_drift_step(xbus_t *xbus, const struct timeval *tv)
driftinfo->delta_tick = new_delta_tick;
if(lost_ticks) {
+ static int rate_limit;
+
driftinfo->lost_ticks++;
driftinfo->lost_tick_count += abs(lost_ticks);
- if(printk_ratelimit()) {
+
+ if((rate_limit++ % 1003) == 0) {
XBUS_DBG(SYNC, xbus, "Lost %d tick%s\n",
lost_ticks,
(abs(lost_ticks) > 1) ? "s": "");
@@ -445,14 +448,8 @@ int dahdi_sync_tick(struct dahdi_span *span, int is_master)
if(is_master) {
static int rate_limit;
- if(xpd->xbus != syncer && ((rate_limit % 1003) == 0)) {
- XPD_ERR(xpd,
- "Dahdi master, but syncer=%s\n",
- xpd->xbus->busname);
- }
- if((rate_limit % 5003) == 0)
- XPD_NOTICE(xpd, "Dahdi master: ignore DAHDI sync\n");
- rate_limit++;
+ if((rate_limit++ % 1003) == 0)
+ XPD_NOTICE(xpd, "Is a DAHDI sync master: ignore sync from DAHDI\n");
goto noop;
}
/* Now we know for sure someone else is dahdi sync master */
@@ -461,7 +458,7 @@ int dahdi_sync_tick(struct dahdi_span *span, int is_master)
if((rate_limit++ % 5003) == 0)
XBUS_DBG(SYNC, syncer,
- "Already a syncer, ignore DAHDI sync\n");
+ "is a SYNCer: ignore sync from DAHDI\n");
goto noop;
}
/* ignore duplicate calls from all our registered spans */
@@ -488,12 +485,15 @@ noop:
* if new_syncer is NULL, than we move all to SYNC_MODE_PLL
* for DAHDI sync.
*/
-static void update_sync_master(xbus_t *new_syncer)
+static void update_sync_master(xbus_t *new_syncer, bool force_dahdi)
{
- const char *msg = (force_dahdi_sync) ? "DAHDI" : "NO-SYNC";
+ const char *msg;
int i;
unsigned long flags;
+ WARN_ON(new_syncer && force_dahdi); /* Ambigous */
+ force_dahdi_sync = force_dahdi;
+ msg = (force_dahdi_sync) ? "DAHDI" : "NO-SYNC";
DBG(SYNC, "%s => %s\n",
(syncer) ? syncer->busname : msg,
(new_syncer) ? new_syncer->busname : msg);
@@ -545,9 +545,9 @@ void elect_syncer(const char *msg)
xbus_t *xbus = xbus_num(i);
if(!xbus)
continue;
- if(!the_xbus)
- the_xbus = xbus;
if(XBUS_IS(xbus, READY)) {
+ if(!the_xbus)
+ the_xbus = xbus; /* First candidate */
for(j = 0; j < MAX_XPDS; j++) {
xpd_t *xpd = xpd_of(xbus, j);
@@ -568,26 +568,25 @@ void elect_syncer(const char *msg)
} else
DBG(SYNC, "%s: No more syncers\n", msg);
if(the_xbus != syncer)
- update_sync_master(the_xbus);
+ update_sync_master(the_xbus, force_dahdi_sync);
}
/*
* This function is used by FXS/FXO. The pcm_mask argument signifies
* channels which should be *added* to the automatic calculation.
* Normally, this argument is 0.
- *
- * The caller should spinlock the XPD before calling it.
*/
-void __pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
+void generic_card_pcm_recompute(xbus_t *xbus, xpd_t *xpd, xpp_line_t pcm_mask)
{
int i;
int line_count = 0;
+ unsigned long flags;
- XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
+ spin_lock_irqsave(&xpd->lock_recompute_pcm, flags);
+ //XPD_DBG(SIGNAL, xpd, "pcm_mask=0x%X\n", pcm_mask);
/* Add/remove all the trivial cases */
- pcm_mask |= xpd->offhook;
- pcm_mask |= xpd->cid_on;
- pcm_mask &= ~xpd->digital_signalling; /* No PCM in D-Channels */
+ pcm_mask |= xpd->offhook_state;
+ pcm_mask |= xpd->oht_pcm_pass;
pcm_mask &= ~xpd->digital_inputs;
pcm_mask &= ~xpd->digital_outputs;
for_each_line(xpd, i)
@@ -605,18 +604,9 @@ void __pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
? RPACKET_HEADERSIZE + sizeof(xpp_line_t) + line_count * DAHDI_CHUNKSIZE
: 0L;
xpd->wanted_pcm_mask = pcm_mask;
-}
-
-/*
- * A spinlocked version of __pcm_recompute()
- */
-void pcm_recompute(xpd_t *xpd, xpp_line_t pcm_mask)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&xpd->lock, flags);
- __pcm_recompute(xpd, pcm_mask);
- spin_unlock_irqrestore(&xpd->lock, flags);
+ XPD_DBG(SIGNAL, xpd, "pcm_len=%d wanted_pcm_mask=0x%X\n",
+ xpd->pcm_len, xpd->wanted_pcm_mask);
+ spin_unlock_irqrestore(&xpd->lock_recompute_pcm, flags);
}
void fill_beep(u_char *buf, int num, int duration)
@@ -647,17 +637,18 @@ void fill_beep(u_char *buf, int num, int duration)
static void do_ec(xpd_t *xpd)
{
- struct dahdi_chan **chans = xpd->span.chans;
- int i;
+ int i;
for (i = 0;i < xpd->span.channels; i++) {
+ struct dahdi_chan *chan = XPD_CHAN(xpd, i);
+
if(unlikely(IS_SET(xpd->digital_signalling, i))) /* Don't echo cancel BRI D-chans */
continue;
if(!IS_SET(xpd->wanted_pcm_mask, i)) /* No ec for unwanted PCM */
continue;
- dahdi_ec_chunk(chans[i], chans[i]->readchunk, xpd->ec_chunk2[i]);
+ dahdi_ec_chunk(chan, chan->readchunk, xpd->ec_chunk2[i]);
memcpy(xpd->ec_chunk2[i], xpd->ec_chunk1[i], DAHDI_CHUNKSIZE);
- memcpy(xpd->ec_chunk1[i], chans[i]->writechunk, DAHDI_CHUNKSIZE);
+ memcpy(xpd->ec_chunk1[i], chan->writechunk, DAHDI_CHUNKSIZE);
}
}
@@ -761,31 +752,33 @@ dropit:
* Generic implementations of card_pcmfromspan()/card_pcmtospan()
* For FXS/FXO
*/
-void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpp_line_t lines, xpacket_t *pack)
+void generic_card_pcm_fromspan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
{
- byte *pcm;
- struct dahdi_chan **chans;
- unsigned long flags;
- int i;
+ byte *pcm;
+ unsigned long flags;
+ xpp_line_t wanted_lines;
+ int i;
BUG_ON(!xbus);
BUG_ON(!xpd);
BUG_ON(!pack);
- RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = lines;
+ wanted_lines = xpd->wanted_pcm_mask;
+ RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, lines) = wanted_lines;
pcm = RPACKET_FIELD(pack, GLOBAL, PCM_WRITE, pcm);
spin_lock_irqsave(&xpd->lock, flags);
- chans = xpd->span.chans;
for (i = 0; i < xpd->channels; i++) {
- if(IS_SET(lines, i)) {
+ struct dahdi_chan *chan = XPD_CHAN(xpd, i);
+
+ if(IS_SET(wanted_lines, i)) {
if(SPAN_REGISTERED(xpd)) {
#ifdef DEBUG_PCMTX
- int channo = xpd->span.chans[i]->channo;
+ int channo = chan->channo;
if(pcmtx >= 0 && pcmtx_chan == channo)
memset((u_char *)pcm, pcmtx, DAHDI_CHUNKSIZE);
else
#endif
- memcpy((u_char *)pcm, chans[i]->writechunk, DAHDI_CHUNKSIZE);
+ memcpy((u_char *)pcm, chan->writechunk, DAHDI_CHUNKSIZE);
} else
memset((u_char *)pcm, 0x7F, DAHDI_CHUNKSIZE);
pcm += DAHDI_CHUNKSIZE;
@@ -814,7 +807,7 @@ void generic_card_pcm_tospan(xbus_t *xbus, xpd_t *xpd, xpacket_t *pack)
if(!SPAN_REGISTERED(xpd))
goto out;
for (i = 0; i < xpd->channels; i++) {
- volatile u_char *r = xpd->span.chans[i]->readchunk;
+ volatile u_char *r = XPD_CHAN(xpd, i)->readchunk;
bool got_data = IS_SET(pcm_mask, i);
if(got_data && !IS_SET(pcm_mute, i)) {
@@ -914,7 +907,6 @@ static void xbus_tick(xbus_t *xbus)
xpd_t *xpd;
xframe_t *xframe = NULL;
xpacket_t *pack = NULL;
- size_t pcm_len;
bool sent_sync_bit = 0;
/*
@@ -930,7 +922,7 @@ static void xbus_tick(xbus_t *xbus)
xmit_mask |= xpd->silence_pcm;
xmit_mask |= xpd->digital_signalling;
for_each_line(xpd, j) {
- xpd->chans[j].chanmute = (optimize_chanmute)
+ XPD_CHAN(xpd, j)->chanmute = (optimize_chanmute)
? !IS_SET(xmit_mask, j)
: 0;
}
@@ -946,6 +938,8 @@ static void xbus_tick(xbus_t *xbus)
* Fill xframes
*/
for(i = 0; i < MAX_XPDS; i++) {
+ size_t pcm_len;
+
if((xpd = xpd_of(xbus, i)) == NULL)
continue;
pcm_len = xpd->pcm_len;
@@ -978,7 +972,7 @@ static void xbus_tick(xbus_t *xbus)
XPACKET_ADDR_SYNC(pack) = 1;
sent_sync_bit = 1;
}
- CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, xpd->wanted_pcm_mask, pack);
+ CALL_XMETHOD(card_pcm_fromspan, xbus, xpd, pack);
XBUS_COUNTER(xbus, TX_PACK_PCM)++;
}
}
@@ -1070,7 +1064,50 @@ void xframe_receive_pcm(xbus_t *xbus, xframe_t *xframe)
xbus->xbus_frag_count++;
}
-#ifdef CONFIG_PROC_FS
+int exec_sync_command(const char *buf, size_t count)
+{
+ int ret = count;
+ int xbusno;
+ xbus_t *xbus;
+
+ if(strncmp("DAHDI", buf, 6) == 0) { /* Ignore the newline */
+ DBG(SYNC, "DAHDI\n");
+ update_sync_master(NULL, 1);
+ } else if(sscanf(buf, "SYNC=%d\n", &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) {
+ DBG(SYNC, "QUERY=%d\n", xbusno);
+ if((xbus = xbus_num(xbusno)) == NULL) {
+ ERR("No bus %d exists\n", xbusno);
+ return -ENXIO;
+ }
+ CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_QUERY, 0);
+ } else {
+ ERR("%s: cannot parse '%s'\n", __FUNCTION__, buf);
+ ret = -EINVAL;
+ }
+ return ret;
+}
+
+int fill_sync_string(char *buf, size_t count)
+{
+ int len = 0;
+
+ if(!syncer) {
+ len += snprintf(buf, count, "%s\n",
+ (force_dahdi_sync) ? "DAHDI" : "NO-SYNC");
+ } else
+ len += snprintf(buf, count, "SYNC=%02d\n", syncer->num);
+ return len;
+}
+
+#ifdef OLD_PROC
+#ifdef CONFIG_PROC_FS
static int proc_sync_read(char *page, char **start, off_t off, int count, int *eof, void *data)
{
int len = 0;
@@ -1079,17 +1116,13 @@ static int proc_sync_read(char *page, char **start, off_t off, int count, int *e
unsigned long usec;
do_gettimeofday(&now);
+ NOTICE("%s: DEPRECATED: %s[%d] read from /proc interface instead of /sys\n",
+ __FUNCTION__, current->comm, current->tgid);
len += sprintf(page + len, "# To modify sync source write into this file:\n");
len += sprintf(page + len, "# DAHDI - Another dahdi device provide sync\n");
len += sprintf(page + len, "# SYNC=nn - XBUS-nn provide sync\n");
len += sprintf(page + len, "# QUERY=nn - Query XBUS-nn for sync information (DEBUG)\n");
- if(!syncer) {
- if(force_dahdi_sync)
- len += sprintf(page + len, "DAHDI\n");
- else
- len += sprintf(page + len, "NO-SYNC\n");
- } else
- len += sprintf(page + len, "SYNC=%02d\n", syncer->num);
+ len += fill_sync_string(page + len, PAGE_SIZE - len);
#ifdef DAHDI_SYNC_TICK
if(force_dahdi_sync) {
len += sprintf(page + len,
@@ -1123,68 +1156,26 @@ static int proc_sync_read(char *page, char **start, off_t off, int count, int *e
static int proc_sync_write(struct file *file, const char __user *buffer, unsigned long count, void *data)
{
char buf[MAX_PROC_WRITE];
- int xbusno;
- int xpd_num;
- xbus_t *xbus;
- xpd_t *xpd;
// DBG(SYNC, "%s: count=%ld\n", __FUNCTION__, count);
+ NOTICE("%s: DEPRECATED: %s[%d] write to /proc interface instead of /sys\n",
+ __FUNCTION__, current->comm, current->tgid);
if(count >= MAX_PROC_WRITE)
return -EINVAL;
if(copy_from_user(buf, buffer, count))
return -EFAULT;
buf[count] = '\0';
- if(strncmp("DAHDI", buf, 5) == 0) {
- DBG(SYNC, "DAHDI\n");
- force_dahdi_sync=1;
- update_sync_master(NULL);
- } 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);
- } 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);
- return -ENXIO;
- }
- CALL_PROTO(GLOBAL, SYNC_SOURCE, xbus, NULL, SYNC_MODE_QUERY, 0);
- } else if(sscanf(buf, "%d %d", &xbusno, &xpd_num) == 2) {
- NOTICE("Using deprecated syntax to update %s file\n",
- PROC_SYNC);
- if(xpd_num != 0) {
- ERR("Currently can only set sync for XPD #0\n");
- return -EINVAL;
- }
- if((xbus = xbus_num(xbusno)) == NULL) {
- ERR("No bus %d exists\n", xbusno);
- return -ENXIO;
- }
- if((xpd = xpd_of(xbus, xpd_num)) == NULL) {
- XBUS_ERR(xbus, "No xpd %d exists\n", xpd_num);
- return -ENXIO;
- }
- update_sync_master(xbus);
- } else {
- ERR("%s: cannot parse '%s'\n", __FUNCTION__, buf);
- count = -EINVAL;
- }
- return count;
+ return exec_sync_command(buf, count);
}
static struct proc_dir_entry *top;
#endif
+#endif /* OLD_PROC */
int xbus_pcm_init(struct proc_dir_entry *toplevel)
{
int ret = 0;
-#ifdef CONFIG_PROC_FS
- struct proc_dir_entry *ent;
-#endif
#ifdef OPTIMIZE_CHANMUTE
INFO("FEATURE: with CHANMUTE optimization (%sactivated)\n",
@@ -1197,27 +1188,34 @@ int xbus_pcm_init(struct proc_dir_entry *toplevel)
#endif
xpp_ticker_init(&global_ticks_series);
xpp_ticker_init(&dahdi_ticker);
-#ifdef CONFIG_PROC_FS
- top = toplevel;
- ent = create_proc_entry(PROC_SYNC, 0644, top);
- if(!ent) {
- ret = -EFAULT;
- goto err;
+#ifdef OLD_PROC
+#ifdef CONFIG_PROC_FS
+ {
+ struct proc_dir_entry *ent;
+
+ top = toplevel;
+ ent = create_proc_entry(PROC_SYNC, 0644, top);
+ if(ent) {
+ ent->read_proc = proc_sync_read;
+ ent->write_proc = proc_sync_write;
+ ent->data = NULL;
+ } else {
+ ret = -EFAULT;
+ }
}
- ent->read_proc = proc_sync_read;
- ent->write_proc = proc_sync_write;
- ent->data = NULL;
#endif
-err:
+#endif /* OLD_PROC */
return ret;
}
void xbus_pcm_shutdown(void)
{
+#ifdef OLD_PROC
#ifdef CONFIG_PROC_FS
DBG(GENERAL, "Removing '%s' from proc\n", PROC_SYNC);
remove_proc_entry(PROC_SYNC, top);
#endif
+#endif /* OLD_PROC */
}
@@ -1227,8 +1225,7 @@ EXPORT_SYMBOL(elect_syncer);
#ifdef DAHDI_SYNC_TICK
EXPORT_SYMBOL(dahdi_sync_tick);
#endif
-EXPORT_SYMBOL(__pcm_recompute);
-EXPORT_SYMBOL(pcm_recompute);
+EXPORT_SYMBOL(generic_card_pcm_recompute);
EXPORT_SYMBOL(generic_card_pcm_tospan);
EXPORT_SYMBOL(generic_card_pcm_fromspan);
#ifdef DEBUG_PCMTX