diff options
author | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-05-13 21:08:09 +0000 |
---|---|---|
committer | tzafrir <tzafrir@5390a7c7-147a-4af0-8ec9-7488f05a26cb> | 2008-05-13 21:08:09 +0000 |
commit | d7e54a785544ac40abc4a88383df3a913ca466e8 (patch) | |
tree | abf630c8372e7c81407172ad31190fa8a617a8ed /kernel/xpp/xbus-core.c | |
parent | 823cf303caf13cc6e4fd2c2173804f0990b29532 (diff) |
xpp r5723: Includes, among others:
* New firmware protocol version: 3.0 .
* New numbers for the device types: (e.g. in card_init* scripts)
- FXS: 1 (was: 3)
- FXO: 2 (was: 4)
- BRI: 3 (was: 6 for TE, 7 for NT)
- PRI: 4 (was: 9)
* Init scripts of FXS and FXO modules are now written in Perl as well
(be sure to have File::Basename, e.g: perl-modules in Debian).
* calibrate_slics merged into init_card_1_30 .
* Module parameter print_dbg replaced with debug . Same meaning.
* init_fxo_modes removed: content moved into init_card_2_30, verified
at build time.
* Code tested with sparse. Most warnings were fixed.
* Set ZT_SIG_DACS for the bchans in the PRI and BRI modules to not get
ignored by ztscan.
* Handle null config_desc we get from some crazy USB controllers.
* genzaptelconf: Fix reporting of empty slots in list mode.
* xpp_blink can now blink a single analog port.
* "slics" has been renamed "chipregs".
* Fixed a small typo in fpga_load(8).
* Fixed bashism in xpp_fxloader.
Merged revisions 4264 via svnmerge from
http://svn.digium.com/svn/zaptel/branches/1.2
git-svn-id: http://svn.digium.com/svn/zaptel/branches/1.4@4266 5390a7c7-147a-4af0-8ec9-7488f05a26cb
Diffstat (limited to 'kernel/xpp/xbus-core.c')
-rw-r--r-- | kernel/xpp/xbus-core.c | 548 |
1 files changed, 236 insertions, 312 deletions
diff --git a/kernel/xpp/xbus-core.c b/kernel/xpp/xbus-core.c index 385f542..26c31f5 100644 --- a/kernel/xpp/xbus-core.c +++ b/kernel/xpp/xbus-core.c @@ -38,6 +38,7 @@ #include "xpd.h" #include "xpp_zap.h" #include "xbus-core.h" +#include "card_global.h" #ifdef XPP_DEBUGFS #include "xpp_log.h" #endif @@ -46,7 +47,7 @@ static const char rcsid[] = "$Id$"; /* Defines */ -#define INITIALIZATION_TIMEOUT (60*HZ) /* in jiffies */ +#define INITIALIZATION_TIMEOUT (90*HZ) /* in jiffies */ #define PROC_XBUSES "xbuses" #define PROC_XBUS_SUMMARY "summary" #define PROC_XBUS_WAITFOR_XPDS "waitfor_xpds" @@ -57,37 +58,15 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer, #endif /* Command line parameters */ -extern int print_dbg; -DEF_PARM(uint, poll_timeout, 1000, 0644, "Timeout (in jiffies) waiting for units to reply"); -DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets"); +extern int debug; +static DEF_PARM(uint, poll_timeout, 1000, 0644, "Timeout (in jiffies) waiting for units to reply"); +static DEF_PARM_BOOL(rx_tasklet, 0, 0644, "Use receive tasklets"); static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data); static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data); static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_size, void *priv); static void transport_destroy(xbus_t *xbus); -/* - * Encapsulate all poll related data of a single xbus. - */ -struct xbus_poller { - /* - * Bus scanning - */ - uint xbus_num; - struct workqueue_struct *wq; - bool is_polling; - atomic_t count_poll_answers; - struct list_head poll_results; - wait_queue_head_t wait_for_polls; - - struct work_struct xpds_init_work; - - atomic_t count_xpds_to_initialize; - atomic_t count_xpds_initialized; - wait_queue_head_t wait_for_xpd_initialization; - struct proc_dir_entry *proc_xbus_waitfor_xpds; -}; - /* Data structures */ static spinlock_t xbuses_lock = SPIN_LOCK_UNLOCKED; static int bus_count = 0; @@ -110,7 +89,7 @@ static void init_xbus(uint num, xbus_t *xbus) init_waitqueue_head(&desc->can_release_xbus); } -int refcount_xbus(uint num) +static int refcount_xbus(uint num) { BUG_ON(num >= ARRAY_SIZE(xbuses_array)); return atomic_read(&xbuses_array[num].xbus_refcount); @@ -149,7 +128,7 @@ void put_xbus(xbus_t *xbus) } } -bool __must_check wait_for_xbus_release(uint xbus_num) +static bool __must_check wait_for_xbus_release(uint xbus_num) { xbus_t *xbus; int ret; @@ -383,13 +362,13 @@ static spinlock_t serialize_dump_xframe = SPIN_LOCK_UNLOCKED; static void do_hexdump(const char msg[], byte *data, uint16_t len) { int i; - int print_dbg = DBG_ANY; /* mask global print_dbg */ + int debug = DBG_ANY; /* mask global debug */ for(i = 0; i < len; i++) DBG(ANY, "%s: %3d> %02X\n", msg, i, data[i]); } -void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int print_dbg) +void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, int debug) { const uint16_t frm_len = XFRAME_LEN(xframe); xpacket_t *pack; @@ -441,12 +420,12 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i break; } do_print = 0; - if(print_dbg == DBG_ANY) + if(debug == DBG_ANY) do_print = 1; else if(XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_READ) && XPACKET_OP(pack) != XPROTO_NAME(GLOBAL,PCM_WRITE)) do_print = 1; - else if(print_dbg & DBG_PCM) { + else if(debug & DBG_PCM) { static int rate_limit; if((rate_limit++ % 1003) == 0) @@ -466,7 +445,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i XPACKET_OP(pack), XPACKET_ADDR_UNIT(pack), XPACKET_ADDR_SUBUNIT(pack), pos); - dump_packet(" ", pack, print_dbg); + dump_packet(" ", pack, debug); } num++; pos = nextpos; @@ -476,7 +455,7 @@ void dump_xframe(const char msg[], const xbus_t *xbus, const xframe_t *xframe, i spin_unlock_irqrestore(&serialize_dump_xframe, flags); } -bool xbus_ready(const xbus_t *xbus, const char msg[]) +static bool xbus_ready(const xbus_t *xbus, const char msg[]) { if(!xbus) { ERR("null xbus: %s\n", msg); @@ -536,6 +515,8 @@ static int really_send_cmd_frame(xbus_t *xbus, xframe_t *xframe) } ops = transportops_get(xbus); BUG_ON(!ops); + if(debug & DBG_COMMANDS) + dump_xframe("TX-CMD", xbus, xframe, DBG_ANY); ret = ops->xframe_send_cmd(xbus, xframe); transportops_put(xbus); if(ret == 0) { @@ -752,159 +733,169 @@ out: } /* - * This must be called from synchronous (non-interrupt) context - * it returns only when all XPD's on the bus are detected and - * initialized. + * Called with xbus->worker locked. */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) -static void xbus_poll(struct work_struct *work) -{ - struct xbus_poller *poller = container_of(work, struct xbus_poller, xpds_init_work); -#else -static void xbus_poll(void *data) +static int new_card(xbus_t *xbus, + int unit, + byte type, + byte subtype, + byte numchips, + byte ports_per_chip, + byte ports, + byte port_dir) { - struct xbus_poller *poller = data; -#endif - int id; + const xproto_table_t *proto_table; + const xops_t *xops; + int i; + int subunits; int ret = 0; - unsigned long flags; - struct list_head *card; - struct list_head *next_card; - struct list_head removal_list; - struct list_head additions_list; - int count_removed; - int count_added; - xbus_t *xbus; - BUG_ON(!poller); - xbus = get_xbus(poller->xbus_num); - if(!xbus) { - XBUS_ERR(xbus, "Aborting poll. XBUS #%d disappeared.\n", - poller->xbus_num); - return; - } - msleep(2); /* roundtrip for older polls */ - spin_lock_irqsave(&xbus->lock, flags); - XBUS_DBG(DEVICES, xbus, "\n"); - poller->is_polling = 1; - if(!XBUS_GET(xbus)) { - XBUS_ERR(xbus, "Aborting poll. Is shutting down.\n"); - goto out; /* FIXME: should not XBUS_PUT() in that case */ - } - /* - * Send out the polls - */ - for(id = 0; id < MAX_XPDS; id++) { - if(!TRANSPORT_RUNNING(xbus)) - break; - XBUS_DBG(DEVICES, xbus, "Polling slot %d\n", id); - spin_unlock_irqrestore(&xbus->lock, flags); - ret = CALL_PROTO(GLOBAL, DESC_REQ, xbus, NULL, id); - spin_lock_irqsave(&xbus->lock, flags); + proto_table = xproto_get(type); + if(!proto_table) { + XBUS_NOTICE(xbus, + "CARD %d: missing protocol table for type %d. Ignored.\n", + unit, type); + return -EINVAL; + } + subunits = (ports + proto_table->ports_per_subunit - 1) / + proto_table->ports_per_subunit; + XBUS_DBG(DEVICES, xbus, "CARD %d type=%d.%d ports=%d (%dx%d), %d subunits, port-dir=0x%02X\n", + unit, + type, + subtype, + ports, + numchips, + ports_per_chip, + subunits, + port_dir + ); + xops = &proto_table->xops; + BUG_ON(!xops); + xbus->worker->num_units += subunits - 1; + for(i = 0; i < subunits; i++) { + if(!TRANSPORT_RUNNING(xbus)) { + ret = -ENODEV; + goto out; + } + XBUS_DBG(DEVICES, xbus, "Creating XPD=%d%d type=%d.%d\n", + unit, + i, + type, + subtype); + if(!XBUS_GET(xbus)) { + XBUS_ERR(xbus, "Aborting creation. Is shutting down.\n"); + ret = -ENODEV; + goto out; + } + ret = create_xpd(xbus, proto_table, unit, i, type, subtype, subunits, port_dir); + XBUS_PUT(xbus); if(ret < 0) { - XBUS_ERR(xbus, "Failed sending DESC_REQ to XPD #%d\n", id); + XBUS_ERR(xbus, "Creation of XPD=%d%d failed %d\n", + unit, i, ret); goto out; } + xbus->worker->num_units_initialized++; } - spin_unlock_irqrestore(&xbus->lock, flags); - /* - * Wait for replies - */ - XBUS_DBG(DEVICES, xbus, "Polled %d XPD's. Waiting for replies max %d jiffies\n", MAX_XPDS, poll_timeout); - ret = wait_event_interruptible_timeout(poller->wait_for_polls, atomic_read(&poller->count_poll_answers) >= MAX_XPDS, poll_timeout); - if(ret == 0) { - XBUS_ERR(xbus, "Poll timeout. Continuing anyway.\n"); - /* - * Continue processing. Maybe some units did reply. - */ - } else if(ret < 0) { - XBUS_ERR(xbus, "Poll interrupted %d\n", ret); - goto out; - } else - XBUS_DBG(DEVICES, xbus, "Poll finished in %d jiffies.\n", poll_timeout - ret); - /* - * Build removals/additions lists - */ - spin_lock_irqsave(&xbus->lock, flags); - INIT_LIST_HEAD(&removal_list); - INIT_LIST_HEAD(&additions_list); - count_removed = 0; - count_added = 0; - list_for_each_safe(card, next_card, &poller->poll_results) { - struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); - byte type = card_desc->type; - xpd_t *xpd; +out: + xproto_put(proto_table); /* ref count is inside the xpds now */ + return ret; +} - BUG_ON(card_desc->magic != CARD_DESC_MAGIC); - /* - * Return the refcount we got in xbus_poller_notify() - * We are still protected by the refcount taken in - * the beginning of xbus_poll(). - */ - put_xbus(xbus); - xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit); - - if(xpd && type == XPD_TYPE_NOMODULE) { /* card removal */ - list_move_tail(card, &removal_list); - count_removed++; - } else if(!xpd && type != XPD_TYPE_NOMODULE) { /* card detection */ - if(card_desc->rev != XPP_PROTOCOL_VERSION) { - XBUS_NOTICE(xbus, "XPD at %d%d: type=%d.%d has bad firmware revision %d.%d\n", - card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit, - card_desc->type, card_desc->subtype, - card_desc->rev / 10, card_desc->rev % 10); - list_del(card); - kfree(card_desc); +static int xbus_initialize(xbus_t *xbus) +{ + int unit; + int subunit; + xpd_t *xpd; + + for(unit = 0; unit < MAX_UNIT; unit++) { + xpd = xpd_byaddr(xbus, unit, 0); + if(!xpd) + continue; + if(run_initialize_registers(xpd) < 0) { + XPD_ERR(xpd, "Register Initialization failed\n"); + goto err; + } + for(subunit = 0; subunit < MAX_SUBUNIT; subunit++) { + xpd = xpd_byaddr(xbus, unit, subunit); + if(!xpd) continue; + if(CALL_XMETHOD(card_init, xpd->xbus, xpd) < 0) { + XPD_ERR(xpd, "Card Initialization failed\n"); + goto err; } - XBUS_INFO(xbus, "Detected XPD at %d%d type=%d.%d Revision %d.%d\n", - card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit, - card_desc->type, card_desc->subtype, - card_desc->rev / 10, card_desc->rev % 10); - list_move_tail(card, &additions_list); - count_added++; - } else { /* same same */ - list_del(card); - kfree(card_desc); + //CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 0); /* Turn off all channels */ + xpd->card_present = 1; + CALL_XMETHOD(XPD_STATE, xpd->xbus, xpd, 1); /* Turn on all channels */ + XPD_INFO(xpd, "Initialized: %s\n", xpd->type_name); + xpd_post_init(xpd); } } - poller->is_polling = 0; - /* - * We set this *after* poll is finished, so wait_for_xpd_initialization can - * tell we already know how many units we have. - */ - atomic_set(&poller->count_xpds_to_initialize, count_added); - spin_unlock_irqrestore(&xbus->lock, flags); - XBUS_INFO(xbus, "Poll results: removals=%d additions=%d\n", count_removed, count_added); - /* - * Process removals first - */ - list_for_each_safe(card, next_card, &removal_list) { - struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); - xpd_t *xpd; + return 0; +err: + for(unit = 0; unit < MAX_UNIT; unit++) { + for(subunit = 0; subunit < MAX_SUBUNIT; subunit++) { + xpd = xpd_byaddr(xbus, unit, subunit); + if(!xpd) + xpd_free(xpd); + } + } + return -EINVAL; +} - list_del(card); - xpd = xpd_byaddr(xbus, card_desc->xpd_addr.unit, card_desc->xpd_addr.subunit); - if(xpd) - xpd_disconnect(xpd); - kfree(card); +/* + * This must be called from synchronous (non-interrupt) context + * it returns only when all XPD's on the bus are detected and + * initialized. + */ +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) +void xbus_populate(struct work_struct *work) +{ + struct xbus_workqueue *worker = container_of(work, struct xbus_workqueue, xpds_init_work); +#else +void xbus_populate(void *data) +{ + struct xbus_workqueue *worker = data; +#endif + xbus_t *xbus; + struct list_head *card; + struct list_head *next_card; + unsigned long flags; + int ret = 0; + + xbus = worker->xbus; + if(!XBUS_GET(xbus)) { + XBUS_NOTICE(xbus, "Shutting down, aboring initialization\n"); + return; } - /* - * Now process additions - */ - list_for_each_safe(card, next_card, &additions_list) { + spin_lock_irqsave(&worker->worker_lock, flags); + list_for_each_safe(card, next_card, &worker->card_list) { struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); list_del(card); - /* FIXME: card_detected() should have a return value for count_xpds_initialized */ - card_detected(card_desc); - atomic_inc(&poller->count_xpds_initialized); + BUG_ON(card_desc->magic != CARD_DESC_MAGIC); + /* Release/Reacquire locks around blocking calls */ + spin_unlock_irqrestore(&xbus->worker->worker_lock, flags); + ret = new_card(xbus, + card_desc->xpd_addr.unit, + card_desc->type, + card_desc->subtype, + card_desc->numchips, + card_desc->ports_per_chip, + card_desc->ports, + card_desc->port_dir); + spin_lock_irqsave(&xbus->worker->worker_lock, flags); + KZFREE(card_desc); + if(ret) + break; } - /* Device-Model */ - if((ret = xbus_sysfs_create(xbus)) < 0) { - XBUS_ERR(xbus, "%s: xbus_sysfs_create() failed: %d\n", __FUNCTION__, ret); - goto out; + spin_unlock_irqrestore(&worker->worker_lock, flags); + xbus_initialize(xbus); + worker->xpds_init_done = 1; + ret = xbus_sysfs_create(xbus); + if(ret) { + XBUS_ERR(xbus, "SYSFS creation failed: %d\n", ret); } + wake_up(&worker->wait_for_xpd_initialization); /* * Now request Astribank to start self_ticking. * This is the last initialization command. So @@ -912,164 +903,107 @@ static void xbus_poll(void *data) */ xbus_request_sync(xbus, SYNC_MODE_PLL); elect_syncer("xbus_poll(end)"); /* FIXME: try to do it later */ -out: - poller->is_polling = 0; /* just for safety */ + put_xbus(xbus); /* taken in AB_DESCRIPTION */ XBUS_PUT(xbus); - wake_up(&poller->wait_for_xpd_initialization); - put_xbus(xbus); - return; } -void xbus_poller_notify(xbus_t *xbus, struct card_desc_struct *card_desc) +static void worker_destroy(struct xbus_workqueue *worker) { - struct xbus_poller *poller; + xbus_t *xbus; + struct list_head *card; + struct list_head *next_card; unsigned long flags; - BUG_ON(!xbus); - poller = xbus->poller; - BUG_ON(!poller); - if(!poller->is_polling) { - XBUS_NOTICE(xbus, "%d%d replied not during poll. Ignore\n", - card_desc->xpd_addr.unit, - card_desc->xpd_addr.subunit); - kfree(card_desc); + if(!worker) return; - } - spin_lock_irqsave(&xbus->lock, flags); - if(card_desc->type == XPD_TYPE_NOMODULE) - XBUS_COUNTER(xbus, DEV_DESC_EMPTY)++; - else - XBUS_COUNTER(xbus, DEV_DESC_FULL)++; - atomic_inc(&poller->count_poll_answers); - list_add_tail(&card_desc->card_list, &poller->poll_results); - spin_unlock_irqrestore(&xbus->lock, flags); - /* - * Reference counting for the xbus. - * Would be returned in xbus_poll() - */ - xbus = get_xbus(xbus->num); - BUG_ON(!xbus); - /* - * wake_up only after exiting our critical section. - * We suspect that otherwise a spinlock nesting may occur - * and cause a panic (if spinlock debugging is compiled in). - */ - wake_up(&poller->wait_for_polls); - return; -} - -static void poller_destroy(struct xbus_poller *poller) -{ - xbus_t *xbus; + spin_lock_irqsave(&worker->worker_lock, flags); + xbus = worker->xbus; + list_for_each_safe(card, next_card, &worker->card_list) { + struct card_desc_struct *card_desc = list_entry(card, struct card_desc_struct, card_list); - if(!poller) - return; - xbus = get_xbus(poller->xbus_num); + BUG_ON(card_desc->magic != CARD_DESC_MAGIC); + list_del(card); + kfree(card_desc); + } + spin_unlock_irqrestore(&worker->worker_lock, flags); if(xbus) { #ifdef CONFIG_PROC_FS - if(xbus->proc_xbus_dir && poller->proc_xbus_waitfor_xpds) { + if(xbus->proc_xbus_dir && worker->proc_xbus_waitfor_xpds) { XBUS_DBG(PROC, xbus, "Removing proc '%s'\n", PROC_XBUS_WAITFOR_XPDS); remove_proc_entry(PROC_XBUS_WAITFOR_XPDS, xbus->proc_xbus_dir); - poller->proc_xbus_waitfor_xpds = NULL; + worker->proc_xbus_waitfor_xpds = NULL; } #endif - XBUS_DBG(DEVICES, xbus, "detach poller\n"); - xbus->poller = NULL; + XBUS_DBG(DEVICES, xbus, "detach worker\n"); + xbus->worker = NULL; } - if (poller->wq) { - DBG(DEVICES, "XBUS #%d: destroy workqueue\n", poller->xbus_num); - flush_workqueue(poller->wq); - destroy_workqueue(poller->wq); - poller->wq = NULL; + if (worker->wq) { + DBG(DEVICES, "XBUS #%d: destroy workqueue\n", worker->xbus->num); + flush_workqueue(worker->wq); + destroy_workqueue(worker->wq); + worker->wq = NULL; } - put_xbus(xbus); - KZFREE(poller); + put_xbus(xbus); /* Taken in worker_new() */ + KZFREE(worker); } /* - * Allocate a poller for the xbus including the nessessary workqueue. + * Allocate a worker for the xbus including the nessessary workqueue. * May call blocking operations, but only briefly (as we are called * from xbus_new() which is called from khubd. */ -static struct xbus_poller *poller_new(xbus_t *xbus) +static struct xbus_workqueue *worker_new(int xbus_num) { - struct xbus_poller *poller; + struct xbus_workqueue *worker; + xbus_t *xbus; + xbus = get_xbus(xbus_num); /* release in worker_destroy */ BUG_ON(xbus->busname[0] == '\0'); /* No name? */ - BUG_ON(xbus->poller); /* Hmmm... overrun pollers? */ + BUG_ON(xbus->worker != NULL); /* Hmmm... nested workers? */ XBUS_DBG(DEVICES, xbus, "\n"); - poller = KZALLOC(sizeof(*poller), GFP_KERNEL); - if(!poller) + worker = KZALLOC(sizeof(*worker), GFP_KERNEL); + if(!worker) goto err; - poller->xbus_num = xbus->num; - xbus->poller = poller; + worker->xbus = xbus; /* poll related variables */ - atomic_set(&poller->count_poll_answers, 0); - atomic_set(&poller->count_xpds_to_initialize, 0); - atomic_set(&poller->count_xpds_initialized, 0); - INIT_LIST_HEAD(&poller->poll_results); - init_waitqueue_head(&poller->wait_for_polls); - init_waitqueue_head(&poller->wait_for_xpd_initialization); - poller->wq = create_singlethread_workqueue(xbus->busname); - if(!poller->wq) { - XBUS_ERR(xbus, "Failed to create poller workqueue.\n"); + spin_lock_init(&worker->worker_lock); + INIT_LIST_HEAD(&worker->card_list); + init_waitqueue_head(&worker->wait_for_xpd_initialization); + worker->wq = create_singlethread_workqueue(xbus->busname); + if(!worker->wq) { + XBUS_ERR(xbus, "Failed to create worker workqueue.\n"); goto err; } #ifdef CONFIG_PROC_FS if(xbus->proc_xbus_dir) { - poller->proc_xbus_waitfor_xpds = create_proc_read_entry( + worker->proc_xbus_waitfor_xpds = create_proc_read_entry( PROC_XBUS_WAITFOR_XPDS, 0444, xbus->proc_xbus_dir, xbus_read_waitfor_xpds, xbus); - if (!poller->proc_xbus_waitfor_xpds) { + if (!worker->proc_xbus_waitfor_xpds) { XBUS_ERR(xbus, "Failed to create proc file '%s'\n", PROC_XBUS_WAITFOR_XPDS); goto err; } - poller->proc_xbus_waitfor_xpds->owner = THIS_MODULE; + worker->proc_xbus_waitfor_xpds->owner = THIS_MODULE; } #endif - return poller; + return worker; err: - poller_destroy(poller); + worker_destroy(worker); return NULL; } -/* - * Sends an xbus_poll() work to the poller workqueue of the given xbus. - */ -static int poller_dispatch(xbus_t *xbus) -{ - struct xbus_poller *poller = xbus->poller; - - if(!poller) { - XBUS_ERR(xbus, "missing poller\n"); - return 0; - } - /* Initialize the work. (adapt to kernel API changes). */ -#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,20) - INIT_WORK(&poller->xpds_init_work, xbus_poll); -#else - INIT_WORK(&poller->xpds_init_work, xbus_poll, poller); -#endif - /* Now send it */ - if(!queue_work(poller->wq, &poller->xpds_init_work)) { - XBUS_ERR(xbus, "Failed to queue xpd initialization work\n"); - return 0; - } - return 1; -} - int xbus_activate(xbus_t *xbus) { struct xbus_ops *ops; - struct xbus_poller *poller; + struct xbus_workqueue *worker; BUG_ON(!xbus); ops = transportops_get(xbus); BUG_ON(!ops); - poller = xbus->poller; - BUG_ON(!poller); + worker = xbus->worker; + BUG_ON(!worker); /* Sanity checks */ BUG_ON(!ops->xframe_send_pcm); BUG_ON(!ops->xframe_send_cmd); @@ -1086,8 +1020,7 @@ int xbus_activate(xbus_t *xbus) * Make sure Astribank knows not to send us ticks. */ xbus_request_sync(xbus, SYNC_MODE_NONE); - /* Poll it */ - poller_dispatch(xbus); + CALL_PROTO(GLOBAL, AB_REQUEST, xbus, NULL); return 0; } @@ -1099,6 +1032,7 @@ void xbus_disconnect(xbus_t *xbus) XBUS_INFO(xbus, "[%s] Disconnecting\n", xbus->label); xbus_set_command_timer(xbus, 1); xbus_request_sync(xbus, SYNC_MODE_NONE); /* no more ticks */ + xbus_sysfs_remove(xbus); /* Device-Model */ for(i = 0; i < MAX_XPDS; i++) { xpd_t *xpd = xpd_of(xbus, i); if(!xpd) @@ -1146,13 +1080,15 @@ static xbus_t *xbus_alloc(void) if(i >= MAX_BUSES) { ERR("%s: No free slot for new bus. i=%d\n", __FUNCTION__, i); kfree(xbus); - return NULL; + xbus = NULL; + goto out; } /* Found empty slot */ xbus->num = i; init_xbus(i, xbus); xbus = get_xbus(i); bus_count++; +out: spin_unlock_irqrestore(&xbuses_lock, flags); return xbus; } @@ -1180,7 +1116,6 @@ static void xbus_free(xbus_t *xbus) debugfs_remove(xbus->debugfs_dir); } #endif - poller_destroy(xbus->poller); #ifdef CONFIG_PROC_FS if(xbus->proc_xbus_dir) { if(xbus->proc_xbus_summary) { @@ -1222,7 +1157,6 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv) { int err; xbus_t *xbus = NULL; - struct xbus_poller *poller; BUG_ON(!ops); XBUS_DBG(GENERAL, xbus, "allocate new xbus\n"); @@ -1285,21 +1219,20 @@ xbus_t *xbus_new(struct xbus_ops *ops, ushort max_send_size, void *priv) goto nobus; } #endif - xframe_queue_init(&xbus->command_queue, 10, 200, "command_queue", xbus); + xframe_queue_init(&xbus->command_queue, 10, 100, "command_queue", xbus); xframe_queue_init(&xbus->receive_queue, 10, 50, "receive_queue", xbus); xframe_queue_init(&xbus->send_pool, 10, 200, "send_pool", xbus); xframe_queue_init(&xbus->receive_pool, 10, 50, "receive_pool", xbus); xframe_queue_init(&xbus->pcm_tospan, 5, 10, "pcm_tospan", xbus); tasklet_init(&xbus->receive_tasklet, receive_tasklet_func, (unsigned long)xbus); /* - * Create poller after /proc/XBUS-?? so the directory exists + * Create worker after /proc/XBUS-?? so the directory exists * before /proc/XBUS-??/waitfor_xpds tries to get created. */ - poller = poller_new(xbus); - if(!poller) { - ERR("Failed to allocate poller\n"); - xbus_free(xbus); - return NULL; + xbus->worker = worker_new(xbus->num); + if(!xbus->worker) { + ERR("Failed to allocate worker\n"); + goto nobus; } return xbus; nobus: @@ -1315,7 +1248,6 @@ void xbus_remove(xbus_t *xbus) down_write(&xbus->in_use); XBUS_INFO(xbus, "[%s] Removing\n", xbus->label); - xbus_sysfs_remove(xbus); /* Device-Model */ for(i = 0; i < MAX_XPDS; i++) { xpd_t *xpd = xpd_of(xbus, i); @@ -1329,6 +1261,7 @@ void xbus_remove(xbus_t *xbus) } xbus->xpds[i] = NULL; } + worker_destroy(xbus->worker); xbus_free(xbus); } @@ -1367,7 +1300,7 @@ static int xbus_fill_proc_queue(char *p, struct xframe_queue *q) static int xbus_read_proc(char *page, char **start, off_t off, int count, int *eof, void *data) { xbus_t *xbus; - struct xbus_poller *poller; + struct xbus_workqueue *worker; unsigned long flags; int len = 0; int i = (int)((unsigned long)data); @@ -1376,7 +1309,7 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e if(!xbus) goto out; spin_lock_irqsave(&xbus->lock, flags); - poller = xbus->poller; + worker = xbus->worker; len += sprintf(page + len, "%s: CONNECTOR=%s LABEL=[%s] STATUS=%s\n", xbus->busname, @@ -1384,11 +1317,6 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e xbus->label, (TRANSPORT_RUNNING(xbus)) ? "connected" : "missing" ); - len += sprintf(page + len, "POLLS: %d/%d\n", - atomic_read(&poller->count_poll_answers), MAX_XPDS); - len += sprintf(page + len, "XPDS_READY: %d/%d\n", - atomic_read(&poller->count_xpds_initialized), - atomic_read(&poller->count_xpds_to_initialize)); len += sprintf(page + len, "\nxbus_ref_count=%d\n", atomic_read(&xbus->xbus_ref_count) ); @@ -1449,7 +1377,7 @@ static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count int len = 0; unsigned long flags; xbus_t *xbus = data; - struct xbus_poller *poller; + struct xbus_workqueue *worker; int ret; if(!xbus) @@ -1458,30 +1386,28 @@ static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count if(!count || off) goto out; /* - * poller is created before /proc/XBUS-?? + * worker is created before /proc/XBUS-?? * So by now it exists and initialized. */ - poller = xbus->poller; - BUG_ON(!poller); + worker = xbus->worker; + BUG_ON(!worker); XBUS_DBG(DEVICES, xbus, "Waiting for card initialization of %d XPD's max %d seconds\n", - atomic_read(&poller->count_xpds_to_initialize), INITIALIZATION_TIMEOUT/HZ); + worker->num_units, + INITIALIZATION_TIMEOUT/HZ); /* * when polling is finished xbus_poll(): - * - Unset poller->is_polling - * - Sets poller->count_xpds_to_initialize. + * - Unset worker->is_polling + * - Sets worker->count_xpds_to_initialize. * So we wait until polling is finished (is_polling == 0) and: * - No poll answers from Astribank (e.g: defective firmware). * - Or no units to initialize (e.g: mini-AB with only main card). * - Or we finished initializing all existing units. * - Or A timeout passed. */ - ret = wait_event_interruptible_timeout(poller->wait_for_xpd_initialization, - !poller->is_polling && ( - atomic_read(&poller->count_poll_answers) == 0 || - atomic_read(&poller->count_xpds_to_initialize) == 0 || - atomic_read(&poller->count_xpds_initialized) >= - atomic_read(&poller->count_xpds_to_initialize)), + ret = wait_event_interruptible_timeout( + worker->wait_for_xpd_initialization, + worker->xpds_init_done, INITIALIZATION_TIMEOUT); if(ret == 0) { XBUS_ERR(xbus, "Card Initialization Timeout\n"); @@ -1492,13 +1418,12 @@ static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count } else XBUS_DBG(DEVICES, xbus, "Finished initialization of %d XPD's in %d seconds.\n", - atomic_read(&poller->count_xpds_initialized), + worker->num_units_initialized, (INITIALIZATION_TIMEOUT - ret)/HZ); spin_lock_irqsave(&xbus->lock, flags); len += sprintf(page + len, "XPDS_READY: %s: %d/%d\n", xbus->busname, - atomic_read(&poller->count_xpds_initialized), - atomic_read(&poller->count_xpds_to_initialize)); + worker->num_units_initialized, worker->num_units); spin_unlock_irqrestore(&xbus->lock, flags); out: if (len <= off+count) @@ -1584,7 +1509,7 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer, len = max_len; atomic_set(&xframe->frame_len, len); memcpy(xframe->packets, pack_start, len); /* FIXME: checksum? */ - dump_xframe("COMMAND", xbus, xframe, print_dbg); + dump_xframe("COMMAND", xbus, xframe, debug); send_cmd_frame(xbus, xframe); out: kfree(buf); @@ -1647,7 +1572,7 @@ static void transport_init(xbus_t *xbus, struct xbus_ops *ops, ushort max_send_s init_waitqueue_head(&xbus->transport.transport_unused); } -void transport_destroy(xbus_t *xbus) +static void transport_destroy(xbus_t *xbus) { int ret; @@ -1777,7 +1702,6 @@ EXPORT_SYMBOL(send_cmd_frame); EXPORT_SYMBOL(xframe_init); EXPORT_SYMBOL(transportops_get); EXPORT_SYMBOL(transportops_put); -EXPORT_SYMBOL(xbus_poller_notify); EXPORT_SYMBOL(xbus_command_queue_tick); #ifdef XPP_DEBUGFS EXPORT_SYMBOL(xbus_log); |