Commit 2574740d authored by Alexandre Bounine's avatar Alexandre Bounine Committed by Linus Torvalds

rapidio: update asynchronous discovery initialization

Update discovery process initialization based on Andrew Morton's comments:

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: default avatarAlexandre Bounine <>
Cc: Matt Porter <>
Cc: Li Yang <>
Signed-off-by: default avatarAndrew Morton <>
Signed-off-by: default avatarLinus Torvalds <>
parent f4c9c0e8
...@@ -1275,49 +1275,68 @@ static void __devinit disc_work_handler(struct work_struct *_work) ...@@ -1275,49 +1275,68 @@ static void __devinit disc_work_handler(struct work_struct *_work)
pr_debug("RIO: discovery work for mport %d %s\n", pr_debug("RIO: discovery work for mport %d %s\n",
work->mport->id, work->mport->name); work->mport->id, work->mport->name);
rio_disc_mport(work->mport); rio_disc_mport(work->mport);
} }
int __devinit rio_init_mports(void) int __devinit rio_init_mports(void)
{ {
struct rio_mport *port; struct rio_mport *port;
struct rio_disc_work *work; struct rio_disc_work *work;
int no_disc = 0; int n = 0;
if (!next_portid)
return -ENODEV;
* First, run enumerations and check if we need to perform discovery
* on any of the registered mports.
list_for_each_entry(port, &rio_mports, node) { list_for_each_entry(port, &rio_mports, node) {
if (port->host_deviceid >= 0) if (port->host_deviceid >= 0)
rio_enum_mport(port); rio_enum_mport(port);
else if (!no_disc) { else
if (!rio_wq) { n++;
rio_wq = alloc_workqueue("riodisc", 0, 0); }
if (!rio_wq) {
pr_err("RIO: unable allocate rio_wq\n"); if (!n)
no_disc = 1; goto no_disc;
} /*
} * If we have mports that require discovery schedule a discovery work
* for each of them. If the code below fails to allocate needed
work = kzalloc(sizeof *work, GFP_KERNEL); * resources, exit without error to keep results of enumeration
if (!work) { * process (if any).
pr_err("RIO: no memory for work struct\n"); * TODO: Implement restart of dicovery process for all or
no_disc = 1; * individual discovering mports.
continue; */
} rio_wq = alloc_workqueue("riodisc", 0, 0);
if (!rio_wq) {
work->mport = port; pr_err("RIO: unable allocate rio_wq\n");
INIT_WORK(&work->work, disc_work_handler); goto no_disc;
queue_work(rio_wq, &work->work);
} }
if (rio_wq) { work = kcalloc(n, sizeof *work, GFP_KERNEL);
pr_debug("RIO: flush discovery workqueue\n"); if (!work) {
flush_workqueue(rio_wq); pr_err("RIO: no memory for work struct\n");
pr_debug("RIO: flush discovery workqueue finished\n");
destroy_workqueue(rio_wq); destroy_workqueue(rio_wq);
goto no_disc;
} }
n = 0;
list_for_each_entry(port, &rio_mports, node) {
if (port->host_deviceid < 0) {
work[n].mport = port;
INIT_WORK(&work[n].work, disc_work_handler);
queue_work(rio_wq, &work[n].work);
pr_debug("RIO: destroy discovery workqueue\n");
rio_init(); rio_init();
return 0; return 0;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment