aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2012-10-10 18:53:59 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-10 19:50:15 -0400
commit2574740d1fe946803caa6b0c06fbb4bf397af35d (patch)
tree50bdf80ba048dd462f3b23f13a7f636401448565
parentf4c9c0e83bdfab6d3de7bc9ad728d99bf6adde92 (diff)
rapidio: update asynchronous discovery initialization
Update discovery process initialization based on Andrew Morton's comments: https://lkml.org/lkml/2012/10/3/552. This update processes all enumerating mports first and schedules discovery work after that. If the initialization routine fails to allocate resources needed to execute discovery, it abandons discovery for all ports. 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>
-rw-r--r--drivers/rapidio/rio.c75
1 files changed, 47 insertions, 28 deletions
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index d4bd69013c50..c17ae22567e0 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1275,49 +1275,68 @@ static void __devinit disc_work_handler(struct work_struct *_work)
1275 pr_debug("RIO: discovery work for mport %d %s\n", 1275 pr_debug("RIO: discovery work for mport %d %s\n",
1276 work->mport->id, work->mport->name); 1276 work->mport->id, work->mport->name);
1277 rio_disc_mport(work->mport); 1277 rio_disc_mport(work->mport);
1278
1279 kfree(work);
1280} 1278}
1281 1279
1282int __devinit rio_init_mports(void) 1280int __devinit rio_init_mports(void)
1283{ 1281{
1284 struct rio_mport *port; 1282 struct rio_mport *port;
1285 struct rio_disc_work *work; 1283 struct rio_disc_work *work;
1286 int no_disc = 0; 1284 int n = 0;
1285
1286 if (!next_portid)
1287 return -ENODEV;
1287 1288
1289 /*
1290 * First, run enumerations and check if we need to perform discovery
1291 * on any of the registered mports.
1292 */
1288 list_for_each_entry(port, &rio_mports, node) { 1293 list_for_each_entry(port, &rio_mports, node) {
1289 if (port->host_deviceid >= 0) 1294 if (port->host_deviceid >= 0)
1290 rio_enum_mport(port); 1295 rio_enum_mport(port);
1291 else if (!no_disc) { 1296 else
1292 if (!rio_wq) { 1297 n++;
1293 rio_wq = alloc_workqueue("riodisc", 0, 0); 1298 }
1294 if (!rio_wq) { 1299
1295 pr_err("RIO: unable allocate rio_wq\n"); 1300 if (!n)
1296 no_disc = 1; 1301 goto no_disc;
1297 continue; 1302
1298 } 1303 /*
1299 } 1304 * If we have mports that require discovery schedule a discovery work
1300 1305 * for each of them. If the code below fails to allocate needed
1301 work = kzalloc(sizeof *work, GFP_KERNEL); 1306 * resources, exit without error to keep results of enumeration
1302 if (!work) { 1307 * process (if any).
1303 pr_err("RIO: no memory for work struct\n"); 1308 * TODO: Implement restart of dicovery process for all or
1304 no_disc = 1; 1309 * individual discovering mports.
1305 continue; 1310 */
1306 } 1311 rio_wq = alloc_workqueue("riodisc", 0, 0);
1307 1312 if (!rio_wq) {
1308 work->mport = port; 1313 pr_err("RIO: unable allocate rio_wq\n");
1309 INIT_WORK(&work->work, disc_work_handler); 1314 goto no_disc;
1310 queue_work(rio_wq, &work->work);
1311 }
1312 } 1315 }
1313 1316
1314 if (rio_wq) { 1317 work = kcalloc(n, sizeof *work, GFP_KERNEL);
1315 pr_debug("RIO: flush discovery workqueue\n"); 1318 if (!work) {
1316 flush_workqueue(rio_wq); 1319 pr_err("RIO: no memory for work struct\n");
1317 pr_debug("RIO: flush discovery workqueue finished\n");
1318 destroy_workqueue(rio_wq); 1320 destroy_workqueue(rio_wq);
1321 goto no_disc;
1319 } 1322 }
1320 1323
1324 n = 0;
1325 list_for_each_entry(port, &rio_mports, node) {
1326 if (port->host_deviceid < 0) {
1327 work[n].mport = port;
1328 INIT_WORK(&work[n].work, disc_work_handler);
1329 queue_work(rio_wq, &work[n].work);
1330 n++;
1331 }
1332 }
1333
1334 flush_workqueue(rio_wq);
1335 pr_debug("RIO: destroy discovery workqueue\n");
1336 destroy_workqueue(rio_wq);
1337 kfree(work);
1338
1339no_disc:
1321 rio_init(); 1340 rio_init();
1322 1341
1323 return 0; 1342 return 0;