greybus: svc: make svc a device
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 25 Nov 2015 14:59:06 +0000 (15:59 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 25 Nov 2015 23:30:03 +0000 (15:30 -0800)
Make the svc object a child device of the host-device device and use
driver core to manage its lifetime.

The svc device name is "<bus_id>-svc", where bus_id is the dynamically
assigned id of the host device.

Note that there is exactly one svc-device per host device (bus).

Signed-off-by: Johan Hovold <johan@hovoldconsulting.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/svc.c

index 79941583858b26e727dde0f49972843fea262b3b..8f4efb340f96717c340ff7d07ac7a2f88bba8683 100644 (file)
@@ -23,6 +23,8 @@ enum gb_svc_state {
 };
 
 struct gb_svc {
+       struct device           dev;
+
        struct gb_connection    *connection;
        enum gb_svc_state       state;
        struct ida              device_id_map;
@@ -667,19 +669,42 @@ static int gb_svc_request_recv(u8 type, struct gb_operation *op)
        }
 }
 
+static void gb_svc_release(struct device *dev)
+{
+       struct gb_svc *svc = container_of(dev, struct gb_svc, dev);
+
+       ida_destroy(&svc->device_id_map);
+       kfree(svc);
+}
+
+struct device_type greybus_svc_type = {
+       .name           = "greybus_svc",
+       .release        = gb_svc_release,
+};
+
 static int gb_svc_connection_init(struct gb_connection *connection)
 {
+       struct gb_host_device *hd = connection->hd;
        struct gb_svc *svc;
 
        svc = kzalloc(sizeof(*svc), GFP_KERNEL);
        if (!svc)
                return -ENOMEM;
 
-       connection->hd->svc = svc;
+       svc->dev.parent = &hd->dev;
+       svc->dev.bus = &greybus_bus_type;
+       svc->dev.type = &greybus_svc_type;
+       svc->dev.dma_mask = svc->dev.parent->dma_mask;
+       device_initialize(&svc->dev);
+
+       dev_set_name(&svc->dev, "%d-svc", hd->bus_id);
+
        svc->state = GB_SVC_STATE_RESET;
        svc->connection = connection;
        connection->private = svc;
 
+       hd->svc = svc;
+
        WARN_ON(connection->hd->initial_svc_connection);
        connection->hd->initial_svc_connection = connection;
 
@@ -692,10 +717,10 @@ static void gb_svc_connection_exit(struct gb_connection *connection)
 {
        struct gb_svc *svc = connection->private;
 
-       ida_destroy(&svc->device_id_map);
        connection->hd->svc = NULL;
        connection->private = NULL;
-       kfree(svc);
+
+       put_device(&svc->dev);
 }
 
 static struct gb_protocol svc_protocol = {