diff options
author | Greg Kroah-Hartman | 2014-10-24 11:34:46 +0200 |
---|---|---|
committer | Greg Kroah-Hartman | 2014-10-24 11:40:59 +0200 |
commit | f0f61b90427b776b884821cde483528580f6d630 (patch) | |
tree | 51666ef5ef41806e6d8f5f5b27ce69da286a460e /drivers/staging/greybus/connection.c | |
parent | greybus: update AP id service message (diff) | |
download | kernel-qcow2-linux-f0f61b90427b776b884821cde483528580f6d630.tar.gz kernel-qcow2-linux-f0f61b90427b776b884821cde483528580f6d630.tar.xz kernel-qcow2-linux-f0f61b90427b776b884821cde483528580f6d630.zip |
greybus: hook up greybus to the driver model
This patch hooks up modules, interfaces, and connections to the driver
model. Now we have a correct hierarchy, and drivers can be correctly
bound to the proper portions in the future. Devices are correctly
reference counted and torn down in the proper order on removal of a
module.
Some basic sysfs attributes have been created for interfaces and
connections. Module attributes are not working properly, but that will
be fixed in future changes.
This has been tested on Alex's machine, with multiple hotplug and unplug
operations of a module working correctly.
Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/staging/greybus/connection.c')
-rw-r--r-- | drivers/staging/greybus/connection.c | 59 |
1 files changed, 56 insertions, 3 deletions
diff --git a/drivers/staging/greybus/connection.c b/drivers/staging/greybus/connection.c index b1e933fc7044..2d71679ff66c 100644 --- a/drivers/staging/greybus/connection.c +++ b/drivers/staging/greybus/connection.c @@ -111,6 +111,44 @@ static void connection_timeout(struct work_struct *work) printk("timeout!\n"); } +static ssize_t state_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_connection *connection = to_gb_connection(dev); + + return sprintf(buf, "%d", connection->state); +} +static DEVICE_ATTR_RO(state); + +static ssize_t protocol_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_connection *connection = to_gb_connection(dev); + + return sprintf(buf, "%d", connection->protocol); +} +static DEVICE_ATTR_RO(protocol); + +static struct attribute *connection_attrs[] = { + &dev_attr_state.attr, + &dev_attr_protocol.attr, + NULL, +}; + +ATTRIBUTE_GROUPS(connection); + +static void gb_connection_release(struct device *dev) +{ + struct gb_connection *connection = to_gb_connection(dev); + + kfree(connection); +} + +static struct device_type greybus_connection_type = { + .name = "greybus_connection", + .release = gb_connection_release, +}; + /* * Set up a Greybus connection, representing the bidirectional link * between a CPort on a (local) Greybus host device and a CPort on @@ -127,6 +165,7 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, { struct gb_connection *connection; struct greybus_host_device *hd; + int retval; connection = kzalloc(sizeof(*connection), GFP_KERNEL); if (!connection) @@ -145,6 +184,21 @@ struct gb_connection *gb_connection_create(struct gb_interface *interface, connection->protocol = protocol; connection->state = GB_CONNECTION_STATE_DISABLED; + connection->dev.parent = &interface->dev; + connection->dev.driver = NULL; + connection->dev.bus = &greybus_bus_type; + connection->dev.type = &greybus_connection_type; + connection->dev.groups = connection_groups; + device_initialize(&connection->dev); + dev_set_name(&connection->dev, "%s:%d", + dev_name(&interface->dev), cport_id); + + retval = device_add(&connection->dev); + if (retval) { + kfree(connection); + return NULL; + } + spin_lock_irq(&gb_connections_lock); _gb_hd_connection_insert(hd, connection); list_add_tail(&connection->interface_links, &interface->connections); @@ -182,9 +236,8 @@ void gb_connection_destroy(struct gb_connection *connection) spin_unlock_irq(&gb_connections_lock); gb_connection_hd_cport_id_free(connection); - /* kref_put(connection->interface); */ - /* kref_put(connection->hd); */ - kfree(connection); + + device_del(&connection->dev); } u16 gb_connection_operation_id(struct gb_connection *connection) |