aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/rapidio
diff options
context:
space:
mode:
authorAlexandre Bounine <alexandre.bounine@idt.com>2013-07-03 18:08:53 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 19:08:04 -0400
commit9edbc30b434f56258d03faac5daf37a555384db3 (patch)
treed6454e8d28a6177d31f91bf081bb0602b8c73056 /drivers/rapidio
parente6161d64263ee7a903acdde1a8ab7d4221d5512f (diff)
rapidio: update enumerator registration mechanism
Update enumeration/discovery method registration mechanism to allow loading enumeration/discovery methods before all mports are registered. Existing statically linked RapidIO subsystem expects that all available RapidIO mport devices are initialized and registered before the enumeration/discovery method is registered. Switching to loadable mport device drivers creates situation when mport device driver can be loaded after enumeration/discovery method is attached (e.g., loadable mport driver in a system with statically linked RapidIO core and enumerator). This also will happen in a system with hot-pluggable RapidIO controllers. To remove the dependency on the initialization/registration order this patch introduces enumeration/discovery registration mechanism that supports arbitrary registration order of mports and enumerator/discovery methods. The following registration rules are implemented: - only one enumeration/discovery method can be registered for given mport ID (including RIO_MPORT_ANY); - when new enumeration/discovery methods tries to attach to the registered mport device, method with matching mport ID will replace a default method previously registered for given mport (if any); - enumeration/discovery method with target ID=RIO_MPORT_ANY will be attached only to mports that do not have another enumerator attached to them; - when new mport device is registered with RapidIO subsystem, registration routine searches for the enumeration/discovery method with the best matching mport ID; 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> Cc: Stef van Os <stef.van.os@Prodrive.nl> Cc: Jean Delvare <jdelvare@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/rapidio')
-rw-r--r--drivers/rapidio/rio-scan.c1
-rw-r--r--drivers/rapidio/rio-sysfs.c17
-rw-r--r--drivers/rapidio/rio.c176
-rw-r--r--drivers/rapidio/rio.h3
4 files changed, 149 insertions, 48 deletions
diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 913950212605..ab837fdb2383 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -1162,6 +1162,7 @@ bail:
1162} 1162}
1163 1163
1164static struct rio_scan rio_scan_ops = { 1164static struct rio_scan rio_scan_ops = {
1165 .owner = THIS_MODULE,
1165 .enumerate = rio_enum_mport, 1166 .enumerate = rio_enum_mport,
1166 .discover = rio_disc_mport, 1167 .discover = rio_disc_mport,
1167}; 1168};
diff --git a/drivers/rapidio/rio-sysfs.c b/drivers/rapidio/rio-sysfs.c
index 864e52f193e1..0c4473e54f86 100644
--- a/drivers/rapidio/rio-sysfs.c
+++ b/drivers/rapidio/rio-sysfs.c
@@ -286,7 +286,6 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
286 size_t count) 286 size_t count)
287{ 287{
288 long val; 288 long val;
289 struct rio_mport *port = NULL;
290 int rc; 289 int rc;
291 290
292 if (kstrtol(buf, 0, &val) < 0) 291 if (kstrtol(buf, 0, &val) < 0)
@@ -300,21 +299,7 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
300 if (val < 0 || val >= RIO_MAX_MPORTS) 299 if (val < 0 || val >= RIO_MAX_MPORTS)
301 return -EINVAL; 300 return -EINVAL;
302 301
303 port = rio_find_mport((int)val); 302 rc = rio_mport_scan((int)val);
304
305 if (!port) {
306 pr_debug("RIO: %s: mport_%d not available\n",
307 __func__, (int)val);
308 return -EINVAL;
309 }
310
311 if (!port->nscan)
312 return -EINVAL;
313
314 if (port->host_deviceid >= 0)
315 rc = port->nscan->enumerate(port, 0);
316 else
317 rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT);
318exit: 303exit:
319 if (!rc) 304 if (!rc)
320 rc = count; 305 rc = count;
diff --git a/drivers/rapidio/rio.c b/drivers/rapidio/rio.c
index b17d5218005e..5eb727cd0652 100644
--- a/drivers/rapidio/rio.c
+++ b/drivers/rapidio/rio.c
@@ -34,6 +34,7 @@ static LIST_HEAD(rio_devices);
34static DEFINE_SPINLOCK(rio_global_list_lock); 34static DEFINE_SPINLOCK(rio_global_list_lock);
35 35
36static LIST_HEAD(rio_mports); 36static LIST_HEAD(rio_mports);
37static LIST_HEAD(rio_scans);
37static DEFINE_MUTEX(rio_mport_list_lock); 38static DEFINE_MUTEX(rio_mport_list_lock);
38static unsigned char next_portid; 39static unsigned char next_portid;
39static DEFINE_SPINLOCK(rio_mmap_lock); 40static DEFINE_SPINLOCK(rio_mmap_lock);
@@ -1602,34 +1603,73 @@ found:
1602 * rio_register_scan - enumeration/discovery method registration interface 1603 * rio_register_scan - enumeration/discovery method registration interface
1603 * @mport_id: mport device ID for which fabric scan routine has to be set 1604 * @mport_id: mport device ID for which fabric scan routine has to be set
1604 * (RIO_MPORT_ANY = set for all available mports) 1605 * (RIO_MPORT_ANY = set for all available mports)
1605 * @scan_ops: enumeration/discovery control structure 1606 * @scan_ops: enumeration/discovery operations structure
1607 *
1608 * Registers enumeration/discovery operations with RapidIO subsystem and
1609 * attaches it to the specified mport device (or all available mports
1610 * if RIO_MPORT_ANY is specified).
1606 * 1611 *
1607 * Assigns enumeration or discovery method to the specified mport device (or all
1608 * available mports if RIO_MPORT_ANY is specified).
1609 * Returns error if the mport already has an enumerator attached to it. 1612 * Returns error if the mport already has an enumerator attached to it.
1610 * In case of RIO_MPORT_ANY ignores ports with valid scan routines and returns 1613 * In case of RIO_MPORT_ANY skips mports with valid scan routines (no error).
1611 * an error if was unable to find at least one available mport.
1612 */ 1614 */
1613int rio_register_scan(int mport_id, struct rio_scan *scan_ops) 1615int rio_register_scan(int mport_id, struct rio_scan *scan_ops)
1614{ 1616{
1615 struct rio_mport *port; 1617 struct rio_mport *port;
1616 int rc = -EBUSY; 1618 struct rio_scan_node *scan;
1619 int rc = 0;
1617 1620
1618 mutex_lock(&rio_mport_list_lock); 1621 pr_debug("RIO: %s for mport_id=%d\n", __func__, mport_id);
1619 list_for_each_entry(port, &rio_mports, node) {
1620 if (port->id == mport_id || mport_id == RIO_MPORT_ANY) {
1621 if (port->nscan && mport_id == RIO_MPORT_ANY)
1622 continue;
1623 else if (port->nscan)
1624 break;
1625 1622
1626 port->nscan = scan_ops; 1623 if ((mport_id != RIO_MPORT_ANY && mport_id >= RIO_MAX_MPORTS) ||
1627 rc = 0; 1624 !scan_ops)
1625 return -EINVAL;
1628 1626
1629 if (mport_id != RIO_MPORT_ANY) 1627 mutex_lock(&rio_mport_list_lock);
1630 break; 1628
1629 /*
1630 * Check if there is another enumerator already registered for
1631 * the same mport ID (including RIO_MPORT_ANY). Multiple enumerators
1632 * for the same mport ID are not supported.
1633 */
1634 list_for_each_entry(scan, &rio_scans, node) {
1635 if (scan->mport_id == mport_id) {
1636 rc = -EBUSY;
1637 goto err_out;
1631 } 1638 }
1632 } 1639 }
1640
1641 /*
1642 * Allocate and initialize new scan registration node.
1643 */
1644 scan = kzalloc(sizeof(*scan), GFP_KERNEL);
1645 if (!scan) {
1646 rc = -ENOMEM;
1647 goto err_out;
1648 }
1649
1650 scan->mport_id = mport_id;
1651 scan->ops = scan_ops;
1652
1653 /*
1654 * Traverse the list of registered mports to attach this new scan.
1655 *
1656 * The new scan with matching mport ID overrides any previously attached
1657 * scan assuming that old scan (if any) is the default one (based on the
1658 * enumerator registration check above).
1659 * If the new scan is the global one, it will be attached only to mports
1660 * that do not have their own individual operations already attached.
1661 */
1662 list_for_each_entry(port, &rio_mports, node) {
1663 if (port->id == mport_id) {
1664 port->nscan = scan_ops;
1665 break;
1666 } else if (mport_id == RIO_MPORT_ANY && !port->nscan)
1667 port->nscan = scan_ops;
1668 }
1669
1670 list_add_tail(&scan->node, &rio_scans);
1671
1672err_out:
1633 mutex_unlock(&rio_mport_list_lock); 1673 mutex_unlock(&rio_mport_list_lock);
1634 1674
1635 return rc; 1675 return rc;
@@ -1639,30 +1679,81 @@ EXPORT_SYMBOL_GPL(rio_register_scan);
1639/** 1679/**
1640 * rio_unregister_scan - removes enumeration/discovery method from mport 1680 * rio_unregister_scan - removes enumeration/discovery method from mport
1641 * @mport_id: mport device ID for which fabric scan routine has to be 1681 * @mport_id: mport device ID for which fabric scan routine has to be
1642 * unregistered (RIO_MPORT_ANY = set for all available mports) 1682 * unregistered (RIO_MPORT_ANY = apply to all mports that use
1683 * the specified scan_ops)
1684 * @scan_ops: enumeration/discovery operations structure
1643 * 1685 *
1644 * Removes enumeration or discovery method assigned to the specified mport 1686 * Removes enumeration or discovery method assigned to the specified mport
1645 * device (or all available mports if RIO_MPORT_ANY is specified). 1687 * device. If RIO_MPORT_ANY is specified, removes the specified operations from
1688 * all mports that have them attached.
1646 */ 1689 */
1647int rio_unregister_scan(int mport_id) 1690int rio_unregister_scan(int mport_id, struct rio_scan *scan_ops)
1648{ 1691{
1649 struct rio_mport *port; 1692 struct rio_mport *port;
1693 struct rio_scan_node *scan;
1694
1695 pr_debug("RIO: %s for mport_id=%d\n", __func__, mport_id);
1696
1697 if (mport_id != RIO_MPORT_ANY && mport_id >= RIO_MAX_MPORTS)
1698 return -EINVAL;
1650 1699
1651 mutex_lock(&rio_mport_list_lock); 1700 mutex_lock(&rio_mport_list_lock);
1652 list_for_each_entry(port, &rio_mports, node) { 1701
1653 if (port->id == mport_id || mport_id == RIO_MPORT_ANY) { 1702 list_for_each_entry(port, &rio_mports, node)
1654 if (port->nscan) 1703 if (port->id == mport_id ||
1655 port->nscan = NULL; 1704 (mport_id == RIO_MPORT_ANY && port->nscan == scan_ops))
1656 if (mport_id != RIO_MPORT_ANY) 1705 port->nscan = NULL;
1657 break; 1706
1707 list_for_each_entry(scan, &rio_scans, node)
1708 if (scan->mport_id == mport_id) {
1709 list_del(&scan->node);
1710 kfree(scan);
1658 } 1711 }
1659 } 1712
1660 mutex_unlock(&rio_mport_list_lock); 1713 mutex_unlock(&rio_mport_list_lock);
1661 1714
1662 return 0; 1715 return 0;
1663} 1716}
1664EXPORT_SYMBOL_GPL(rio_unregister_scan); 1717EXPORT_SYMBOL_GPL(rio_unregister_scan);
1665 1718
1719/**
1720 * rio_mport_scan - execute enumeration/discovery on the specified mport
1721 * @mport_id: number (ID) of mport device
1722 */
1723int rio_mport_scan(int mport_id)
1724{
1725 struct rio_mport *port = NULL;
1726 int rc;
1727
1728 mutex_lock(&rio_mport_list_lock);
1729 list_for_each_entry(port, &rio_mports, node) {
1730 if (port->id == mport_id)
1731 goto found;
1732 }
1733 mutex_unlock(&rio_mport_list_lock);
1734 return -ENODEV;
1735found:
1736 if (!port->nscan) {
1737 mutex_unlock(&rio_mport_list_lock);
1738 return -EINVAL;
1739 }
1740
1741 if (!try_module_get(port->nscan->owner)) {
1742 mutex_unlock(&rio_mport_list_lock);
1743 return -ENODEV;
1744 }
1745
1746 mutex_unlock(&rio_mport_list_lock);
1747
1748 if (port->host_deviceid >= 0)
1749 rc = port->nscan->enumerate(port, 0);
1750 else
1751 rc = port->nscan->discover(port, RIO_SCAN_ENUM_NO_WAIT);
1752
1753 module_put(port->nscan->owner);
1754 return rc;
1755}
1756
1666static void rio_fixup_device(struct rio_dev *dev) 1757static void rio_fixup_device(struct rio_dev *dev)
1667{ 1758{
1668} 1759}
@@ -1691,7 +1782,10 @@ static void disc_work_handler(struct work_struct *_work)
1691 work = container_of(_work, struct rio_disc_work, work); 1782 work = container_of(_work, struct rio_disc_work, work);
1692 pr_debug("RIO: discovery work for mport %d %s\n", 1783 pr_debug("RIO: discovery work for mport %d %s\n",
1693 work->mport->id, work->mport->name); 1784 work->mport->id, work->mport->name);
1694 work->mport->nscan->discover(work->mport, 0); 1785 if (try_module_get(work->mport->nscan->owner)) {
1786 work->mport->nscan->discover(work->mport, 0);
1787 module_put(work->mport->nscan->owner);
1788 }
1695} 1789}
1696 1790
1697int rio_init_mports(void) 1791int rio_init_mports(void)
@@ -1710,8 +1804,10 @@ int rio_init_mports(void)
1710 mutex_lock(&rio_mport_list_lock); 1804 mutex_lock(&rio_mport_list_lock);
1711 list_for_each_entry(port, &rio_mports, node) { 1805 list_for_each_entry(port, &rio_mports, node) {
1712 if (port->host_deviceid >= 0) { 1806 if (port->host_deviceid >= 0) {
1713 if (port->nscan) 1807 if (port->nscan && try_module_get(port->nscan->owner)) {
1714 port->nscan->enumerate(port, 0); 1808 port->nscan->enumerate(port, 0);
1809 module_put(port->nscan->owner);
1810 }
1715 } else 1811 } else
1716 n++; 1812 n++;
1717 } 1813 }
@@ -1725,7 +1821,7 @@ int rio_init_mports(void)
1725 * for each of them. If the code below fails to allocate needed 1821 * for each of them. If the code below fails to allocate needed
1726 * resources, exit without error to keep results of enumeration 1822 * resources, exit without error to keep results of enumeration
1727 * process (if any). 1823 * process (if any).
1728 * TODO: Implement restart of dicovery process for all or 1824 * TODO: Implement restart of discovery process for all or
1729 * individual discovering mports. 1825 * individual discovering mports.
1730 */ 1826 */
1731 rio_wq = alloc_workqueue("riodisc", 0, 0); 1827 rio_wq = alloc_workqueue("riodisc", 0, 0);
@@ -1751,9 +1847,9 @@ int rio_init_mports(void)
1751 n++; 1847 n++;
1752 } 1848 }
1753 } 1849 }
1754 mutex_unlock(&rio_mport_list_lock);
1755 1850
1756 flush_workqueue(rio_wq); 1851 flush_workqueue(rio_wq);
1852 mutex_unlock(&rio_mport_list_lock);
1757 pr_debug("RIO: destroy discovery workqueue\n"); 1853 pr_debug("RIO: destroy discovery workqueue\n");
1758 destroy_workqueue(rio_wq); 1854 destroy_workqueue(rio_wq);
1759 kfree(work); 1855 kfree(work);
@@ -1784,6 +1880,8 @@ __setup("riohdid=", rio_hdid_setup);
1784 1880
1785int rio_register_mport(struct rio_mport *port) 1881int rio_register_mport(struct rio_mport *port)
1786{ 1882{
1883 struct rio_scan_node *scan = NULL;
1884
1787 if (next_portid >= RIO_MAX_MPORTS) { 1885 if (next_portid >= RIO_MAX_MPORTS) {
1788 pr_err("RIO: reached specified max number of mports\n"); 1886 pr_err("RIO: reached specified max number of mports\n");
1789 return 1; 1887 return 1;
@@ -1792,9 +1890,25 @@ int rio_register_mport(struct rio_mport *port)
1792 port->id = next_portid++; 1890 port->id = next_portid++;
1793 port->host_deviceid = rio_get_hdid(port->id); 1891 port->host_deviceid = rio_get_hdid(port->id);
1794 port->nscan = NULL; 1892 port->nscan = NULL;
1893
1795 mutex_lock(&rio_mport_list_lock); 1894 mutex_lock(&rio_mport_list_lock);
1796 list_add_tail(&port->node, &rio_mports); 1895 list_add_tail(&port->node, &rio_mports);
1896
1897 /*
1898 * Check if there are any registered enumeration/discovery operations
1899 * that have to be attached to the added mport.
1900 */
1901 list_for_each_entry(scan, &rio_scans, node) {
1902 if (port->id == scan->mport_id ||
1903 scan->mport_id == RIO_MPORT_ANY) {
1904 port->nscan = scan->ops;
1905 if (port->id == scan->mport_id)
1906 break;
1907 }
1908 }
1797 mutex_unlock(&rio_mport_list_lock); 1909 mutex_unlock(&rio_mport_list_lock);
1910
1911 pr_debug("RIO: %s %s id=%d\n", __func__, port->name, port->id);
1798 return 0; 1912 return 0;
1799} 1913}
1800 1914
diff --git a/drivers/rapidio/rio.h b/drivers/rapidio/rio.h
index d59587762c76..085215cd8502 100644
--- a/drivers/rapidio/rio.h
+++ b/drivers/rapidio/rio.h
@@ -42,9 +42,10 @@ extern int rio_add_device(struct rio_dev *rdev);
42extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid, 42extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
43 u8 hopcount, u8 port_num); 43 u8 hopcount, u8 port_num);
44extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops); 44extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
45extern int rio_unregister_scan(int mport_id); 45extern int rio_unregister_scan(int mport_id, struct rio_scan *scan_ops);
46extern void rio_attach_device(struct rio_dev *rdev); 46extern void rio_attach_device(struct rio_dev *rdev);
47extern struct rio_mport *rio_find_mport(int mport_id); 47extern struct rio_mport *rio_find_mport(int mport_id);
48extern int rio_mport_scan(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[];