summaryrefslogtreecommitdiff
path: root/xpp/xbus-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'xpp/xbus-core.c')
-rw-r--r--xpp/xbus-core.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/xpp/xbus-core.c b/xpp/xbus-core.c
index 9f73a86..59db079 100644
--- a/xpp/xbus-core.c
+++ b/xpp/xbus-core.c
@@ -33,7 +33,7 @@
#include <linux/ctype.h>
#endif
#include <linux/device.h>
-#include <linux/delay.h> /* for mdelay() to debug */
+#include <linux/delay.h> /* for msleep() to debug */
#include "xpd.h"
#include "xpp_zap.h"
#include "xbus-core.h"
@@ -42,7 +42,7 @@
static const char rcsid[] = "$Id$";
/* Defines */
-#define POLL_TIMEOUT (MAX_XPDS) /* in jiffies */
+#define POLL_TIMEOUT (2*MAX_XPDS) /* in jiffies */
#define INITIALIZATION_TIMEOUT (40*HZ) /* in jiffies */
#define PROC_XBUSES "xbuses"
#define PROC_XBUS_SUMMARY "summary"
@@ -55,6 +55,7 @@ static int proc_xbus_command_write(struct file *file, const char __user *buffer,
/* Command line parameters */
extern int print_dbg;
+DEF_PARM(uint, poll_timeout, POLL_TIMEOUT,"Timeout (in jiffies) waiting for units to reply (default " __stringify(POLL_TIMEOUT) ")");
/* Forward declarations */
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
@@ -226,7 +227,7 @@ static int xbus_poll(void *data)
ERR("%s is being removed...\n", xbus->busname);
return -EBUSY;
}
- mdelay(2); /* roundtrip for older polls */
+ msleep(2); /* roundtrip for older polls */
spin_lock_irqsave(&xbus->lock, flags);
DBG("%s\n", xbus->busname);
@@ -250,16 +251,18 @@ static int xbus_poll(void *data)
/*
* Wait for replies
*/
- 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);
+ 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;
+ ERR("%s: Poll timeout. Continuing anyway.\n", xbus->busname);
+ /*
+ * Continue processing. Maybe some units did reply.
+ */
} else if(ret < 0) {
ERR("%s: Poll interrupted %d\n", xbus->busname, ret);
goto out;
- }
- DBG("%s: Poll finished in %d jiffies. Start processing.\n", xbus->busname, POLL_TIMEOUT - ret);
+ } else
+ DBG("%s: Poll finished in %d jiffies.\n", xbus->busname, poll_timeout - ret);
/*
* Build removals/additions lists
*/
@@ -288,6 +291,10 @@ static int xbus_poll(void *data)
kfree(card_desc);
}
}
+ /*
+ * We set this *after* poll is finished, so wait_for_xpd_initialization can
+ * tell we already know how many units we have.
+ */
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);
@@ -659,7 +666,14 @@ static int xbus_read_waitfor_xpds(char *page, char **start, off_t off, int count
if(!xbus)
goto out;
DBG("%s: Waiting for card initialization of %d XPD's max %d seconds\n", xbus->busname, MAX_XPDS, INITIALIZATION_TIMEOUT/HZ);
+ /*
+ * xbus_poll sets count_xpds_to_initialize only when polling is finished.
+ * To prevent race conditions we test both:
+ * - It is none zero -- meaning we already have the poll results.
+ * - And all units have finished initialization.
+ */
ret = wait_event_interruptible_timeout(xbus->wait_for_xpd_initialization,
+ atomic_read(&xbus->count_xpds_to_initialize) &&
atomic_read(&xbus->count_xpds_initialized) >= atomic_read(&xbus->count_xpds_to_initialize),
INITIALIZATION_TIMEOUT);
if(ret == 0) {