From d8562c778088ff6ab3383df5ceead41eff4bf124 Mon Sep 17 00:00:00 2001 From: tzafrir Date: Thu, 19 Mar 2009 20:08:29 +0000 Subject: xpp: a massive backport from DAHDI. From Xorcom branch-rel-6839-r6908 . Sun Mar 1 2009 Oron Peled - xpp.r6795 * Fix cases where the command_queue overflowed during initialization. - Also add a 'command_queue_length' parameter to xpp.ko * 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 - New 'offhook' attribute in: /sys/bus/xpds/devices/??:?:?/offhook * 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. Mon, Dec 8 2008 Oron Peled - xpp.r6430 * PRI: - Match our span clocking priorities (in system.conf) to Digium -- this is a reversal of the previous state. Now lower numbers (greater than 0) are better. - Synchronization fixes for PRI ports other than 0. - Fix T1 CRC for some countries (e.g: China). * FXS: fix bug in VMWI detection if using old asterisk which does not provide ZT_VMWI ioctl(). * FXO: - Improve caller_id_style module parameter. This provide a workaround for countries that send this information without any notification (reverse polarity, ring, etc.) - Don't force on-hook upon power-denial. So, loopstart devices would ignore these as expected. * Implement a flow-control to prevent user space (init_card_* scripts) from pressuring our command queue. git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4631 5390a7c7-147a-4af0-8ec9-7488f05a26cb --- kernel/xpp/xpp_zap.c | 314 ++++++++++++++++++++++++++++++++++----------------- 1 file changed, 208 insertions(+), 106 deletions(-) (limited to 'kernel/xpp/xpp_zap.c') diff --git a/kernel/xpp/xpp_zap.c b/kernel/xpp/xpp_zap.c index b1a1bbe..9e39b01 100644 --- a/kernel/xpp/xpp_zap.c +++ b/kernel/xpp/xpp_zap.c @@ -49,8 +49,10 @@ static const char rcsid[] = "$Id$"; #ifdef CONFIG_PROC_FS struct proc_dir_entry *xpp_proc_toplevel = NULL; #define PROC_DIR "xpp" +#ifdef OLD_PROC #define PROC_XPD_ZTREGISTER "zt_registration" #define PROC_XPD_BLINK "blink" +#endif #define PROC_XPD_SUMMARY "summary" #endif @@ -107,26 +109,53 @@ int total_registered_spans(void) return atomic_read(&num_registered_spans); } -static int zaptel_register_xpd(xpd_t *xpd); -static int zaptel_unregister_xpd(xpd_t *xpd); static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); +#ifdef OLD_PROC static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data); static int proc_xpd_ztregister_write(struct file *file, const char __user *buffer, unsigned long count, void *data); static int proc_xpd_blink_read(char *page, char **start, off_t off, int count, int *eof, void *data); static int proc_xpd_blink_write(struct file *file, const char __user *buffer, unsigned long count, void *data); +#endif /*------------------------- XPD Management -------------------------*/ +static atomic_t *refcount_xpd(xpd_t *xpd) +{ + struct kref *kref = &xpd->xpd_dev.kobj.kref; + + return &kref->refcount; +} + +xpd_t *get_xpd(const char *msg, xpd_t *xpd) +{ + struct device *dev; + + XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", + msg, atomic_read(refcount_xpd(xpd))); + dev = get_device(&xpd->xpd_dev); + return dev_to_xpd(dev); +} + +void put_xpd(const char *msg, xpd_t *xpd) +{ + XPD_DBG(DEVICES, xpd, "%s: refcount_xpd=%d\n", + msg, atomic_read(refcount_xpd(xpd))); + put_device(&xpd->xpd_dev); +} + static void xpd_proc_remove(xbus_t *xbus, xpd_t *xpd) { #ifdef CONFIG_PROC_FS if(xpd->proc_xpd_dir) { +#ifdef OLD_PROC chip_proc_remove(xbus, xpd); +#endif if(xpd->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; } +#ifdef OLD_PROC if(xpd->proc_xpd_ztregister) { XPD_DBG(PROC, xpd, "Removing proc '%s'\n", PROC_XPD_ZTREGISTER); remove_proc_entry(PROC_XPD_ZTREGISTER, xpd->proc_xpd_dir); @@ -137,6 +166,7 @@ static void xpd_proc_remove(xbus_t *xbus, xpd_t *xpd) remove_proc_entry(PROC_XPD_BLINK, xpd->proc_xpd_dir); xpd->proc_xpd_blink = NULL; } +#endif XPD_DBG(PROC, xpd, "Removing %s/%s proc directory\n", xbus->busname, xpd->xpdname); remove_proc_entry(xpd->xpdname, xbus->proc_xbus_dir); @@ -161,6 +191,7 @@ static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd) goto err; } xpd->proc_xpd_summary->owner = THIS_MODULE; +#ifdef OLD_PROC xpd->proc_xpd_ztregister = create_proc_entry(PROC_XPD_ZTREGISTER, 0644, xpd->proc_xpd_dir); if (!xpd->proc_xpd_ztregister) { XPD_ERR(xpd, "Failed to create proc file '%s'\n", PROC_XPD_ZTREGISTER); @@ -181,6 +212,7 @@ static int xpd_proc_create(xbus_t *xbus, xpd_t *xpd) xpd->proc_xpd_blink->write_proc = proc_xpd_blink_write; if(chip_proc_create(xbus, xpd) < 0) goto err; +#endif #endif return 0; err: @@ -202,40 +234,17 @@ void xpd_free(xpd_t *xpd) return; XPD_DBG(DEVICES, xpd, "\n"); xpd_proc_remove(xbus, xpd); - xbus_unregister_xpd(xbus, xpd); + xbus_xpd_unbind(xbus, xpd); + if (xpd->chans) + KZFREE(xpd->chans); KZFREE(xpd); -} - - -__must_check int xpd_common_init(xbus_t *xbus, xpd_t *xpd, int unit, int subunit, int subtype, int subunits) -{ - int ret; - - MKADDR(&xpd->addr, unit, subunit); - xpd->xbus_idx = XPD_IDX(unit,subunit); - snprintf(xpd->xpdname, XPD_NAMELEN, "XPD-%1d%1d", unit, subunit); - xpd->subtype = subtype; - xpd->subunits = subunits; - xpd->offhook_state = 0; - - /* For USB-1 disable some channels */ - if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) { - xpp_line_t no_pcm; - - no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs; - xpd->no_pcm = no_pcm; - XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n", - MAX_SEND_SIZE(xbus), xpd->no_pcm); - } - if((ret = xpd_proc_create(xbus, xpd)) < 0) - return ret; - xbus_register_xpd(xbus, xpd); - return 0; + DBG(DEVICES, "refcount_xbus=%d\n", refcount_xbus(xbus)); + put_xbus(__FUNCTION__, xbus); /* was taken in xpd_alloc() */ } /* * Synchronous part of XPD detection. - * Called from xbus_poll() + * Called from new_card() */ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, int unit, @@ -247,7 +256,6 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, { xpd_t *xpd = NULL; bool to_phone; - int ret = -EINVAL; BUG_ON(type == XPD_TYPE_NOMODULE); to_phone = BIT(subunit) & port_dir; @@ -256,20 +264,15 @@ int create_xpd(xbus_t *xbus, const xproto_table_t *proto_table, if(xpd) { XPD_NOTICE(xpd, "XPD at %d%d already exists\n", unit, subunit); - goto out; + return 0; } xpd = proto_table->xops.card_new(xbus, unit, subunit, proto_table, subtype, subunits, to_phone); if(!xpd) { XBUS_NOTICE(xbus, "card_new(%d,%d,%d,%d,%d) failed. Ignored.\n", unit, subunit, proto_table->type, subtype, to_phone); - goto err; + return -EINVAL; } -out: return 0; -err: - if(xpd) - xpd_free(xpd); - return ret; } void xpd_post_init(xpd_t *xpd) @@ -311,6 +314,10 @@ static int xpd_read_proc(char *page, char **start, off_t off, int count, int *eo xpd->timing_priority, xpd->timer_count, xpd->span.mainttimer ); + len += sprintf(page + len, "xpd_state: %s (%d)\n", + xpd_statename(xpd->xpd_state), xpd->xpd_state); + len += sprintf(page + len, "open_counter=%d refcount=%d\n", + atomic_read(&xpd->open_counter), atomic_read(refcount_xpd(xpd))); len += sprintf(page + len, "Address: U=%d S=%d\n", xpd->addr.unit, xpd->addr.subunit); len += sprintf(page + len, "Subunits: %d\n", xpd->subunits); len += sprintf(page + len, "Type: %d.%d\n\n", xpd->type, xpd->subtype); @@ -412,37 +419,93 @@ out: #endif +const char *xpd_statename(enum xpd_state st) +{ + switch(st) { + case XPD_STATE_START: return "START"; + case XPD_STATE_INIT_REGS: return "INIT_REGS"; + case XPD_STATE_READY: return "READY"; + case XPD_STATE_NOHW: return "NOHW"; + } + return NULL; +} + +bool xpd_setstate(xpd_t *xpd, enum xpd_state newstate) +{ + BUG_ON(!xpd); + XPD_DBG(DEVICES, xpd, "%s: %s (%d) -> %s (%d)\n", __FUNCTION__, + xpd_statename(xpd->xpd_state), xpd->xpd_state, + xpd_statename(newstate), newstate); + switch(newstate) { + case XPD_STATE_START: + goto badstate; + case XPD_STATE_INIT_REGS: + if(xpd->xpd_state != XPD_STATE_START) + goto badstate; + if(xpd->addr.subunit != 0) { + XPD_NOTICE(xpd, + "%s: Moving to %s allowed only for subunit 0\n", + __FUNCTION__, xpd_statename(newstate)); + goto badstate; + } + break; + case XPD_STATE_READY: + if(xpd->addr.subunit == 0) { + /* Unit 0 script initialize registers of all subunits */ + if(xpd->xpd_state != XPD_STATE_INIT_REGS) + goto badstate; + } else { + if(xpd->xpd_state != XPD_STATE_START) + goto badstate; + } + break; + case XPD_STATE_NOHW: + break; + default: + XPD_ERR(xpd, "%s: Unknown newstate=%d\n", __FUNCTION__, newstate); + } + xpd->xpd_state = newstate; + return 1; +badstate: + XPD_NOTICE(xpd, "%s: cannot transition: %s (%d) -> %s (%d)\n", + __FUNCTION__, + xpd_statename(xpd->xpd_state), xpd->xpd_state, + xpd_statename(newstate), newstate); + return 0; +} + + /* * xpd_alloc - Allocator for new XPD's * */ -xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channels) +__must_check xpd_t *xpd_alloc(xbus_t *xbus, + int unit, int subunit, + int subtype, int subunits, + size_t privsize, const xproto_table_t *proto_table, int channels) { xpd_t *xpd = NULL; size_t alloc_size = sizeof(xpd_t) + privsize; int type = proto_table->type; BUG_ON(!proto_table); - DBG(DEVICES, "type=%d channels=%d (alloc_size=%zd)\n", + XBUS_DBG(DEVICES, xbus, "type=%d channels=%d (alloc_size=%zd)\n", type, channels, alloc_size); if(channels > CHANNELS_PERXPD) { - ERR("%s: type=%d: too many channels %d\n", + XBUS_ERR(xbus, "%s: type=%d: too many channels %d\n", __FUNCTION__, type, channels); goto err; } if((xpd = KZALLOC(alloc_size, GFP_KERNEL)) == NULL) { - ERR("%s: type=%d: Unable to allocate memory\n", + XBUS_ERR(xbus, "%s: type=%d: Unable to allocate memory\n", __FUNCTION__, type); goto err; } xpd->priv = (byte *)xpd + sizeof(xpd_t); spin_lock_init(&xpd->lock); spin_lock_init(&xpd->lock_recompute_pcm); - xpd->xbus = NULL; - xpd->xbus_idx = -1; xpd->channels = channels; - xpd->chans = NULL; xpd->card_present = 0; xpd->offhook_state = 0x0; /* ONHOOK */ xpd->type = proto_table->type; @@ -450,6 +513,9 @@ xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channel xpd->xops = &proto_table->xops; xpd->digital_outputs = 0; xpd->digital_inputs = 0; + xpd->xpd_state = XPD_STATE_START; + xpd->subtype = subtype; + xpd->subunits = subunits; atomic_set(&xpd->zt_registered, 0); atomic_set(&xpd->open_counter, 0); @@ -459,13 +525,27 @@ xpd_t *xpd_alloc(size_t privsize, const xproto_table_t *proto_table, int channel ERR("%s: Unable to allocate channels\n", __FUNCTION__); goto err; } - xproto_get(type); /* will be returned in xpd_free() */ + /* For USB-1 disable some channels */ + if(MAX_SEND_SIZE(xbus) < RPACKET_SIZE(GLOBAL, PCM_WRITE)) { + xpp_line_t no_pcm; + + no_pcm = 0x7F | xpd->digital_outputs | xpd->digital_inputs; + xpd->no_pcm = no_pcm; + XBUS_NOTICE(xbus, "max xframe size = %d, disabling some PCM channels. no_pcm=0x%04X\n", + MAX_SEND_SIZE(xbus), xpd->no_pcm); + } + xbus_xpd_bind(xbus, xpd, unit, subunit); + if(xpd_proc_create(xbus, xpd) < 0) + goto err; + xbus = get_xbus(__FUNCTION__, xbus); /* returned in xpd_free() */ + xproto_get(type); /* will be returned in xpd_free() */ return xpd; err: if(xpd) { + xpd_proc_remove(xbus, xpd); if(xpd->chans) kfree((void *)xpd->chans); - kfree(xpd); + KZFREE(xpd); } return NULL; } @@ -477,31 +557,50 @@ err: #define ZT_EVENT_REMOVED (20) #endif -void xpd_disconnect(xpd_t *xpd) +/* + * Try our best to make asterisk close all channels related to + * this Astribank: + * - Set span state to ZT_ALARM_NOTOPEN in all relevant spans. + * - Notify zaptel afterwards about spans (so it can see all changes at once). + * - Also send ZT_EVENT_REMOVED on all channels. + */ +void xbus_request_removal(xbus_t *xbus) { unsigned long flags; + int i; - BUG_ON(!xpd); - - spin_lock_irqsave(&xpd->lock, flags); - XPD_DBG(DEVICES, xpd, "(%p)\n", xpd->xproto); - if(!xpd->card_present) /* Multiple reports */ - goto out; - xpd->card_present = 0; - if(SPAN_REGISTERED(xpd)) { - int i; - - update_xpd_status(xpd, ZT_ALARM_NOTOPEN); - /* TODO: Should this be done before releasing the spinlock? */ - XPD_DBG(DEVICES, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n"); - for (i=0; ispan.channels; i++) { - zt_qevent_lock(XPD_CHAN(xpd, i),ZT_EVENT_REMOVED); + for(i = 0; i < MAX_XPDS; i++) { + xpd_t *xpd = xpd_of(xbus, i); + if(xpd) { + XPD_DBG(DEVICES, xpd, "\n"); + spin_lock_irqsave(&xpd->lock, flags); + xpd->card_present = 0; + xpd_setstate(xpd, XPD_STATE_NOHW); + xpd->span.alarms = ZT_ALARM_NOTOPEN; + spin_unlock_irqrestore(&xpd->lock, flags); + } + } + /* Now notify zaptel */ + for(i = 0; i < MAX_XPDS; i++) { + xpd_t *xpd = xpd_of(xbus, i); + if(xpd) { + if(SPAN_REGISTERED(xpd)) { + int i; + + zt_alarm_notify(&xpd->span); + XPD_DBG(DEVICES, xpd, "Queuing ZT_EVENT_REMOVED on all channels to ask user to release them\n"); + for (i=0; ispan.channels; i++) { + zt_qevent_lock(XPD_CHAN(xpd, i),ZT_EVENT_REMOVED); + } + } + xpd_device_unregister(xpd); } } -out: - spin_unlock_irqrestore(&xpd->lock, flags); } +/* + * The xpd isn't open by anyone, we can unregister it and free it + */ void xpd_remove(xpd_t *xpd) { xbus_t *xbus; @@ -532,9 +631,9 @@ void update_xpd_status(xpd_t *xpd, int alarm_flag) } if(span->alarms == alarm_flag) return; + XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag); span->alarms = alarm_flag; zt_alarm_notify(span); - XPD_DBG(GENERAL, xpd, "Update XPD alarms: %s -> %02X\n", xpd->span.name, alarm_flag); } /* @@ -608,6 +707,7 @@ void hookstate_changed(xpd_t *xpd, int pos, bool to_offhook) } #ifdef CONFIG_PROC_FS +#ifdef OLD_PROC static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int count, int *eof, void *data) { int len = 0; @@ -615,8 +715,9 @@ static int proc_xpd_ztregister_read(char *page, char **start, off_t off, int cou xpd_t *xpd = data; BUG_ON(!xpd); + XPD_NOTICE(xpd, "%s: DEPRECATED: %s[%d] read from /proc interface instead of /sys\n", + __FUNCTION__, current->comm, current->tgid); spin_lock_irqsave(&xpd->lock, flags); - len += sprintf(page + len, "%d\n", SPAN_REGISTERED(xpd) ? xpd->span.spanno : 0); spin_unlock_irqrestore(&xpd->lock, flags); if (len <= off+count) @@ -638,6 +739,8 @@ static int proc_xpd_ztregister_write(struct file *file, const char __user *buffe int ret; BUG_ON(!xpd); + XPD_NOTICE(xpd, "%s: DEPRECATED: %s[%d] wrote 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)) @@ -646,6 +749,8 @@ static int proc_xpd_ztregister_write(struct file *file, const char __user *buffe ret = sscanf(buf, "%d", &zt_reg); if(ret != 1) return -EINVAL; + if(!XBUS_IS(xpd->xbus, READY)) + return -ENODEV; XPD_DBG(GENERAL, xpd, "%s\n", (zt_reg) ? "register" : "unregister"); if(zt_reg) ret = zaptel_register_xpd(xpd); @@ -661,8 +766,9 @@ static int proc_xpd_blink_read(char *page, char **start, off_t off, int count, i xpd_t *xpd = data; BUG_ON(!xpd); + XPD_NOTICE(xpd, "%s: DEPRECATED: %s[%d] read from /proc interface instead of /sys\n", + __FUNCTION__, current->comm, current->tgid); spin_lock_irqsave(&xpd->lock, flags); - len += sprintf(page + len, "0x%lX\n", xpd->blink_mode); spin_unlock_irqrestore(&xpd->lock, flags); if (len <= off+count) @@ -685,6 +791,8 @@ static int proc_xpd_blink_write(struct file *file, const char __user *buffer, un BUG_ON(!xpd); + XPD_NOTICE(xpd, "%s: DEPRECATED: %s[%d] wrote 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)) @@ -699,6 +807,7 @@ static int proc_xpd_blink_write(struct file *file, const char __user *buffer, un xpd->blink_mode = blink; return count; } +#endif #endif @@ -730,23 +839,28 @@ int xpp_open(struct zt_chan *chan) return -EINVAL; } xpd = chan->pvt; + xpd = get_xpd(__FUNCTION__, xpd); /* Returned in xpp_close() */ if (!xpd) { NOTICE("open called on a chan with no pvt (xpd)\n"); - return -EINVAL; + BUG(); } xbus = xpd->xbus; if (!xbus) { NOTICE("open called on a chan with no xbus\n"); - return -EINVAL; + BUG(); } pos = chan->chanpos - 1; + if(!xpd->card_present) { + LINE_NOTICE(xpd, pos, "Cannot open -- device not ready\n"); + put_xpd(__FUNCTION__, xpd); + return -ENODEV; + } #endif - spin_lock_irqsave(&xbus->lock, flags); - atomic_inc(&xbus->xbus_ref_count); atomic_inc(&xpd->open_counter); - DBG(DEVICES, "chan=%d (xbus_ref_count=%d)\n", - pos, atomic_read(&xbus->xbus_ref_count)); + LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", + current->comm, current->pid, + atomic_read(&xpd->open_counter)); spin_unlock_irqrestore(&xbus->lock, flags); if(xpd->xops->card_open) xpd->xops->card_open(xpd, pos); @@ -761,14 +875,14 @@ int xpp_close(struct zt_chan *chan) unsigned long flags; spin_lock_irqsave(&xbus->lock, flags); - atomic_dec(&xpd->open_counter); spin_unlock_irqrestore(&xbus->lock, flags); if(xpd->xops->card_close) xpd->xops->card_close(xpd, pos); - XPD_DBG(GENERAL, xpd, "pid=%d: chan=%d (xbus_ref_count=%d)\n", - current->pid, pos, atomic_read(&xbus->xbus_ref_count)); - if(atomic_dec_and_test(&xbus->xbus_ref_count)) - xbus_remove(xbus); + LINE_DBG(DEVICES, xpd, pos, "%s[%d]: open_counter=%d\n", + current->comm, current->pid, + atomic_read(&xpd->open_counter)); + atomic_dec(&xpd->open_counter); /* from xpp_open() */ + put_xpd(__FUNCTION__, xpd); /* from xpp_open() */ return 0; } @@ -841,23 +955,23 @@ int xpp_maint(struct zt_span *span, int cmd) DBG(GENERAL, "span->mainttimer=%d\n", span->mainttimer); switch(cmd) { case ZT_MAINT_NONE: - printk("XXX Turn off local and remote loops XXX\n"); + INFO("XXX Turn off local and remote loops XXX\n"); break; case ZT_MAINT_LOCALLOOP: - printk("XXX Turn on local loopback XXX\n"); + INFO("XXX Turn on local loopback XXX\n"); break; case ZT_MAINT_REMOTELOOP: - printk("XXX Turn on remote loopback XXX\n"); + INFO("XXX Turn on remote loopback XXX\n"); break; case ZT_MAINT_LOOPUP: - printk("XXX Send loopup code XXX\n"); + INFO("XXX Send loopup code XXX\n"); // CALL_XMETHOD(LOOPBACK_AX, xpd->xbus, xpd, loopback_data, ARRAY_SIZE(loopback_data)); break; case ZT_MAINT_LOOPDOWN: - printk("XXX Send loopdown code XXX\n"); + INFO("XXX Send loopdown code XXX\n"); break; case ZT_MAINT_LOOPSTOP: - printk("XXX Stop sending loop codes XXX\n"); + INFO("XXX Stop sending loop codes XXX\n"); break; default: ERR("XPP: Unknown maint command: %d\n", cmd); @@ -895,7 +1009,7 @@ static int xpp_watchdog(struct zt_span *span, int cause) * - User action through /proc * - During xpd_remove() */ -static int zaptel_unregister_xpd(xpd_t *xpd) +int zaptel_unregister_xpd(xpd_t *xpd) { unsigned long flags; @@ -908,6 +1022,7 @@ static int zaptel_unregister_xpd(xpd_t *xpd) return -EIDRM; } update_xpd_status(xpd, ZT_ALARM_NOTOPEN); + /* We should now have only a ref from the xbus (from create_xpd()) */ if(atomic_read(&xpd->open_counter)) { XPD_NOTICE(xpd, "Busy (open_counter=%d). Skipping.\n", atomic_read(&xpd->open_counter)); spin_unlock_irqrestore(&xpd->lock, flags); @@ -925,7 +1040,7 @@ static int zaptel_unregister_xpd(xpd_t *xpd) return 0; } -static int zaptel_register_xpd(xpd_t *xpd) +int zaptel_register_xpd(xpd_t *xpd) { struct zt_span *span; xbus_t *xbus; @@ -985,7 +1100,7 @@ static int zaptel_register_xpd(xpd_t *xpd) * - The modern "/sys/bus/astribanks/devices/xbus-??/connector" attribute * So let's also export it via the newfangled "location" field. */ - snprintf(span->location, sizeof(span->location) - 1, "%s", xbus->location); + snprintf(span->location, sizeof(span->location) - 1, "%s", xbus->connector); /* * Who said a span and irq have 1-1 relationship? * Also exporting this low-level detail isn't too wise. @@ -996,8 +1111,6 @@ static int zaptel_register_xpd(xpd_t *xpd) #ifdef ZAPTEL_SYNC_TICK span->sync_tick = zaptel_sync_tick; #endif - if (xpp_ec) - span->echocan = xpp_echocan; #ifdef CONFIG_ZAPTEL_WATCHDOG span->watchdog = xpp_watchdog; #endif @@ -1025,22 +1138,10 @@ static int zaptel_register_xpd(xpd_t *xpd) for_each_line(xpd, cn) { if(IS_OFFHOOK(xpd, cn)) notify_rxsig(xpd, cn, ZT_RXSIG_OFFHOOK); - } + } return 0; } -/*------------------------- Proc debugging interface ---------------*/ - -#ifdef CONFIG_PROC_FS - -#if 0 -static int xpp_zap_write_proc(struct file *file, const char __user *buffer, unsigned long count, void *data) -{ -} -#endif - -#endif - /*------------------------- Initialization -------------------------*/ static void do_cleanup(void) @@ -1097,12 +1198,13 @@ static void __exit xpp_zap_cleanup(void) } EXPORT_SYMBOL(debug); -EXPORT_SYMBOL(xpd_common_init); EXPORT_SYMBOL(create_xpd); EXPORT_SYMBOL(xpd_post_init); +EXPORT_SYMBOL(get_xpd); +EXPORT_SYMBOL(put_xpd); EXPORT_SYMBOL(xpd_alloc); EXPORT_SYMBOL(xpd_free); -EXPORT_SYMBOL(xpd_disconnect); +EXPORT_SYMBOL(xbus_request_removal); EXPORT_SYMBOL(update_xpd_status); EXPORT_SYMBOL(oht_pcm); EXPORT_SYMBOL(mark_offhook); -- cgit v1.2.3