Skip to content

Commit 9edbc30

Browse files
Alexandre Bouninetorvalds
authored andcommitted
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>
1 parent e6161d6 commit 9edbc30

File tree

5 files changed

+164
-48
lines changed

5 files changed

+164
-48
lines changed

drivers/rapidio/rio-scan.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,7 @@ static int rio_disc_mport(struct rio_mport *mport, u32 flags)
11621162
}
11631163

11641164
static struct rio_scan rio_scan_ops = {
1165+
.owner = THIS_MODULE,
11651166
.enumerate = rio_enum_mport,
11661167
.discover = rio_disc_mport,
11671168
};

drivers/rapidio/rio-sysfs.c

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,6 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
286286
size_t count)
287287
{
288288
long val;
289-
struct rio_mport *port = NULL;
290289
int rc;
291290

292291
if (kstrtol(buf, 0, &val) < 0)
@@ -300,21 +299,7 @@ static ssize_t bus_scan_store(struct bus_type *bus, const char *buf,
300299
if (val < 0 || val >= RIO_MAX_MPORTS)
301300
return -EINVAL;
302301

303-
port = rio_find_mport((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);
302+
rc = rio_mport_scan((int)val);
318303
exit:
319304
if (!rc)
320305
rc = count;

drivers/rapidio/rio.c

Lines changed: 145 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ static LIST_HEAD(rio_devices);
3434
static DEFINE_SPINLOCK(rio_global_list_lock);
3535

3636
static LIST_HEAD(rio_mports);
37+
static LIST_HEAD(rio_scans);
3738
static DEFINE_MUTEX(rio_mport_list_lock);
3839
static unsigned char next_portid;
3940
static DEFINE_SPINLOCK(rio_mmap_lock);
@@ -1602,34 +1603,73 @@ struct rio_mport *rio_find_mport(int mport_id)
16021603
* rio_register_scan - enumeration/discovery method registration interface
16031604
* @mport_id: mport device ID for which fabric scan routine has to be set
16041605
* (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).
16061611
*
1607-
* Assigns enumeration or discovery method to the specified mport device (or all
1608-
* available mports if RIO_MPORT_ANY is specified).
16091612
* 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
1611-
* an error if was unable to find at least one available mport.
1613+
* In case of RIO_MPORT_ANY skips mports with valid scan routines (no error).
16121614
*/
16131615
int rio_register_scan(int mport_id, struct rio_scan *scan_ops)
16141616
{
16151617
struct rio_mport *port;
1616-
int rc = -EBUSY;
1618+
struct rio_scan_node *scan;
1619+
int rc = 0;
16171620

1618-
mutex_lock(&rio_mport_list_lock);
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;
1621+
pr_debug("RIO: %s for mport_id=%d\n", __func__, mport_id);
16251622

1626-
port->nscan = scan_ops;
1627-
rc = 0;
1623+
if ((mport_id != RIO_MPORT_ANY && mport_id >= RIO_MAX_MPORTS) ||
1624+
!scan_ops)
1625+
return -EINVAL;
16281626

1629-
if (mport_id != RIO_MPORT_ANY)
1630-
break;
1627+
mutex_lock(&rio_mport_list_lock);
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;
16311638
}
16321639
}
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+
1672+
err_out:
16331673
mutex_unlock(&rio_mport_list_lock);
16341674

16351675
return rc;
@@ -1639,30 +1679,81 @@ EXPORT_SYMBOL_GPL(rio_register_scan);
16391679
/**
16401680
* rio_unregister_scan - removes enumeration/discovery method from mport
16411681
* @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
16431685
*
16441686
* 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.
16461689
*/
1647-
int rio_unregister_scan(int mport_id)
1690+
int rio_unregister_scan(int mport_id, struct rio_scan *scan_ops)
16481691
{
16491692
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;
16501699

16511700
mutex_lock(&rio_mport_list_lock);
1652-
list_for_each_entry(port, &rio_mports, node) {
1653-
if (port->id == mport_id || mport_id == RIO_MPORT_ANY) {
1654-
if (port->nscan)
1655-
port->nscan = NULL;
1656-
if (mport_id != RIO_MPORT_ANY)
1657-
break;
1701+
1702+
list_for_each_entry(port, &rio_mports, node)
1703+
if (port->id == mport_id ||
1704+
(mport_id == RIO_MPORT_ANY && port->nscan == scan_ops))
1705+
port->nscan = NULL;
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);
16581711
}
1659-
}
1712+
16601713
mutex_unlock(&rio_mport_list_lock);
16611714

16621715
return 0;
16631716
}
16641717
EXPORT_SYMBOL_GPL(rio_unregister_scan);
16651718

1719+
/**
1720+
* rio_mport_scan - execute enumeration/discovery on the specified mport
1721+
* @mport_id: number (ID) of mport device
1722+
*/
1723+
int 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;
1735+
found:
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+
16661757
static void rio_fixup_device(struct rio_dev *dev)
16671758
{
16681759
}
@@ -1691,7 +1782,10 @@ static void disc_work_handler(struct work_struct *_work)
16911782
work = container_of(_work, struct rio_disc_work, work);
16921783
pr_debug("RIO: discovery work for mport %d %s\n",
16931784
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+
}
16951789
}
16961790

16971791
int rio_init_mports(void)
@@ -1710,8 +1804,10 @@ int rio_init_mports(void)
17101804
mutex_lock(&rio_mport_list_lock);
17111805
list_for_each_entry(port, &rio_mports, node) {
17121806
if (port->host_deviceid >= 0) {
1713-
if (port->nscan)
1807+
if (port->nscan && try_module_get(port->nscan->owner)) {
17141808
port->nscan->enumerate(port, 0);
1809+
module_put(port->nscan->owner);
1810+
}
17151811
} else
17161812
n++;
17171813
}
@@ -1725,7 +1821,7 @@ int rio_init_mports(void)
17251821
* for each of them. If the code below fails to allocate needed
17261822
* resources, exit without error to keep results of enumeration
17271823
* process (if any).
1728-
* TODO: Implement restart of dicovery process for all or
1824+
* TODO: Implement restart of discovery process for all or
17291825
* individual discovering mports.
17301826
*/
17311827
rio_wq = alloc_workqueue("riodisc", 0, 0);
@@ -1751,9 +1847,9 @@ int rio_init_mports(void)
17511847
n++;
17521848
}
17531849
}
1754-
mutex_unlock(&rio_mport_list_lock);
17551850

17561851
flush_workqueue(rio_wq);
1852+
mutex_unlock(&rio_mport_list_lock);
17571853
pr_debug("RIO: destroy discovery workqueue\n");
17581854
destroy_workqueue(rio_wq);
17591855
kfree(work);
@@ -1784,6 +1880,8 @@ __setup("riohdid=", rio_hdid_setup);
17841880

17851881
int rio_register_mport(struct rio_mport *port)
17861882
{
1883+
struct rio_scan_node *scan = NULL;
1884+
17871885
if (next_portid >= RIO_MAX_MPORTS) {
17881886
pr_err("RIO: reached specified max number of mports\n");
17891887
return 1;
@@ -1792,9 +1890,25 @@ int rio_register_mport(struct rio_mport *port)
17921890
port->id = next_portid++;
17931891
port->host_deviceid = rio_get_hdid(port->id);
17941892
port->nscan = NULL;
1893+
17951894
mutex_lock(&rio_mport_list_lock);
17961895
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+
}
17971909
mutex_unlock(&rio_mport_list_lock);
1910+
1911+
pr_debug("RIO: %s %s id=%d\n", __func__, port->name, port->id);
17981912
return 0;
17991913
}
18001914

drivers/rapidio/rio.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,9 +42,10 @@ extern int rio_add_device(struct rio_dev *rdev);
4242
extern int rio_enable_rx_tx_port(struct rio_mport *port, int local, u16 destid,
4343
u8 hopcount, u8 port_num);
4444
extern int rio_register_scan(int mport_id, struct rio_scan *scan_ops);
45-
extern int rio_unregister_scan(int mport_id);
45+
extern int rio_unregister_scan(int mport_id, struct rio_scan *scan_ops);
4646
extern void rio_attach_device(struct rio_dev *rdev);
4747
extern struct rio_mport *rio_find_mport(int mport_id);
48+
extern int rio_mport_scan(int mport_id);
4849

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

include/linux/rio.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -465,14 +465,29 @@ static inline struct rio_mport *dma_to_mport(struct dma_device *ddev)
465465

466466
/**
467467
* struct rio_scan - RIO enumeration and discovery operations
468+
* @owner: The module owner of this structure
468469
* @enumerate: Callback to perform RapidIO fabric enumeration.
469470
* @discover: Callback to perform RapidIO fabric discovery.
470471
*/
471472
struct rio_scan {
473+
struct module *owner;
472474
int (*enumerate)(struct rio_mport *mport, u32 flags);
473475
int (*discover)(struct rio_mport *mport, u32 flags);
474476
};
475477

478+
/**
479+
* struct rio_scan_node - list node to register RapidIO enumeration and
480+
* discovery methods with RapidIO core.
481+
* @mport_id: ID of an mport (net) serviced by this enumerator
482+
* @node: node in global list of registered enumerators
483+
* @ops: RIO enumeration and discovery operations
484+
*/
485+
struct rio_scan_node {
486+
int mport_id;
487+
struct list_head node;
488+
struct rio_scan *ops;
489+
};
490+
476491
/* Architecture and hardware-specific functions */
477492
extern int rio_register_mport(struct rio_mport *);
478493
extern int rio_open_inb_mbox(struct rio_mport *, void *, int, int);

0 commit comments

Comments
 (0)