Skip to content

Commit 2574740

Browse files
Alexandre Bouninetorvalds
authored andcommitted
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>
1 parent f4c9c0e commit 2574740

File tree

1 file changed

+47
-28
lines changed

1 file changed

+47
-28
lines changed

drivers/rapidio/rio.c

Lines changed: 47 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1275,49 +1275,68 @@ static void __devinit disc_work_handler(struct work_struct *_work)
12751275
pr_debug("RIO: discovery work for mport %d %s\n",
12761276
work->mport->id, work->mport->name);
12771277
rio_disc_mport(work->mport);
1278-
1279-
kfree(work);
12801278
}
12811279

12821280
int __devinit rio_init_mports(void)
12831281
{
12841282
struct rio_mport *port;
12851283
struct rio_disc_work *work;
1286-
int no_disc = 0;
1284+
int n = 0;
1285+
1286+
if (!next_portid)
1287+
return -ENODEV;
12871288

1289+
/*
1290+
* First, run enumerations and check if we need to perform discovery
1291+
* on any of the registered mports.
1292+
*/
12881293
list_for_each_entry(port, &rio_mports, node) {
12891294
if (port->host_deviceid >= 0)
12901295
rio_enum_mport(port);
1291-
else if (!no_disc) {
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-
}
1296+
else
1297+
n++;
1298+
}
1299+
1300+
if (!n)
1301+
goto no_disc;
1302+
1303+
/*
1304+
* If we have mports that require discovery schedule a discovery work
1305+
* for each of them. If the code below fails to allocate needed
1306+
* resources, exit without error to keep results of enumeration
1307+
* process (if any).
1308+
* TODO: Implement restart of dicovery process for all or
1309+
* individual discovering mports.
1310+
*/
1311+
rio_wq = alloc_workqueue("riodisc", 0, 0);
1312+
if (!rio_wq) {
1313+
pr_err("RIO: unable allocate rio_wq\n");
1314+
goto no_disc;
13121315
}
13131316

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");
1317+
work = kcalloc(n, sizeof *work, GFP_KERNEL);
1318+
if (!work) {
1319+
pr_err("RIO: no memory for work struct\n");
13181320
destroy_workqueue(rio_wq);
1321+
goto no_disc;
13191322
}
13201323

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+
1339+
no_disc:
13211340
rio_init();
13221341

13231342
return 0;

0 commit comments

Comments
 (0)