Skip to content

Commit

Permalink
rapidio: make enumeration/discovery configurable
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alexandre Bounine authored and Linus Torvalds committed May 24, 2013
1 parent 585dc0c commit a11650e
Show file tree
Hide file tree
Showing 8 changed files with 304 additions and 139 deletions.
20 changes: 20 additions & 0 deletions drivers/rapidio/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,24 @@ config RAPIDIO_DEBUG

If you are unsure about this, say N here.

choice
prompt "Enumeration method"
depends on RAPIDIO
default RAPIDIO_ENUM_BASIC
help
There are different enumeration and discovery mechanisms offered
for RapidIO subsystem. You may select single built-in method or
or any number of methods to be built as modules.
Selecting a built-in method disables use of loadable methods.

If unsure, select Basic built-in.

config RAPIDIO_ENUM_BASIC
tristate "Basic"
help
This option includes basic RapidIO fabric enumeration and discovery
mechanism similar to one described in RapidIO specification Annex 1.

endchoice

source "drivers/rapidio/switches/Kconfig"
3 changes: 2 additions & 1 deletion drivers/rapidio/Makefile
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
#
# Makefile for RapidIO interconnect services
#
obj-y += rio.o rio-access.o rio-driver.o rio-scan.o rio-sysfs.o
obj-y += rio.o rio-access.o rio-driver.o rio-sysfs.o
obj-$(CONFIG_RAPIDIO_ENUM_BASIC) += rio-scan.o

obj-$(CONFIG_RAPIDIO) += switches/
obj-$(CONFIG_RAPIDIO) += devices/
Expand Down
7 changes: 7 additions & 0 deletions drivers/rapidio/rio-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,13 @@ void rio_unregister_driver(struct rio_driver *rdrv)
driver_unregister(&rdrv->driver);
}

void rio_attach_device(struct rio_dev *rdev)
{
rdev->dev.bus = &rio_bus_type;
rdev->dev.parent = &rio_bus;
}
EXPORT_SYMBOL_GPL(rio_attach_device);

/**
* rio_match_bus - Tell if a RIO device structure has a matching RIO driver device id structure
* @dev: the standard device structure to match against
Expand Down
166 changes: 39 additions & 127 deletions drivers/rapidio/rio-scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,8 @@

#include "rio.h"

LIST_HEAD(rio_devices);

static void rio_init_em(struct rio_dev *rdev);

DEFINE_SPINLOCK(rio_global_list_lock);

static int next_destid = 0;
static int next_comptag = 1;

Expand Down Expand Up @@ -326,127 +322,6 @@ static int rio_is_switch(struct rio_dev *rdev)
return 0;
}

/**
* rio_switch_init - Sets switch operations for a particular vendor switch
* @rdev: RIO device
* @do_enum: Enumeration/Discovery mode flag
*
* Searches the RIO switch ops table for known switch types. If the vid
* and did match a switch table entry, then call switch initialization
* routine to setup switch-specific routines.
*/
static void rio_switch_init(struct rio_dev *rdev, int do_enum)
{
struct rio_switch_ops *cur = __start_rio_switch_ops;
struct rio_switch_ops *end = __end_rio_switch_ops;

while (cur < end) {
if ((cur->vid == rdev->vid) && (cur->did == rdev->did)) {
pr_debug("RIO: calling init routine for %s\n",
rio_name(rdev));
cur->init_hook(rdev, do_enum);
break;
}
cur++;
}

if ((cur >= end) && (rdev->pef & RIO_PEF_STD_RT)) {
pr_debug("RIO: adding STD routing ops for %s\n",
rio_name(rdev));
rdev->rswitch->add_entry = rio_std_route_add_entry;
rdev->rswitch->get_entry = rio_std_route_get_entry;
rdev->rswitch->clr_table = rio_std_route_clr_table;
}

if (!rdev->rswitch->add_entry || !rdev->rswitch->get_entry)
printk(KERN_ERR "RIO: missing routing ops for %s\n",
rio_name(rdev));
}

/**
* rio_add_device- Adds a RIO device to the device model
* @rdev: RIO device
*
* Adds the RIO device to the global device list and adds the RIO
* device to the RIO device list. Creates the generic sysfs nodes
* for an RIO device.
*/
static int rio_add_device(struct rio_dev *rdev)
{
int err;

err = device_add(&rdev->dev);
if (err)
return err;

spin_lock(&rio_global_list_lock);
list_add_tail(&rdev->global_list, &rio_devices);
spin_unlock(&rio_global_list_lock);

rio_create_sysfs_dev_files(rdev);

return 0;
}

/**
* rio_enable_rx_tx_port - enable input receiver and output transmitter of
* given port
* @port: Master port associated with the RIO network
* @local: local=1 select local port otherwise a far device is reached
* @destid: Destination ID of the device to check host bit
* @hopcount: Number of hops to reach the target
* @port_num: Port (-number on switch) to enable on a far end device
*
* Returns 0 or 1 from on General Control Command and Status Register
* (EXT_PTR+0x3C)
*/
inline int rio_enable_rx_tx_port(struct rio_mport *port,
int local, u16 destid,
u8 hopcount, u8 port_num) {
#ifdef CONFIG_RAPIDIO_ENABLE_RX_TX_PORTS
u32 regval;
u32 ext_ftr_ptr;

/*
* enable rx input tx output port
*/
pr_debug("rio_enable_rx_tx_port(local = %d, destid = %d, hopcount = "
"%d, port_num = %d)\n", local, destid, hopcount, port_num);

ext_ftr_ptr = rio_mport_get_physefb(port, local, destid, hopcount);

if (local) {
rio_local_read_config_32(port, ext_ftr_ptr +
RIO_PORT_N_CTL_CSR(0),
&regval);
} else {
if (rio_mport_read_config_32(port, destid, hopcount,
ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), &regval) < 0)
return -EIO;
}

if (regval & RIO_PORT_N_CTL_P_TYP_SER) {
/* serial */
regval = regval | RIO_PORT_N_CTL_EN_RX_SER
| RIO_PORT_N_CTL_EN_TX_SER;
} else {
/* parallel */
regval = regval | RIO_PORT_N_CTL_EN_RX_PAR
| RIO_PORT_N_CTL_EN_TX_PAR;
}

if (local) {
rio_local_write_config_32(port, ext_ftr_ptr +
RIO_PORT_N_CTL_CSR(0), regval);
} else {
if (rio_mport_write_config_32(port, destid, hopcount,
ext_ftr_ptr + RIO_PORT_N_CTL_CSR(port_num), regval) < 0)
return -EIO;
}
#endif
return 0;
}

/**
* rio_setup_device- Allocates and sets up a RIO device
* @net: RIO network
Expand Down Expand Up @@ -587,8 +462,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
rdev->destid);
}

rdev->dev.bus = &rio_bus_type;
rdev->dev.parent = &rio_bus;
rio_attach_device(rdev);

device_initialize(&rdev->dev);
rdev->dev.release = rio_release_dev;
Expand Down Expand Up @@ -1421,3 +1295,41 @@ int rio_disc_mport(struct rio_mport *mport)
bail:
return -EBUSY;
}

static struct rio_scan rio_scan_ops = {
.enumerate = rio_enum_mport,
.discover = rio_disc_mport,
};

static bool scan;
module_param(scan, bool, 0);
MODULE_PARM_DESC(scan, "Start RapidIO network enumeration/discovery "
"(default = 0)");

/**
* rio_basic_attach:
*
* When this enumeration/discovery method is loaded as a module this function
* registers its specific enumeration and discover routines for all available
* RapidIO mport devices. The "scan" command line parameter controls ability of
* the module to start RapidIO enumeration/discovery automatically.
*
* Returns 0 for success or -EIO if unable to register itself.
*
* This enumeration/discovery method cannot be unloaded and therefore does not
* provide a matching cleanup_module routine.
*/

static int __init rio_basic_attach(void)
{
if (rio_register_scan(RIO_MPORT_ANY, &rio_scan_ops))
return -EIO;
if (scan)
rio_init_mports();
return 0;
}

late_initcall(rio_basic_attach);

MODULE_DESCRIPTION("Basic RapidIO enumeration/discovery");
MODULE_LICENSE("GPL");
Loading

0 comments on commit a11650e

Please sign in to comment.