rapidio: rework device hierarchy and introduce mport class of devices
This patch removes an artificial RapidIO bus root device and establishes actual device hierarchy by providing reference to real parent devices. It also introduces device class for RapidIO controller devices (on-chip or an eternal bridge, known as "mport"). Existing implementation was sufficient for SoC-based platforms that have a single RapidIO controller. With introduction of devices using multiple RapidIO controllers and PCIe-to-RapidIO bridges the old scheme is very limiting or does not work at all. The implemented changes allow to properly reference platform's local RapidIO mport devices and provide device details needed for upper layers. This change to RapidIO device hierarchy does not break any known existing kernel or user space interfaces. 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-technologies.com> Cc: Stef van Os <stef.van.os@prodrive-technologies.com> Cc: Jerry Jacobs <jerry.jacobs@prodrive-technologies.com> Cc: Arno Tiemersma <arno.tiemersma@prodrive-technologies.com> Cc: Rob Landley <rob@landley.net> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
此提交包含在:
@@ -2256,6 +2256,7 @@ static int tsi721_setup_mport(struct tsi721_device *priv)
|
||||
mport->phy_type = RIO_PHY_SERIAL;
|
||||
mport->priv = (void *)priv;
|
||||
mport->phys_efptr = 0x100;
|
||||
mport->dev.parent = &pdev->dev;
|
||||
priv->mport = mport;
|
||||
|
||||
INIT_LIST_HEAD(&mport->dbells);
|
||||
|
@@ -167,7 +167,6 @@ void rio_unregister_driver(struct rio_driver *rdrv)
|
||||
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);
|
||||
|
||||
@@ -216,9 +215,12 @@ static int rio_uevent(struct device *dev, struct kobj_uevent_env *env)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct device rio_bus = {
|
||||
.init_name = "rapidio",
|
||||
struct class rio_mport_class = {
|
||||
.name = "rapidio_port",
|
||||
.owner = THIS_MODULE,
|
||||
.dev_groups = rio_mport_groups,
|
||||
};
|
||||
EXPORT_SYMBOL_GPL(rio_mport_class);
|
||||
|
||||
struct bus_type rio_bus_type = {
|
||||
.name = "rapidio",
|
||||
@@ -233,14 +235,20 @@ struct bus_type rio_bus_type = {
|
||||
/**
|
||||
* rio_bus_init - Register the RapidIO bus with the device model
|
||||
*
|
||||
* Registers the RIO bus device and RIO bus type with the Linux
|
||||
* Registers the RIO mport device class and RIO bus type with the Linux
|
||||
* device model.
|
||||
*/
|
||||
static int __init rio_bus_init(void)
|
||||
{
|
||||
if (device_register(&rio_bus) < 0)
|
||||
printk("RIO: failed to register RIO bus device\n");
|
||||
return bus_register(&rio_bus_type);
|
||||
int ret;
|
||||
|
||||
ret = class_register(&rio_mport_class);
|
||||
if (!ret) {
|
||||
ret = bus_register(&rio_bus_type);
|
||||
if (ret)
|
||||
class_unregister(&rio_mport_class);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
postcore_initcall(rio_bus_init);
|
||||
|
@@ -461,6 +461,7 @@ static struct rio_dev *rio_setup_device(struct rio_net *net,
|
||||
rdev->comp_tag & RIO_CTAG_UDEVID);
|
||||
}
|
||||
|
||||
rdev->dev.parent = &port->dev;
|
||||
rio_attach_device(rdev);
|
||||
|
||||
device_initialize(&rdev->dev);
|
||||
|
@@ -341,3 +341,43 @@ const struct attribute_group *rio_bus_groups[] = {
|
||||
&rio_bus_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static ssize_t
|
||||
port_destid_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rio_mport *mport = to_rio_mport(dev);
|
||||
|
||||
if (mport)
|
||||
return sprintf(buf, "0x%04x\n", mport->host_deviceid);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
static DEVICE_ATTR_RO(port_destid);
|
||||
|
||||
static ssize_t sys_size_show(struct device *dev, struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rio_mport *mport = to_rio_mport(dev);
|
||||
|
||||
if (mport)
|
||||
return sprintf(buf, "%u\n", mport->sys_size);
|
||||
else
|
||||
return -ENODEV;
|
||||
}
|
||||
static DEVICE_ATTR_RO(sys_size);
|
||||
|
||||
static struct attribute *rio_mport_attrs[] = {
|
||||
&dev_attr_port_destid.attr,
|
||||
&dev_attr_sys_size.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const struct attribute_group rio_mport_group = {
|
||||
.attrs = rio_mport_attrs,
|
||||
};
|
||||
|
||||
const struct attribute_group *rio_mport_groups[] = {
|
||||
&rio_mport_group,
|
||||
NULL,
|
||||
};
|
||||
|
@@ -1884,6 +1884,7 @@ static int rio_get_hdid(int index)
|
||||
int rio_register_mport(struct rio_mport *port)
|
||||
{
|
||||
struct rio_scan_node *scan = NULL;
|
||||
int res = 0;
|
||||
|
||||
if (next_portid >= RIO_MAX_MPORTS) {
|
||||
pr_err("RIO: reached specified max number of mports\n");
|
||||
@@ -1894,6 +1895,16 @@ int rio_register_mport(struct rio_mport *port)
|
||||
port->host_deviceid = rio_get_hdid(port->id);
|
||||
port->nscan = NULL;
|
||||
|
||||
dev_set_name(&port->dev, "rapidio%d", port->id);
|
||||
port->dev.class = &rio_mport_class;
|
||||
|
||||
res = device_register(&port->dev);
|
||||
if (res)
|
||||
dev_err(&port->dev, "RIO: mport%d registration failed ERR=%d\n",
|
||||
port->id, res);
|
||||
else
|
||||
dev_dbg(&port->dev, "RIO: mport%d registered\n", port->id);
|
||||
|
||||
mutex_lock(&rio_mport_list_lock);
|
||||
list_add_tail(&port->node, &rio_mports);
|
||||
|
||||
|
@@ -50,6 +50,7 @@ extern int rio_mport_scan(int mport_id);
|
||||
/* Structures internal to the RIO core code */
|
||||
extern const struct attribute_group *rio_dev_groups[];
|
||||
extern const struct attribute_group *rio_bus_groups[];
|
||||
extern const struct attribute_group *rio_mport_groups[];
|
||||
|
||||
#define RIO_GET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x00ff0000) >> 16))
|
||||
#define RIO_SET_DID(size, x) (size ? (x & 0xffff) : ((x & 0x000000ff) << 16))
|
||||
|
新增問題並參考
封鎖使用者