Commit a11650e11093ed57dca78bf16e7836517c599098

Authored by Alexandre Bounine
Committed by Linus Torvalds
1 parent 585dc0c2f6

rapidio: make enumeration/discovery configurable

Systems that use RapidIO fabric may need to implement their own
enumeration and discovery methods which are better suitable for needs of
a target application.

The following set of patches is intended to simplify process of
introduction of new RapidIO fabric enumeration/discovery methods.

The first patch offers ability to add new RapidIO enumeration/discovery
methods using kernel configuration options.  This new configuration
option mechanism allows to select statically linked or modular
enumeration/discovery method(s) from the list of existing methods or use
external module(s).

This patch also updates the currently existing enumeration/discovery
code to be used as a statically linked or modular method.

The corresponding configuration option is named "Basic
enumeration/discovery" method.  This is the only one configuration
option available today but new methods are expected to be introduced
after adoption of provided patches.

The second patch address a long time complaint of RapidIO subsystem
users regarding fabric enumeration/discovery start sequence.  Existing
implementation offers only a boot-time enumeration/discovery start which
requires synchronized boot of all endpoints in RapidIO network.  While
it works for small closed configurations with limited number of
endpoints, using this approach in systems with large number of endpoints
is quite challenging.

To eliminate requirement for synchronized start the second patch
introduces RapidIO enumeration/discovery start from user space.

For compatibility with the existing RapidIO subsystem implementation,
automatic boot time enumeration/discovery start can be configured in by
specifying "rio-scan.scan=1" command line parameter if statically linked
basic enumeration method is selected.

This patch:

Rework to implement RapidIO enumeration/discovery method selection
combined with ability to use enumeration/discovery as a kernel module.

This patch adds ability to introduce new RapidIO enumeration/discovery
methods using kernel configuration options.  Configuration option
mechanism allows to select statically linked or modular
enumeration/discovery method from the list of existing methods or use
external modules.  If a modular enumeration/discovery is selected each
RapidIO mport device can have its own method attached to it.

The existing enumeration/discovery code was updated to be used as
statically linked or modular method.  This configuration option is named
"Basic enumeration/discovery" method.

Several common routines have been moved from rio-scan.c to make them
available to other enumeration methods and reduce number of exported
symbols.

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
Cc: Li Yang <leoli@freescale.com>
Cc: Kumar Gala <galak@kernel.crashing.org>
Cc: Andre van Herk <andre.van.herk@Prodrive.nl>
Cc: Micha Nelissen <micha.nelissen@Prodrive.nl>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

Showing 8 changed files with 304 additions and 139 deletions Side-by-side Diff

drivers/rapidio/Kconfig
... ... @@ -47,5 +47,25 @@
47 47  
48 48 If you are unsure about this, say N here.
49 49  
  50 +choice
  51 + prompt "Enumeration method"
  52 + depends on RAPIDIO
  53 + default RAPIDIO_ENUM_BASIC
  54 + help
  55 + There are different enumeration and discovery mechanisms offered
  56 + for RapidIO subsystem. You may select single built-in method or
  57 + or any number of methods to be built as modules.
  58 + Selecting a built-in method disables use of loadable methods.
  59 +
  60 + If unsure, select Basic built-in.
  61 +
  62 +config RAPIDIO_ENUM_BASIC
  63 + tristate "Basic"
  64 + help
  65 + This option includes basic RapidIO fabric enumeration and discovery
  66 + mechanism similar to one described in RapidIO specification Annex 1.
  67 +
  68 +endchoice
  69 +
50 70 source "drivers/rapidio/switches/Kconfig"
drivers/rapidio/Makefile
1 1 #
2 2 # Makefile for RapidIO interconnect services
3 3 #
4   -obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
  4 +obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o
  5 +obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o
5 6  
6 7 obj-$(CONFIG_RAPIDIO) += switches/
7 8 obj-$(CONFIG_RAPIDIO) += devices/
drivers/rapidio/rio-driver.c
... ... @@ -164,6 +164,13 @@
164 164 driver_unregister(&rdrv->driver);
165 165 }
166 166  
  167 +void rio_attach_device(struct rio_dev *rdev)
  168 +{
  169 + rdev->dev.bus = &rio_bus_type;
  170 + rdev->dev.parent = &rio_bus;
  171 +}
  172 +EXPORT_SYMBOL_GPL(rio_attach_device);
  173 +
167 174 /**
168 175 * rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure
169 176 * @dev: the standard device structure to match against
drivers/rapidio/rio-scan.c
... ... @@ -37,12 +37,8 @@
37 37  
38 38 #include "rio.h"
39 39  
40   -LIST_HEAD(rio_devices);
41   -
42 40 static void rio_init_em(struct rio_dev *rdev);
43 41  
44   -DEFINE_SPINLOCK(rio_global_list_lock);
45   -
46 42 static int next_destid = 0;
47 43 static int next_comptag = 1;
48 44  
... ... @@ -327,127 +323,6 @@
327 323 }
328 324  
329 325 /**
330   - * rio_switch_init - Sets switch operations for a particular vendor switch
331   - * @rdev: RIO device
332   - * @do_enum: Enumeration/Discovery mode flag
333   - *
334   - * Searches the RIO switch ops table for known switch types. If the vid
335   - * and did match a switch table entry, then call switch initialization
336   - * routine to setup switch-specific routines.
337   - */
338   -static void rio_switch_init(struct rio_dev *rdev, int do_enum)
339   -{
340   - struct rio_switch_ops *cur = __start_rio_switch_ops;
341   - struct rio_switch_ops *end = __end_rio_switch_ops;
342   -
343   - while (cur < end) {
344   - if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
345   - pr_debug("RIO: calling init routine for %s\n",
346   - rio_name(rdev));
347   - cur->init_hook(rdev, do_enum);
348   - break;
349   - }
350   - cur++;
351   - }
352   -
353   - if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
354   - pr_debug("RIO: adding STD routing ops for %s\n",
355   - rio_name(rdev));
356   - rdev->rswitch->add_entry = rio_std_route_add_entry;
357   - rdev->rswitch->get_entry = rio_std_route_get_entry;
358   - rdev->rswitch->clr_table = rio_std_route_clr_table;
359   - }
360   -
361   - if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
362   - printk(KERN_ERR "RIO: missing routing ops for %s\n",
363   - rio_name(rdev));
364   -}
365   -
366   -/**
367   - * rio_add_device- Adds a RIO device to the device model
368   - * @rdev: RIO device
369   - *
370   - * Adds the RIO device to the global device list and adds the RIO
371   - * device to the RIO device list. Creates the generic sysfs nodes
372   - * for an RIO device.
373   - */
374   -static int rio_add_device(struct rio_dev *rdev)
375   -{
376   - int err;
377   -
378   - err = device_add(&rdev->dev);
379   - if (err)
380   - return err;
381   -
382   - spin_lock(&rio_global_list_lock);
383   - list_add_tail(&rdev->global_list, &rio_devices);
384   - spin_unlock(&rio_global_list_lock);
385   -
386   - rio_create_sysfs_dev_files(rdev);
387   -
388   - return 0;
389   -}
390   -
391   -/**
392   - * rio_enable_rx_tx_port - enable input receiver and output transmitter of
393   - * given port
394   - * @port: Master port associated with the RIO network
395   - * @local: local=1 select local port otherwise a far device is reached
396   - * @destid: Destination ID of the device to check host bit
397   - * @hopcount: Number of hops to reach the target
398   - * @port_num: Port (-number on switch) to enable on a far end device
399   - *
400   - * Returns 0 or 1 from on General Control Command and Status Register
401   - * (EXT_PTR+0x3C)
402   - */
403   -inline int rio_enable_rx_tx_port(struct rio_mport *port,
404   - int local, u16 destid,
405   - u8 hopcount, u8 port_num) {
406   -#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
407   - u32 regval;
408   - u32 ext_ftr_ptr;
409   -
410   - /*
411   - * enable rx input tx output port
412   - */
413   - pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
414   - "%d, port_num = %d)\n", local, destid, hopcount, port_num);
415   -
416   - ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
417   -
418   - if (local) {
419   - rio_local_read_config_32(port, ext_ftr_ptr +
420   - RIO_PORT_N_CTL_CSR(0),
421   - &regval);
422   - } else {
423   - if (rio_mport_read_config_32(port, destid, hopcount,
424   - ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
425   - return -EIO;
426   - }
427   -
428   - if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
429   - /* serial */
430   - regval = regval | RIO_PORT_N_CTL_EN_RX_SER
431   - | RIO_PORT_N_CTL_EN_TX_SER;
432   - } else {
433   - /* parallel */
434   - regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
435   - | RIO_PORT_N_CTL_EN_TX_PAR;
436   - }
437   -
438   - if (local) {
439   - rio_local_write_config_32(port, ext_ftr_ptr +
440   - RIO_PORT_N_CTL_CSR(0), regval);
441   - } else {
442   - if (rio_mport_write_config_32(port, destid, hopcount,
443   - ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
444   - return -EIO;
445   - }
446   -#endif
447   - return 0;
448   -}
449   -
450   -/**
451 326 * rio_setup_device- Allocates and sets up a RIO device
452 327 * @net: RIO network
453 328 * @port: Master port to send transactions
... ... @@ -587,8 +462,7 @@
587 462 rdev->destid);
588 463 }
589 464  
590   - rdev->dev.bus = &rio_bus_type;
591   - rdev->dev.parent = &rio_bus;
  465 + rio_attach_device(rdev);
592 466  
593 467 device_initialize(&rdev->dev);
594 468 rdev->dev.release = rio_release_dev;
... ... @@ -1421,4 +1295,42 @@
1421 1295 bail:
1422 1296 return -EBUSY;
1423 1297 }
  1298 +
  1299 +static struct rio_scan rio_scan_ops = {
  1300 + .enumerate = rio_enum_mport,
  1301 + .discover = rio_disc_mport,
  1302 +};
  1303 +
  1304 +static bool scan;
  1305 +module_param(scan, bool, 0);
  1306 +MODULE_PARM_DESC(scan, "Start RapidIO network enumeration/discovery "
  1307 + "(default = 0)");
  1308 +
  1309 +/**
  1310 + * rio_basic_attach:
  1311 + *
  1312 + * When this enumeration/discovery method is loaded as a module this function
  1313 + * registers its specific enumeration and discover routines for all available
  1314 + * RapidIO mport devices. The "scan" command line parameter controls ability of
  1315 + * the module to start RapidIO enumeration/discovery automatically.
  1316 + *
  1317 + * Returns 0 for success or -EIO if unable to register itself.
  1318 + *
  1319 + * This enumeration/discovery method cannot be unloaded and therefore does not
  1320 + * provide a matching cleanup_module routine.
  1321 + */
  1322 +
  1323 +static int __init rio_basic_attach(void)
  1324 +{
  1325 + if (rio_register_scan(RIO_MPORT_ANY, &rio_scan_ops))
  1326 + return -EIO;
  1327 + if (scan)
  1328 + rio_init_mports();
  1329 + return 0;
  1330 +}
  1331 +
  1332 +late_initcall(rio_basic_attach);
  1333 +
  1334 +MODULE_DESCRIPTION("Basic RapidIO enumeration/discovery");
  1335 +MODULE_LICENSE("GPL");
drivers/rapidio/rio.c
... ... @@ -31,7 +31,11 @@
31 31  
32 32 #include "rio.h"
33 33  
  34 +static LIST_HEAD(rio_devices);
  35 +static DEFINE_SPINLOCK(rio_global_list_lock);
  36 +
34 37 static LIST_HEAD(rio_mports);
  38 +static DEFINE_MUTEX(rio_mport_list_lock);
35 39 static unsigned char next_portid;
36 40 static DEFINE_SPINLOCK(rio_mmap_lock);
37 41  
... ... @@ -53,6 +57,32 @@
53 57 }
54 58  
55 59 /**
  60 + * rio_add_device- Adds a RIO device to the device model
  61 + * @rdev: RIO device
  62 + *
  63 + * Adds the RIO device to the global device list and adds the RIO
  64 + * device to the RIO device list. Creates the generic sysfs nodes
  65 + * for an RIO device.
  66 + */
  67 +int rio_add_device(struct rio_dev *rdev)
  68 +{
  69 + int err;
  70 +
  71 + err = device_add(&rdev->dev);
  72 + if (err)
  73 + return err;
  74 +
  75 + spin_lock(&rio_global_list_lock);
  76 + list_add_tail(&rdev->global_list, &rio_devices);
  77 + spin_unlock(&rio_global_list_lock);
  78 +
  79 + rio_create_sysfs_dev_files(rdev);
  80 +
  81 + return 0;
  82 +}
  83 +EXPORT_SYMBOL_GPL(rio_add_device);
  84 +
  85 +/**
56 86 * rio_request_inb_mbox - request inbound mailbox service
57 87 * @mport: RIO master port from which to allocate the mailbox resource
58 88 * @dev_id: Device specific pointer to pass on event
... ... @@ -489,6 +519,7 @@
489 519  
490 520 return ext_ftr_ptr;
491 521 }
  522 +EXPORT_SYMBOL_GPL(rio_mport_get_physefb);
492 523  
493 524 /**
494 525 * rio_get_comptag - Begin or continue searching for a RIO device by component tag
... ... @@ -521,6 +552,7 @@
521 552 spin_unlock(&rio_global_list_lock);
522 553 return rdev;
523 554 }
  555 +EXPORT_SYMBOL_GPL(rio_get_comptag);
524 556  
525 557 /**
526 558 * rio_set_port_lockout - Sets/clears LOCKOUT bit (RIO EM 1.3) for a switch port.
527 559  
... ... @@ -545,8 +577,109 @@
545 577 regval);
546 578 return 0;
547 579 }
  580 +EXPORT_SYMBOL_GPL(rio_set_port_lockout);
548 581  
549 582 /**
  583 + * rio_switch_init - Sets switch operations for a particular vendor switch
  584 + * @rdev: RIO device
  585 + * @do_enum: Enumeration/Discovery mode flag
  586 + *
  587 + * Searches the RIO switch ops table for known switch types. If the vid
  588 + * and did match a switch table entry, then call switch initialization
  589 + * routine to setup switch-specific routines.
  590 + */
  591 +void rio_switch_init(struct rio_dev *rdev, int do_enum)
  592 +{
  593 + struct rio_switch_ops *cur = __start_rio_switch_ops;
  594 + struct rio_switch_ops *end = __end_rio_switch_ops;
  595 +
  596 + while (cur < end) {
  597 + if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
  598 + pr_debug("RIO: calling init routine for %s\n",
  599 + rio_name(rdev));
  600 + cur->init_hook(rdev, do_enum);
  601 + break;
  602 + }
  603 + cur++;
  604 + }
  605 +
  606 + if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
  607 + pr_debug("RIO: adding STD routing ops for %s\n",
  608 + rio_name(rdev));
  609 + rdev->rswitch->add_entry = rio_std_route_add_entry;
  610 + rdev->rswitch->get_entry = rio_std_route_get_entry;
  611 + rdev->rswitch->clr_table = rio_std_route_clr_table;
  612 + }
  613 +
  614 + if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
  615 + printk(KERN_ERR "RIO: missing routing ops for %s\n",
  616 + rio_name(rdev));
  617 +}
  618 +EXPORT_SYMBOL_GPL(rio_switch_init);
  619 +
  620 +/**
  621 + * rio_enable_rx_tx_port - enable input receiver and output transmitter of
  622 + * given port
  623 + * @port: Master port associated with the RIO network
  624 + * @local: local=1 select local port otherwise a far device is reached
  625 + * @destid: Destination ID of the device to check host bit
  626 + * @hopcount: Number of hops to reach the target
  627 + * @port_num: Port (-number on switch) to enable on a far end device
  628 + *
  629 + * Returns 0 or 1 from on General Control Command and Status Register
  630 + * (EXT_PTR+0x3C)
  631 + */
  632 +int rio_enable_rx_tx_port(struct rio_mport *port,
  633 + int local, u16 destid,
  634 + u8 hopcount, u8 port_num)
  635 +{
  636 +#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
  637 + u32 regval;
  638 + u32 ext_ftr_ptr;
  639 +
  640 + /*
  641 + * enable rx input tx output port
  642 + */
  643 + pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
  644 + "%d, port_num = %d)\n", local, destid, hopcount, port_num);
  645 +
  646 + ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);
  647 +
  648 + if (local) {
  649 + rio_local_read_config_32(port, ext_ftr_ptr +
  650 + RIO_PORT_N_CTL_CSR(0),
  651 + &regval);
  652 + } else {
  653 + if (rio_mport_read_config_32(port, destid, hopcount,
  654 + ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
  655 + return -EIO;
  656 + }
  657 +
  658 + if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
  659 + /* serial */
  660 + regval = regval | RIO_PORT_N_CTL_EN_RX_SER
  661 + | RIO_PORT_N_CTL_EN_TX_SER;
  662 + } else {
  663 + /* parallel */
  664 + regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
  665 + | RIO_PORT_N_CTL_EN_TX_PAR;
  666 + }
  667 +
  668 + if (local) {
  669 + rio_local_write_config_32(port, ext_ftr_ptr +
  670 + RIO_PORT_N_CTL_CSR(0), regval);
  671 + } else {
  672 + if (rio_mport_write_config_32(port, destid, hopcount,
  673 + ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
  674 + return -EIO;
  675 + }
  676 +#endif
  677 + return 0;
  678 +}
  679 +EXPORT_SYMBOL_GPL(rio_enable_rx_tx_port);
  680 +
  681 +
  682 +/**
550 683 * rio_chk_dev_route - Validate route to the specified device.
551 684 * @rdev: RIO device failed to respond
552 685 * @nrdev: Last active device on the route to rdev
... ... @@ -610,6 +743,7 @@
610 743  
611 744 return 0;
612 745 }
  746 +EXPORT_SYMBOL_GPL(rio_mport_chk_dev_access);
613 747  
614 748 /**
615 749 * rio_chk_dev_access - Validate access to the specified device.
... ... @@ -941,6 +1075,7 @@
941 1075 return RIO_GET_BLOCK_ID(reg_val);
942 1076 }
943 1077 }
  1078 +EXPORT_SYMBOL_GPL(rio_mport_get_efb);
944 1079  
945 1080 /**
946 1081 * rio_mport_get_feature - query for devices' extended features
... ... @@ -997,6 +1132,7 @@
997 1132  
998 1133 return 0;
999 1134 }
  1135 +EXPORT_SYMBOL_GPL(rio_mport_get_feature);
1000 1136  
1001 1137 /**
1002 1138 * rio_get_asm - Begin or continue searching for a RIO device by vid/did/asm_vid/asm_did
... ... @@ -1246,6 +1382,71 @@
1246 1382  
1247 1383 #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
1248 1384  
  1385 +/**
  1386 + * rio_register_scan - enumeration/discovery method registration interface
  1387 + * @mport_id: mport device ID for which fabric scan routine has to be set
  1388 + * (RIO_MPORT_ANY = set for all available mports)
  1389 + * @scan_ops: enumeration/discovery control structure
  1390 + *
  1391 + * Assigns enumeration or discovery method to the specified mport device (or all
  1392 + * available mports if RIO_MPORT_ANY is specified).
  1393 + * Returns error if the mport already has an enumerator attached to it.
  1394 + * In case of RIO_MPORT_ANY ignores ports with valid scan routines and returns
  1395 + * an error if was unable to find at least one available mport.
  1396 + */
  1397 +int rio_register_scan(int mport_id, struct rio_scan *scan_ops)
  1398 +{
  1399 + struct rio_mport *port;
  1400 + int rc = -EBUSY;
  1401 +
  1402 + mutex_lock(&rio_mport_list_lock);
  1403 + list_for_each_entry(port, &rio_mports, node) {
  1404 + if (port->id == mport_id || mport_id == RIO_MPORT_ANY) {
  1405 + if (port->nscan && mport_id == RIO_MPORT_ANY)
  1406 + continue;
  1407 + else if (port->nscan)
  1408 + break;
  1409 +
  1410 + port->nscan = scan_ops;
  1411 + rc = 0;
  1412 +
  1413 + if (mport_id != RIO_MPORT_ANY)
  1414 + break;
  1415 + }
  1416 + }
  1417 + mutex_unlock(&rio_mport_list_lock);
  1418 +
  1419 + return rc;
  1420 +}
  1421 +EXPORT_SYMBOL_GPL(rio_register_scan);
  1422 +
  1423 +/**
  1424 + * rio_unregister_scan - removes enumeration/discovery method from mport
  1425 + * @mport_id: mport device ID for which fabric scan routine has to be
  1426 + * unregistered (RIO_MPORT_ANY = set for all available mports)
  1427 + *
  1428 + * Removes enumeration or discovery method assigned to the specified mport
  1429 + * device (or all available mports if RIO_MPORT_ANY is specified).
  1430 + */
  1431 +int rio_unregister_scan(int mport_id)
  1432 +{
  1433 + struct rio_mport *port;
  1434 +
  1435 + mutex_lock(&rio_mport_list_lock);
  1436 + list_for_each_entry(port, &rio_mports, node) {
  1437 + if (port->id == mport_id || mport_id == RIO_MPORT_ANY) {
  1438 + if (port->nscan)
  1439 + port->nscan = NULL;
  1440 + if (mport_id != RIO_MPORT_ANY)
  1441 + break;
  1442 + }
  1443 + }
  1444 + mutex_unlock(&rio_mport_list_lock);
  1445 +
  1446 + return 0;
  1447 +}
  1448 +EXPORT_SYMBOL_GPL(rio_unregister_scan);
  1449 +
1249 1450 static void rio_fixup_device(struct rio_dev *dev)
1250 1451 {
1251 1452 }
... ... @@ -1274,7 +1475,7 @@
1274 1475 work = container_of(_work, struct rio_disc_work, work);
1275 1476 pr_debug("RIO: discovery work for mport %d %s\n",
1276 1477 work->mport->id, work->mport->name);
1277   - rio_disc_mport(work->mport);
  1478 + work->mport->nscan->discover(work->mport);
1278 1479 }
1279 1480  
1280 1481 int rio_init_mports(void)
1281 1482  
1282 1483  
... ... @@ -1290,12 +1491,15 @@
1290 1491 * First, run enumerations and check if we need to perform discovery
1291 1492 * on any of the registered mports.
1292 1493 */
  1494 + mutex_lock(&rio_mport_list_lock);
1293 1495 list_for_each_entry(port, &rio_mports, node) {
1294   - if (port->host_deviceid >= 0)
1295   - rio_enum_mport(port);
1296   - else
  1496 + if (port->host_deviceid >= 0) {
  1497 + if (port->nscan)
  1498 + port->nscan->enumerate(port);
  1499 + } else
1297 1500 n++;
1298 1501 }
  1502 + mutex_unlock(&rio_mport_list_lock);
1299 1503  
1300 1504 if (!n)
1301 1505 goto no_disc;
1302 1506  
1303 1507  
... ... @@ -1322,14 +1526,16 @@
1322 1526 }
1323 1527  
1324 1528 n = 0;
  1529 + mutex_lock(&rio_mport_list_lock);
1325 1530 list_for_each_entry(port, &rio_mports, node) {
1326   - if (port->host_deviceid < 0) {
  1531 + if (port->host_deviceid < 0 && port->nscan) {
1327 1532 work[n].mport = port;
1328 1533 INIT_WORK(&work[n].work, disc_work_handler);
1329 1534 queue_work(rio_wq, &work[n].work);
1330 1535 n++;
1331 1536 }
1332 1537 }
  1538 + mutex_unlock(&rio_mport_list_lock);
1333 1539  
1334 1540 flush_workqueue(rio_wq);
1335 1541 pr_debug("RIO: destroy discovery workqueue\n");
... ... @@ -1342,8 +1548,6 @@
1342 1548 return 0;
1343 1549 }
1344 1550  
1345   -device_initcall_sync(rio_init_mports);
1346   -
1347 1551 static int hdids[RIO_MAX_MPORTS + 1];
1348 1552  
1349 1553 static int rio_get_hdid(int index)
1350 1554  
... ... @@ -1371,7 +1575,10 @@
1371 1575  
1372 1576 port->id = next_portid++;
1373 1577 port->host_deviceid = rio_get_hdid(port->id);
  1578 + port->nscan = NULL;
  1579 + mutex_lock(&rio_mport_list_lock);
1374 1580 list_add_tail(&port->node, &rio_mports);
  1581 + mutex_unlock(&rio_mport_list_lock);
1375 1582 return 0;
1376 1583 }
1377 1584  
... ... @@ -1386,4 +1593,5 @@
1386 1593 EXPORT_SYMBOL_GPL(rio_release_inb_mbox);
1387 1594 EXPORT_SYMBOL_GPL(rio_request_outb_mbox);
1388 1595 EXPORT_SYMBOL_GPL(rio_release_outb_mbox);
  1596 +EXPORT_SYMBOL_GPL(rio_init_mports);
drivers/rapidio/rio.h
... ... @@ -15,6 +15,7 @@
15 15 #include <linux/rio.h>
16 16  
17 17 #define RIO_MAX_CHK_RETRY 3
  18 +#define RIO_MPORT_ANY (-1)
18 19  
19 20 /* Functions internal to the RIO core code */
20 21  
... ... @@ -27,8 +28,6 @@
27 28 extern int rio_mport_chk_dev_access(struct rio_mport *mport, u16 destid,
28 29 u8 hopcount);
29 30 extern int rio_create_sysfs_dev_files(struct rio_dev *rdev);
30   -extern int rio_enum_mport(struct rio_mport *mport);
31   -extern int rio_disc_mport(struct rio_mport *mport);
32 31 extern int rio_std_route_add_entry(struct rio_mport *mport, u16 destid,
33 32 u8 hopcount, u16 table, u16 route_destid,
34 33 u8 route_port);
35 34  
... ... @@ -39,10 +38,16 @@
39 38 u8 hopcount, u16 table);
40 39 extern int rio_set_port_lockout(struct rio_dev *rdev, u32 pnum, int lock);
41 40 extern struct rio_dev *rio_get_comptag(u32 comp_tag, struct rio_dev *from);
  41 +extern int rio_add_device(struct rio_dev *rdev);
  42 +extern void rio_switch_init(struct rio_dev *rdev, int do_enum);
  43 +extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
  44 + u8 hopcount, u8 port_num);
  45 +extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
  46 +extern int rio_unregister_scan(int mport_id);
  47 +extern void rio_attach_device(struct rio_dev *rdev);
42 48  
43 49 /* Structures internal to the RIO core code */
44 50 extern struct device_attribute rio_dev_attrs[];
45   -extern spinlock_t rio_global_list_lock;
46 51  
47 52 extern struct rio_switch_ops __start_rio_switch_ops[];
48 53 extern struct rio_switch_ops __end_rio_switch_ops[];
... ... @@ -83,7 +83,6 @@
83 83  
84 84 extern struct bus_type rio_bus_type;
85 85 extern struct device rio_bus;
86   -extern struct list_head rio_devices; /* list of all devices */
87 86  
88 87 struct rio_mport;
89 88 struct rio_dev;
... ... @@ -237,6 +236,7 @@
237 236 * @name: Port name string
238 237 * @priv: Master port private data
239 238 * @dma: DMA device associated with mport
  239 + * @nscan: RapidIO network enumeration/discovery operations
240 240 */
241 241 struct rio_mport {
242 242 struct list_head dbells; /* list of doorbell events */
... ... @@ -262,6 +262,7 @@
262 262 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
263 263 struct dma_device dma;
264 264 #endif
  265 + struct rio_scan *nscan;
265 266 };
266 267  
267 268 struct rio_id_table {
... ... @@ -459,6 +460,16 @@
459 460 return container_of(ddev, struct rio_mport, dma);
460 461 }
461 462 #endif /* CONFIG_RAPIDIO_DMA_ENGINE */
  463 +
  464 +/**
  465 + * struct rio_scan - RIO enumeration and discovery operations
  466 + * @enumerate: Callback to perform RapidIO fabric enumeration.
  467 + * @discover: Callback to perform RapidIO fabric discovery.
  468 + */
  469 +struct rio_scan {
  470 + int (*enumerate)(struct rio_mport *mport);
  471 + int (*discover)(struct rio_mport *mport);
  472 +};
462 473  
463 474 /* Architecture and hardware-specific functions */
464 475 extern int rio_register_mport(struct rio_mport *);
include/linux/rio_drv.h
... ... @@ -433,6 +433,7 @@
433 433 extern struct rio_dev *rio_get_device(u16 vid, u16 did, struct rio_dev *from);
434 434 extern struct rio_dev *rio_get_asm(u16 vid, u16 did, u16 asm_vid, u16 asm_did,
435 435 struct rio_dev *from);
  436 +extern int rio_init_mports(void);
436 437  
437 438 #endif /* LINUX_RIO_DRV_H */