aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2013-05-24 18:55:06 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-24 19:22:50 -0400
commitbc8fcfea18249640f2728c46d70999dcb7e4dc49 (patch)
tree7d24b4132c4dd821c998649f21344bec6f4a3453
parenta11650e11093ed57dca78bf16e7836517c599098 (diff)
rapidio: add enumeration/discovery start from user space
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 <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>
-rw-r--r--drivers/rapidio/rio-driver.c1
-rw-r--r--drivers/rapidio/rio-scan.c24
-rw-r--r--drivers/rapidio/rio-sysfs.c45
-rw-r--r--drivers/rapidio/rio.c28
-rw-r--r--drivers/rapidio/rio.h2
-rw-r--r--include/linux/rio.h9
6 files changed, 102 insertions, 7 deletions
diff --git a/drivers/rapidio/rio-driver.c b/drivers/rapidio/rio-driver.c
index 55850bb21480..a0c875563d76 100644
--- a/drivers/rapidio/rio-driver.c
+++ b/drivers/rapidio/rio-driver.c
@@ -207,6 +207,7 @@ struct bus_type rio_bus_type = {
207 .name = "rapidio", 207 .name = "rapidio",
208 .match = rio_match_bus, 208 .match = rio_match_bus,
209 .dev_attrs = rio_dev_attrs, 209 .dev_attrs = rio_dev_attrs,
210 .bus_attrs = rio_bus_attrs,
210 .probe = rio_device_probe, 211 .probe = rio_device_probe,
211 .remove = rio_device_remove, 212 .remove = rio_device_remove,
212}; 213};
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 7bdc67419cc3..4c15dbf81087 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -1134,19 +1134,30 @@ static void rio_pw_enable(struct rio_mport *port, int enable)
1134/** 1134/**
1135 * rio_enum_mport- Start enumeration through a master port 1135 * rio_enum_mport- Start enumeration through a master port
1136 * @mport: Master port to send transactions 1136 * @mport: Master port to send transactions
1137 * @flags: Enumeration control flags
1137 * 1138 *
1138 * Starts the enumeration process. If somebody has enumerated our 1139 * Starts the enumeration process. If somebody has enumerated our
1139 * master port device, then give up. If not and we have an active 1140 * master port device, then give up. If not and we have an active
1140 * link, then start recursive peer enumeration. Returns %0 if 1141 * link, then start recursive peer enumeration. Returns %0 if
1141 * enumeration succeeds or %-EBUSY if enumeration fails. 1142 * enumeration succeeds or %-EBUSY if enumeration fails.
1142 */ 1143 */
1143int rio_enum_mport(struct rio_mport *mport) 1144int rio_enum_mport(struct rio_mport *mport, u32 flags)
1144{ 1145{
1145 struct rio_net *net = NULL; 1146 struct rio_net *net = NULL;
1146 int rc = 0; 1147 int rc = 0;
1147 1148
1148 printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id, 1149 printk(KERN_INFO "RIO: enumerate master port %d, %s\n", mport->id,
1149 mport->name); 1150 mport->name);
1151
1152 /*
1153 * To avoid multiple start requests (repeat enumeration is not supported
1154 * by this method) check if enumeration/discovery was performed for this
1155 * mport: if mport was added into the list of mports for a net exit
1156 * with error.
1157 */
1158 if (mport->nnode.next || mport->nnode.prev)
1159 return -EBUSY;
1160
1150 /* If somebody else enumerated our master port device, bail. */ 1161 /* If somebody else enumerated our master port device, bail. */
1151 if (rio_enum_host(mport) < 0) { 1162 if (rio_enum_host(mport) < 0) {
1152 printk(KERN_INFO 1163 printk(KERN_INFO
@@ -1236,14 +1247,16 @@ static void rio_build_route_tables(struct rio_net *net)
1236/** 1247/**
1237 * rio_disc_mport- Start discovery through a master port 1248 * rio_disc_mport- Start discovery through a master port
1238 * @mport: Master port to send transactions 1249 * @mport: Master port to send transactions
1250 * @flags: discovery control flags
1239 * 1251 *
1240 * Starts the discovery process. If we have an active link, 1252 * Starts the discovery process. If we have an active link,
1241 * then wait for the signal that enumeration is complete. 1253 * then wait for the signal that enumeration is complete (if wait
1254 * is allowed).
1242 * When enumeration completion is signaled, start recursive 1255 * When enumeration completion is signaled, start recursive
1243 * peer discovery. Returns %0 if discovery succeeds or %-EBUSY 1256 * peer discovery. Returns %0 if discovery succeeds or %-EBUSY
1244 * on failure. 1257 * on failure.
1245 */ 1258 */
1246int rio_disc_mport(struct rio_mport *mport) 1259int rio_disc_mport(struct rio_mport *mport, u32 flags)
1247{ 1260{
1248 struct rio_net *net = NULL; 1261 struct rio_net *net = NULL;
1249 unsigned long to_end; 1262 unsigned long to_end;
@@ -1253,6 +1266,11 @@ int rio_disc_mport(struct rio_mport *mport)
1253 1266
1254 /* If master port has an active link, allocate net and discover peers */ 1267 /* If master port has an active link, allocate net and discover peers */
1255 if (rio_mport_is_active(mport)) { 1268 if (rio_mport_is_active(mport)) {
1269 if (rio_enum_complete(mport))
1270 goto enum_done;
1271 else if (flags & RIO_SCAN_ENUM_NO_WAIT)
1272 return -EAGAIN;
1273
1256 pr_debug("RIO: wait for enumeration to complete...\n"); 1274 pr_debug("RIO: wait for enumeration to complete...\n");
1257 1275
1258 to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ; 1276 to_end = jiffies + CONFIG_RAPIDIO_DISC_TIMEOUT * HZ;
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 4dbe360989be..66d4acd5e18f 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -285,3 +285,48 @@ void rio_remove_sysfs_dev_files(struct rio_dev *rdev)
285 rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE); 285 rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
286 } 286 }
287} 287}
288
289static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
290 size_t count)
291{
292 long val;
293 struct rio_mport *port = NULL;
294 int rc;
295
296 if (kstrtol(buf, 0, &val) < 0)
297 return -EINVAL;
298
299 if (val == RIO_MPORT_ANY) {
300 rc = rio_init_mports();
301 goto exit;
302 }
303
304 if (val < 0 || val >= RIO_MAX_MPORTS)
305 return -EINVAL;
306
307 port = rio_find_mport((int)val);
308
309 if (!port) {
310 pr_debug("RIO: %s: mport_%d not available\n",
311 __func__, (int)val);
312 return -EINVAL;
313 }
314
315 if (!port->nscan)
316 return -EINVAL;
317
318 if (port->host_deviceid >= 0)
319 rc = port->nscan->enumerate(port, 0);
320 else
321 rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT);
322exit:
323 if (!rc)
324 rc = count;
325
326 return rc;
327}
328
329struct bus_attribute rio_bus_attrs[] = {
330 __ATTR(scan, (S_IWUSR|S_IWGRP), NULL, bus_scan_store),
331 __ATTR_NULL
332};
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index 6e75dda34799..cb1c08996fbb 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -1383,6 +1383,30 @@ EXPORT_SYMBOL_GPL(rio_dma_prep_slave_sg);
1383#endif /* CONFIG_RAPIDIO_DMA_ENGINE */ 1383#endif /* CONFIG_RAPIDIO_DMA_ENGINE */
1384 1384
1385/** 1385/**
1386 * rio_find_mport - find RIO mport by its ID
1387 * @mport_id: number (ID) of mport device
1388 *
1389 * Given a RIO mport number, the desired mport is located
1390 * in the global list of mports. If the mport is found, a pointer to its
1391 * data structure is returned. If no mport is found, %NULL is returned.
1392 */
1393struct rio_mport *rio_find_mport(int mport_id)
1394{
1395 struct rio_mport *port;
1396
1397 mutex_lock(&rio_mport_list_lock);
1398 list_for_each_entry(port, &rio_mports, node) {
1399 if (port->id == mport_id)
1400 goto found;
1401 }
1402 port = NULL;
1403found:
1404 mutex_unlock(&rio_mport_list_lock);
1405
1406 return port;
1407}
1408
1409/**
1386 * rio_register_scan - enumeration/discovery method registration interface 1410 * rio_register_scan - enumeration/discovery method registration interface
1387 * @mport_id: mport device ID for which fabric scan routine has to be set 1411 * @mport_id: mport device ID for which fabric scan routine has to be set
1388 * (RIO_MPORT_ANY = set for all available mports) 1412 * (RIO_MPORT_ANY = set for all available mports)
@@ -1475,7 +1499,7 @@ static void disc_work_handler(struct work_struct *_work)
1475 work = container_of(_work, struct rio_disc_work, work); 1499 work = container_of(_work, struct rio_disc_work, work);
1476 pr_debug("RIO: discovery work for mport %d %s\n", 1500 pr_debug("RIO: discovery work for mport %d %s\n",
1477 work->mport->id, work->mport->name); 1501 work->mport->id, work->mport->name);
1478 work->mport->nscan->discover(work->mport); 1502 work->mport->nscan->discover(work->mport, 0);
1479} 1503}
1480 1504
1481int rio_init_mports(void) 1505int rio_init_mports(void)
@@ -1495,7 +1519,7 @@ int rio_init_mports(void)
1495 list_for_each_entry(port, &rio_mports, node) { 1519 list_for_each_entry(port, &rio_mports, node) {
1496 if (port->host_deviceid >= 0) { 1520 if (port->host_deviceid >= 0) {
1497 if (port->nscan) 1521 if (port->nscan)
1498 port->nscan->enumerate(port); 1522 port->nscan->enumerate(port, 0);
1499 } else 1523 } else
1500 n++; 1524 n++;
1501 } 1525 }
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index 0afdf482517e..c14f864dea5c 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -45,9 +45,11 @@ extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
45extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops); 45extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
46extern int rio_unregister_scan(int mport_id); 46extern int rio_unregister_scan(int mport_id);
47extern void rio_attach_device(struct rio_dev *rdev); 47extern void rio_attach_device(struct rio_dev *rdev);
48extern struct rio_mport *rio_find_mport(int mport_id);
48 49
49/* Structures internal to the RIO core code */ 50/* Structures internal to the RIO core code */
50extern struct device_attribute rio_dev_attrs[]; 51extern struct device_attribute rio_dev_attrs[];
52extern struct bus_attribute rio_bus_attrs[];
51 53
52extern struct rio_switch_ops __start_rio_switch_ops[]; 54extern struct rio_switch_ops __start_rio_switch_ops[];
53extern struct rio_switch_ops __end_rio_switch_ops[]; 55extern struct rio_switch_ops __end_rio_switch_ops[];
diff --git a/include/linux/rio.h b/include/linux/rio.h
index cd3796ee7410..18e099342e6f 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -265,6 +265,11 @@ struct rio_mport {
265 struct rio_scan *nscan; 265 struct rio_scan *nscan;
266}; 266};
267 267
268/*
269 * Enumeration/discovery control flags
270 */
271#define RIO_SCAN_ENUM_NO_WAIT 0x00000001 /* Do not wait for enum completed */
272
268struct rio_id_table { 273struct rio_id_table {
269 u16 start; /* logical minimal id */ 274 u16 start; /* logical minimal id */
270 u32 max; /* max number of IDs in table */ 275 u32 max; /* max number of IDs in table */
@@ -467,8 +472,8 @@ static inline struct rio_mport *dma_to_mport(struct dma_device *ddev)
467 * @discover: Callback to perform RapidIO fabric discovery. 472 * @discover: Callback to perform RapidIO fabric discovery.
468 */ 473 */
469struct rio_scan { 474struct rio_scan {
470 int (*enumerate)(struct rio_mport *mport); 475 int (*enumerate)(struct rio_mport *mport, u32 flags);
471 int (*discover)(struct rio_mport *mport); 476 int (*discover)(struct rio_mport *mport, u32 flags);
472}; 477};
473 478
474/* Architecture and hardware-specific functions */ 479/* Architecture and hardware-specific functions */