summaryrefslogtreecommitdiffstats
path: root/drivers/rapidio/rio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rapidio/rio.c')
-rw-r--r--drivers/rapidio/rio.c51
1 files changed, 49 insertions, 2 deletions
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index d7b68cc2d843..d4bd69013c50 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1260,15 +1260,62 @@ static int __devinit rio_init(void)
return 0;
}
+static struct workqueue_struct *rio_wq;
+
+struct rio_disc_work {
+ struct work_struct work;
+ struct rio_mport *mport;
+};
+
+static void __devinit disc_work_handler(struct work_struct *_work)
+{
+ struct rio_disc_work *work;
+
+ work = container_of(_work, struct rio_disc_work, work);
+ pr_debug("RIO: discovery work for mport %d %s\n",
+ work->mport->id, work->mport->name);
+ rio_disc_mport(work->mport);
+
+ kfree(work);
+}
+
int __devinit rio_init_mports(void)
{
struct rio_mport *port;
+ struct rio_disc_work *work;
+ int no_disc = 0;
list_for_each_entry(port, &rio_mports, node) {
if (port->host_deviceid >= 0)
rio_enum_mport(port);
- else
- rio_disc_mport(port);
+ else if (!no_disc) {
+ if (!rio_wq) {
+ rio_wq = alloc_workqueue("riodisc", 0, 0);
+ if (!rio_wq) {
+ pr_err("RIO: unable allocate rio_wq\n");
+ no_disc = 1;
+ continue;
+ }
+ }
+
+ work = kzalloc(sizeof *work, GFP_KERNEL);
+ if (!work) {
+ pr_err("RIO: no memory for work struct\n");
+ no_disc = 1;
+ continue;
+ }
+
+ work->mport = port;
+ INIT_WORK(&work->work, disc_work_handler);
+ queue_work(rio_wq, &work->work);
+ }
+ }
+
+ if (rio_wq) {
+ pr_debug("RIO: flush discovery workqueue\n");
+ flush_workqueue(rio_wq);
+ pr_debug("RIO: flush discovery workqueue finished\n");
+ destroy_workqueue(rio_wq);
}
rio_init();