aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio/rio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/rapidio/rio.c')
-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;