diff options
Diffstat (limited to 'xpp/xbus-core.c')
-rw-r--r-- | xpp/xbus-core.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/xpp/xbus-core.c b/xpp/xbus-core.c index b346bd7..7a9e374 100644 --- a/xpp/xbus-core.c +++ b/xpp/xbus-core.c @@ -43,6 +43,7 @@ static const char rcsid[] = "$Id$"; /* Defines */ #define POLL_TIMEOUT (MAX_XPDS) /* in jiffies */ +#define INITIALIZATION_TIMEOUT (40*HZ) /* in jiffies */ #define PROC_XBUSES "xbuses" #define PROC_XBUS_SUMMARY "summary" #define PROC_XBUS_WAITFOR_XPDS "waitfor_xpds" @@ -325,13 +326,13 @@ static int xbus_poll(void *data) ERR("%s is being removed...\n", xbus->busname); return -EBUSY; } + mdelay(2); /* roundtrip for older polls */ spin_lock_irqsave(&xbus->lock, flags); DBG("%s\n", xbus->busname); /* * Send out the polls */ - atomic_set(&xbus->count_poll_answers, 0); for(id = 0; id < MAX_XPDS; id++) { if(!xbus->hardware_exists) break; @@ -349,13 +350,16 @@ static int xbus_poll(void *data) /* * Wait for replies */ - DBG("%s: Polled %d XPD's. Waiting for replies\n", xbus->busname, MAX_XPDS); - ret = wait_event_timeout(xbus->wait_for_polls, atomic_read(&xbus->count_poll_answers) >= MAX_XPDS, POLL_TIMEOUT); - if(ret < 0) { - ERR("%s: Poll timeout %d\n", xbus->busname, ret); + DBG("%s: Polled %d XPD's. Waiting for replies max %d jiffies\n", xbus->busname, MAX_XPDS, POLL_TIMEOUT); + ret = wait_event_interruptible_timeout(xbus->wait_for_polls, atomic_read(&xbus->count_poll_answers) >= MAX_XPDS, POLL_TIMEOUT); + if(ret == 0) { + ERR("%s: Poll timeout\n", xbus->busname); + goto out; + } else if(ret < 0) { + ERR("%s: Poll interrupted %d\n", xbus->busname, ret); goto out; } - DBG("%s: Poll finished. Start processing.\n", xbus->busname); + DBG("%s: Poll finished in %d jiffies. Start processing.\n", xbus->busname, POLL_TIMEOUT-ret); /* * Build removals/additions lists */ @@ -384,6 +388,7 @@ static int xbus_poll(void *data) kfree(card_desc); } } + atomic_set(&xbus->count_xpds_to_initialize, count_added); spin_unlock_irqrestore(&xbus->lock, flags); INFO("%s: Poll results: removals=%d additions=%d\n", xbus->busname, count_removed, count_added); /* @@ -407,9 +412,11 @@ static int xbus_poll(void *data) 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(&xbus->count_xpds_initialized); } - complete_all(&xbus->xpds_initialized); + wake_up(&xbus->wait_for_xpd_initialization); out: up_read(&xbus->in_use); return ret; @@ -557,12 +564,17 @@ xbus_t *xbus_new(xbus_ops_t *ops) INFO("New xbus: %s\n", xbus->busname); init_waitqueue_head(&xbus->packet_cache_empty); atomic_set(&xbus->packet_counter, 0); + + /* poll related variables */ atomic_set(&xbus->count_poll_answers, 0); - init_waitqueue_head(&xbus->wait_for_polls); - init_rwsem(&xbus->in_use); + atomic_set(&xbus->count_xpds_to_initialize, 0); + atomic_set(&xbus->count_xpds_initialized, 0); INIT_LIST_HEAD(&xbus->poll_results); - init_completion(&xbus->xpds_initialized); + init_waitqueue_head(&xbus->wait_for_polls); + init_waitqueue_head(&xbus->wait_for_xpd_initialization); xbus->num_xpds = 0; + + init_rwsem(&xbus->in_use); xbus_reset_counters(xbus); /* Device-Model */ @@ -703,8 +715,11 @@ static int xbus_read_proc(char *page, char **start, off_t off, int count, int *e (xbus->hardware_exists) ? "connected" : "missing", xbus->bus_type ); - len += sprintf(page + len, "POLLS: %d/%d\n", atomic_read(&xbus->count_poll_answers), MAX_XPDS); - len += sprintf(page + len, "XPDS_READY: %s\n", (xbus->xpds_initialized.done) ? "YES" : "NO"); + len += sprintf(page + len, "POLLS: %d/%d\n", + atomic_read(&xbus->count_poll_answers), MAX_XPDS); + len += sprintf(page + len, "XPDS_READY: %d/%d\n", + atomic_read(&xbus->count_xpds_initialized), + atomic_read(&xbus->count_xpds_to_initialize)); len += sprintf(page + len, "\nmax_packet_size=%d open_counter=%d packet_count=%d\n", xbus->max_packet_size, xbus->open_counter, @@ -732,20 +747,29 @@ out: static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count, int *eof, void *data) { - int len = 0; - unsigned long flags; - xbus_t *xbus = data; - int i; + int len = 0; + unsigned long flags; + xbus_t *xbus = data; + int ret; if(!xbus) goto out; - i = wait_for_completion_interruptible_timeout(&xbus->xpds_initialized, 40*HZ); - if(i < 0) { - NOTICE("PID=%d waiting for XPDS initialization failed: %d\n", current->pid, i); - return i; + DBG("%s: Waiting for card initialization of %d XPD's max %d seconds\n", xbus->busname, MAX_XPDS, INITIALIZATION_TIMEOUT/HZ); + ret = wait_event_interruptible_timeout(xbus->wait_for_xpd_initialization, + atomic_read(&xbus->count_xpds_initialized) >= atomic_read(&xbus->count_xpds_to_initialize), + INITIALIZATION_TIMEOUT); + if(ret == 0) { + ERR("%s: Card Initialization Timeout\n", xbus->busname); + return ret; + } else if(ret < 0) { + ERR("%s: Card Initialization Interrupted %d\n", xbus->busname, ret); + return ret; } + DBG("%s: Finished initialization of %d XPD's in %d seconds.\n", xbus->busname, MAX_XPDS, (INITIALIZATION_TIMEOUT - ret)/HZ); spin_lock_irqsave(&xbus->lock, flags); - len += sprintf(page + len, "XPDS_READY: %s\n", (xbus->xpds_initialized.done) ? "YES" : "NO"); + len += sprintf(page + len, "XPDS_READY: %d/%d\n", + atomic_read(&xbus->count_xpds_initialized), + atomic_read(&xbus->count_xpds_to_initialize)); spin_unlock_irqrestore(&xbus->lock, flags); out: if (len <= off+count) |