greybus: svc: register svc device at hello
authorJohan Hovold <johan@hovoldconsulting.com>
Wed, 25 Nov 2015 14:59:08 +0000 (15:59 +0100)
committerGreg Kroah-Hartman <gregkh@google.com>
Wed, 25 Nov 2015 23:30:03 +0000 (15:30 -0800)
Register the svc device upon reception of the HELLO request.

The SVC HELLO request contains the endo id and AP interface id, which
will be exposed from the svc device rather than the endo.

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

index 8c8ba02b76e9ee03c92d2ecc4eef2f47474e4f2f..d1e26c4a26fced479d0e942423d12dac2a1ae2a8 100644 (file)
@@ -81,6 +81,7 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
        struct gb_module *module = NULL;
        struct gb_interface *intf = NULL;
        struct gb_bundle *bundle = NULL;
+       struct gb_svc *svc = NULL;
 
        if (is_gb_endo(dev)) {
                /*
@@ -99,6 +100,8 @@ static int greybus_uevent(struct device *dev, struct kobj_uevent_env *env)
        } else if (is_gb_bundle(dev)) {
                bundle = to_gb_bundle(dev);
                intf = bundle->intf;
+       } else if (is_gb_svc(dev)) {
+               svc = to_gb_svc(dev);
        } else {
                dev_WARN(dev, "uevent for unknown greybus device \"type\"!\n");
                return -EINVAL;
index 8ef3a0426a0923a06a3d9af7900ee5d14e9834d7..fa81733282d6de5800bd975ebe408c903f0ec9df 100644 (file)
@@ -109,6 +109,7 @@ extern struct device_type greybus_endo_type;
 extern struct device_type greybus_module_type;
 extern struct device_type greybus_interface_type;
 extern struct device_type greybus_bundle_type;
+extern struct device_type greybus_svc_type;
 
 static inline int is_gb_host_device(const struct device *dev)
 {
@@ -135,6 +136,11 @@ static inline int is_gb_bundle(const struct device *dev)
        return dev->type == &greybus_bundle_type;
 }
 
+static inline int is_gb_svc(const struct device *dev)
+{
+       return dev->type == &greybus_svc_type;
+}
+
 static inline bool cport_id_valid(struct gb_host_device *hd, u16 cport_id)
 {
        return cport_id != CPORT_ID_BAD && cport_id < hd->num_cports;
index 5aa21f7c591df26f473e34bd5bd5d5e6523bb0cd..fab5c45c0701c096a3c071461a4856a3f8cf9160 100644 (file)
 #define CPORT_FLAGS_CSD_N       BIT(1)
 #define CPORT_FLAGS_CSV_N       BIT(2)
 
-enum gb_svc_state {
-       GB_SVC_STATE_RESET,
-       GB_SVC_STATE_PROTOCOL_VERSION,
-       GB_SVC_STATE_SVC_HELLO,
-};
-
-struct gb_svc {
-       struct device           dev;
-
-       struct gb_connection    *connection;
-       enum gb_svc_state       state;
-       struct ida              device_id_map;
-};
 
 struct svc_hotplug {
        struct work_struct work;
@@ -348,6 +335,7 @@ static int gb_svc_version_request(struct gb_operation *op)
 static int gb_svc_hello(struct gb_operation *op)
 {
        struct gb_connection *connection = op->connection;
+       struct gb_svc *svc = connection->private;
        struct gb_host_device *hd = connection->hd;
        struct gb_svc_hello_request *hello_request;
        struct gb_interface *intf;
@@ -370,6 +358,12 @@ static int gb_svc_hello(struct gb_operation *op)
        endo_id = le16_to_cpu(hello_request->endo_id);
        interface_id = hello_request->interface_id;
 
+       ret = device_add(&svc->dev);
+       if (ret) {
+               dev_err(&svc->dev, "failed to register svc device: %d\n", ret);
+               return ret;
+       }
+
        /* Setup Endo */
        ret = greybus_endo_setup(hd, endo_id, interface_id);
        if (ret)
@@ -671,7 +665,7 @@ 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);
+       struct gb_svc *svc = to_gb_svc(dev);
 
        ida_destroy(&svc->device_id_map);
        kfree(svc);
@@ -716,6 +710,9 @@ static void gb_svc_connection_exit(struct gb_connection *connection)
 {
        struct gb_svc *svc = connection->private;
 
+       if (device_is_registered(&svc->dev))
+               device_del(&svc->dev);
+
        connection->hd->svc = NULL;
        connection->private = NULL;
 
index d2f406fa798a6f3ce7cd71c1bd07acfbb1ce520e..c9d8866f8f298dfc684351e5d3596df47d535776 100644 (file)
 #ifndef __SVC_H
 #define __SVC_H
 
-struct gb_svc;
+enum gb_svc_state {
+       GB_SVC_STATE_RESET,
+       GB_SVC_STATE_PROTOCOL_VERSION,
+       GB_SVC_STATE_SVC_HELLO,
+};
+
+struct gb_svc {
+       struct device           dev;
+
+       struct gb_connection    *connection;
+       enum gb_svc_state       state;
+       struct ida              device_id_map;
+};
+#define to_gb_svc(d) container_of(d, struct gb_svc, d)
 
 int gb_svc_intf_reset(struct gb_svc *svc, u8 intf_id);
 int gb_svc_connection_create(struct gb_svc *svc, u8 intf1_id, u16 cport1_id,