Skip to content

Commit

Permalink
rapidio: add enumeration/discovery start from user space
Browse files Browse the repository at this point in the history
Add RapidIO enumeration/discovery start from user space.  User space
start allows to defer RapidIO fabric scan until the moment when all
participating endpoints are initialized avoiding mandatory synchronized
start of all endpoints (which may be challenging in systems with large
number of RapidIO endpoints).

Signed-off-by: Alexandre Bounine <[email protected]>
Cc: Matt Porter <[email protected]>
Cc: Li Yang <[email protected]>
Cc: Kumar Gala <[email protected]>
Cc: Andre van Herk <[email protected]>
Cc: Micha Nelissen <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
  • Loading branch information
Alexandre Bounine authored and torvalds committed May 24, 2013
1 parent a11650e commit bc8fcfe
Show file tree
Hide file tree
Showing 6 changed files with 102 additions and 7 deletions.
1 change: 1 addition & 0 deletions drivers/rapidio/rio-driver.c
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ struct bus_type rio_bus_type = {
.name = "rapidio",
.match = rio_match_bus,
.dev_attrs = rio_dev_attrs,
.bus_attrs = rio_bus_attrs,
.probe = rio_device_probe,
.remove = rio_device_remove,
};
Expand Down
24 changes: 21 additions & 3 deletions drivers/rapidio/rio-scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -1134,19 +1134,30 @@ static void rio_pw_enable(struct rio_mport *port, int enable)
/**
* rio_enum_mport- Start enumeration through a master port
* @mport: Master port to send transactions
* @flags: Enumeration control flags
*
* Starts the enumeration process. If somebody has enumerated our
* master port device, then give up. If not and we have an active
* link, then start recursive peer enumeration. Returns %0 if
* enumeration succeeds or %-EBUSY if enumeration fails.
*/
int rio_enum_mport(struct rio_mport *mport)
int rio_enum_mport(struct rio_mport *mport, u32 flags)
{
struct rio_net *net = NULL;
int rc = 0;

printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id,
mport->name);

/*
* To avoid multiple start requests (repeat enumeration is not supported
* by this method) check if enumeration/discovery was performed for this
* mport: if mport was added into the list of mports for a net exit
* with error.
*/
if (mport->nnode.next || mport->nnode.prev)
return -EBUSY;

/* If somebody else enumerated our master port device, bail. */
if (rio_enum_host(mport) < 0) {
printk(KERN_INFO
Expand Down Expand Up @@ -1236,14 +1247,16 @@ static void rio_build_route_tables(struct rio_net *net)
/**
* rio_disc_mport- Start discovery through a master port
* @mport: Master port to send transactions
* @flags: discovery control flags
*
* Starts the discovery process. If we have an active link,
* then wait for the signal that enumeration is complete.
* then wait for the signal that enumeration is complete (if wait
* is allowed).
* When enumeration completion is signaled, start recursive
* peer discovery. Returns %0 if discovery succeeds or %-EBUSY
* on failure.
*/
int rio_disc_mport(struct rio_mport *mport)
int rio_disc_mport(struct rio_mport *mport, u32 flags)
{
struct rio_net *net = NULL;
unsigned long to_end;
Expand All @@ -1253,6 +1266,11 @@ int rio_disc_mport(struct rio_mport *mport)

/* If master port has an active link, allocate net and discover peers */
if (rio_mport_is_active(mport)) {
if (rio_enum_complete(mport))
goto enum_done;
else if (flags & RIO_SCAN_ENUM_NO_WAIT)
return -EAGAIN;

pr_debug("RIO: wait for enumeration to complete...\n");

to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
Expand Down
45 changes: 45 additions & 0 deletions drivers/rapidio/rio-sysfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,48 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
}
}

static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
size_t count)
{
long val;
struct rio_mport *port = NULL;
int rc;

if (kstrtol(buf, 0, &val) < 0)
return -EINVAL;

if (val == RIO_MPORT_ANY) {
rc = rio_init_mports();
goto exit;
}

if (val < 0 || val >= RIO_MAX_MPORTS)
return -EINVAL;

port = rio_find_mport((int)val);

if (!port) {
pr_debug("RIO: %s: mport_%d not available\n",
__func__, (int)val);
return -EINVAL;
}

if (!port->nscan)
return -EINVAL;

if (port->host_deviceid >= 0)
rc = port->nscan->enumerate(port, 0);
else
rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT);
exit:
if (!rc)
rc = count;

return rc;
}

struct bus_attribute rio_bus_attrs[] = {
__ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store),
__ATTR_NULL
};
28 changes: 26 additions & 2 deletions drivers/rapidio/rio.c
Original file line number Diff line number Diff line change
Expand Up @@ -1382,6 +1382,30 @@ EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg);

#endif /* CONFIG_RAPIDIO_DMA_ENGINE */

/**
* rio_find_mport - find RIO mport by its ID
* @mport_id: number (ID) of mport device
*
* Given a RIO mport number, the desired mport is located
* in the global list of mports. If the mport is found, a pointer to its
* data structure is returned. If no mport is found, %NULL is returned.
*/
struct rio_mport *rio_find_mport(int mport_id)
{
struct rio_mport *port;

mutex_lock(&rio_mport_list_lock);
list_for_each_entry(port, &rio_mports, node) {
if (port->id == mport_id)
goto found;
}
port = NULL;
found:
mutex_unlock(&rio_mport_list_lock);

return port;
}

/**
* rio_register_scan - enumeration/discovery method registration interface
* @mport_id: mport device ID for which fabric scan routine has to be set
Expand Down Expand Up @@ -1475,7 +1499,7 @@ static void disc_work_handler(struct work_struct *_work)
work = container_of(_work, struct rio_disc_work, work);
pr_debug("RIO: discovery work for mport %d %s\n",
work->mport->id, work->mport->name);
work->mport->nscan->discover(work->mport);
work->mport->nscan->discover(work->mport, 0);
}

int rio_init_mports(void)
Expand All @@ -1495,7 +1519,7 @@ int rio_init_mports(void)
list_for_each_entry(port, &rio_mports, node) {
if (port->host_deviceid >= 0) {
if (port->nscan)
port->nscan->enumerate(port);
port->nscan->enumerate(port, 0);
} else
n++;
}
Expand Down
2 changes: 2 additions & 0 deletions drivers/rapidio/rio.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@ extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
extern int rio_unregister_scan(int mport_id);
extern void rio_attach_device(struct rio_dev *rdev);
extern struct rio_mport *rio_find_mport(int mport_id);

/* Structures internal to the RIO core code */
extern struct device_attribute rio_dev_attrs[];
extern struct bus_attribute rio_bus_attrs[];

extern struct rio_switch_ops __start_rio_switch_ops[];
extern struct rio_switch_ops __end_rio_switch_ops[];
Expand Down
9 changes: 7 additions & 2 deletions include/linux/rio.h
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,11 @@ struct rio_mport {
struct rio_scan *nscan;
};

/*
* Enumeration/discovery control flags
*/
#define RIO_SCAN_ENUM_NO_WAIT 0x00000001 /* Do not wait for enum completed */

struct rio_id_table {
u16 start; /* logical minimal id */
u32 max; /* max number of IDs in table */
Expand Down Expand Up @@ -467,8 +472,8 @@ static inline struct rio_mport *dma_to_mport(struct dma_device *ddev)
* @discover: Callback to perform RapidIO fabric discovery.
*/
struct rio_scan {
int (*enumerate)(struct rio_mport *mport);
int (*discover)(struct rio_mport *mport);
int (*enumerate)(struct rio_mport *mport, u32 flags);
int (*discover)(struct rio_mport *mport, u32 flags);
};

/* Architecture and hardware-specific functions */
Expand Down

0 comments on commit bc8fcfe

Please sign in to comment.