aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2012-10-04 20:16:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-05 14:05:22 -0400
commit005842efd1ac8ef455ebd28a8c713944863edc5a (patch)
tree9aea8b929ab5efc237d699cc36a4bed6adb51ad4 /drivers/rapidio
parenta7071efc20567f4b6c454ff93ca80daf51bf93e9 (diff)
rapidio: run discovery as an asynchronous process
Modify mport initialization routine to run the RapidIO discovery process asynchronously. This allows to have an arbitrary order of enumerating and discovering ports in systems with multiple RapidIO controllers without creating a deadlock situation if enumerator port is registered after a discovering one. Making netID matching to mportID ensures consistent net ID assignment in multiport RapidIO systems with asynchronous discovery process (global counter implementation is affected by race between threads). [akpm@linux-foundation.org: tweak code layput] Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com> Cc: Matt Porter <mporter@kernel.crashing.org> Cc: Li Yang <leoli@freescale.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio')
-rw-r--r--drivers/rapidio/rio-scan.c3
-rw-r--r--drivers/rapidio/rio.c51
2 files changed, 50 insertions, 4 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 8b7c4bce7a4a..745670f535e8 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -44,7 +44,6 @@ static void rio_init_em(struct rio_dev *rdev);
44DEFINE_SPINLOCK(rio_global_list_lock); 44DEFINE_SPINLOCK(rio_global_list_lock);
45 45
46static int next_destid = 0; 46static int next_destid = 0;
47static int next_net = 0;
48static int next_comptag = 1; 47static int next_comptag = 1;
49 48
50static int rio_mport_phys_table[] = { 49static int rio_mport_phys_table[] = {
@@ -1062,7 +1061,7 @@ static struct rio_net __devinit *rio_alloc_net(struct rio_mport *port)
1062 INIT_LIST_HEAD(&net->mports); 1061 INIT_LIST_HEAD(&net->mports);
1063 list_add_tail(&port->nnode, &net->mports); 1062 list_add_tail(&port->nnode, &net->mports);
1064 net->hport = port; 1063 net->hport = port;
1065 net->id = next_net++; 1064 net->id = port->id;
1066 } 1065 }
1067 return net; 1066 return net;
1068} 1067}
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)
1260 return 0; 1260 return 0;
1261} 1261}
1262 1262
1263static struct workqueue_struct *rio_wq;
1264
1265struct rio_disc_work {
1266 struct work_struct work;
1267 struct rio_mport *mport;
1268};
1269
1270static void __devinit disc_work_handler(struct work_struct *_work)
1271{
1272 struct rio_disc_work *work;
1273
1274 work = container_of(_work, struct rio_disc_work, work);
1275 pr_debug("RIO: discovery work for mport %d %s\n",
1276 work->mport->id, work->mport->name);
1277 rio_disc_mport(work->mport);
1278
1279 kfree(work);
1280}
1281
1263int __devinit rio_init_mports(void) 1282int __devinit rio_init_mports(void)
1264{ 1283{
1265 struct rio_mport *port; 1284 struct rio_mport *port;
1285 struct rio_disc_work *work;
1286 int no_disc = 0;
1266 1287
1267 list_for_each_entry(port, &rio_mports, node) { 1288 list_for_each_entry(port, &rio_mports, node) {
1268 if (port->host_deviceid >= 0) 1289 if (port->host_deviceid >= 0)
1269 rio_enum_mport(port); 1290 rio_enum_mport(port);
1270 else 1291 else if (!no_disc) {
1271 rio_disc_mport(port); 1292 if (!rio_wq) {
1293 rio_wq = alloc_workqueue("riodisc", 0, 0);
1294 if (!rio_wq) {
1295 pr_err("RIO: unable allocate rio_wq\n");
1296 no_disc = 1;
1297 continue;
1298 }
1299 }
1300
1301 work = kzalloc(sizeof *work, GFP_KERNEL);
1302 if (!work) {
1303 pr_err("RIO: no memory for work struct\n");
1304 no_disc = 1;
1305 continue;
1306 }
1307
1308 work->mport = port;
1309 INIT_WORK(&work->work, disc_work_handler);
1310 queue_work(rio_wq, &work->work);
1311 }
1312 }
1313
1314 if (rio_wq) {
1315 pr_debug("RIO: flush discovery workqueue\n");
1316 flush_workqueue(rio_wq);
1317 pr_debug("RIO: flush discovery workqueue finished\n");
1318 destroy_workqueue(rio_wq);
1272 } 1319 }
1273 1320
1274 rio_init(); 1321 rio_init();