aboutsummaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/interface.c
diff options
context:
space:
mode:
authorGravatar Viresh Kumar <viresh.kumar@linaro.org> 2015-06-22 16:42:27 +0530
committerGravatar Greg Kroah-Hartman <gregkh@google.com> 2015-06-23 23:16:15 -0700
commit6c68da264b080f749e8848b0227e6bb7d7c72f21 (patch)
tree9092b29b987a070bf14d925dfd3e10d1bc3821bb /drivers/staging/greybus/interface.c
parentgreybus: Add control protocol support (diff)
downloadlinux-6c68da264b080f749e8848b0227e6bb7d7c72f21.tar.gz
linux-6c68da264b080f749e8848b0227e6bb7d7c72f21.tar.bz2
linux-6c68da264b080f749e8848b0227e6bb7d7c72f21.zip
greybus: interface: Get manifest using Control protocol
Control protocol is ready to be used for fetching manifest. Lets do it. This changes few things: - Creates/initializes bundle/connection for control protocol initially and skips doing the same later. - Manifest is parsed at link-up now, instead of hotplug which was the case earlier. This is because we need device_id (provided during link-up) for registering bundle. - Manifest is fetched using control protocol. So the sequence of events is: Event Previously Now ----- ---------- --- Interface Hotplug create intf create intf parse mfst Interface Link Up init bundles create control conn get mfst size get mfst parse mfst init bundles Reviewed-by: Alex Elder <elder@linaro.org> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
Diffstat (limited to 'drivers/staging/greybus/interface.c')
-rw-r--r--drivers/staging/greybus/interface.c100
1 files changed, 80 insertions, 20 deletions
diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c
index 5b1621ccf724..901c4acc2421 100644
--- a/drivers/staging/greybus/interface.c
+++ b/drivers/staging/greybus/interface.c
@@ -67,6 +67,36 @@ struct device_type greybus_interface_type = {
};
/*
+ * Create kernel structures corresponding to a bundle and connection for
+ * managing control CPort. Also initialize the bundle, which will request SVC to
+ * set route and will initialize the control protocol for this connection.
+ */
+static int gb_create_control_connection(struct gb_interface *intf, u8 device_id)
+{
+ struct gb_bundle *bundle;
+ int ret;
+
+ bundle = gb_bundle_create(intf, GB_CONTROL_BUNDLE_ID,
+ GREYBUS_CLASS_CONTROL);
+ if (!bundle)
+ return -EINVAL;
+
+ if (!gb_connection_create(bundle, GB_CONTROL_CPORT_ID,
+ GREYBUS_PROTOCOL_CONTROL))
+ return -EINVAL;
+
+ ret = gb_bundle_init(bundle, device_id);
+ if (ret) {
+ dev_err(&intf->dev,
+ "error %d initializing bundles for interface %hu\n",
+ ret, intf->interface_id);
+ return ret;
+ }
+
+ return 0;
+}
+
+/*
* A Greybus module represents a user-replicable component on an Ara
* phone. An interface is the physical connection on that module. A
* module may have more than one interface.
@@ -78,8 +108,8 @@ struct device_type greybus_interface_type = {
* Returns a pointer to the new interfce or a null pointer if a
* failure occurs due to memory exhaustion.
*/
-static struct gb_interface *gb_interface_create(struct greybus_host_device *hd,
- u8 interface_id)
+struct gb_interface *gb_interface_create(struct greybus_host_device *hd,
+ u8 interface_id)
{
struct gb_module *module;
struct gb_interface *intf;
@@ -165,29 +195,60 @@ static void gb_interface_destroy(struct gb_interface *intf)
/**
* gb_interface_add
*
- * Pass in a buffer that _should_ contain a Greybus manifest
- * and register a greybus device structure with the kernel core.
+ * Create connection for control CPort and then request/parse manifest.
+ * Finally initialize all the bundles to set routes via SVC and initialize all
+ * connections.
*/
-void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data,
- int size)
+int gb_interface_init(struct gb_interface *intf, u8 device_id)
{
- struct gb_interface *intf;
+ int ret, size;
+ void *manifest;
+
+ /* Establish control CPort connection */
+ ret = gb_create_control_connection(intf, device_id);
+ if (ret) {
+ dev_err(&intf->dev, "Failed to create control CPort connection (%d)\n", ret);
+ return ret;
+ }
- intf = gb_interface_create(hd, interface_id);
- if (!intf) {
- dev_err(hd->parent, "failed to create interface\n");
- return;
+ /* Get manifest size using control protocol on CPort */
+ size = gb_control_get_manifest_size_operation(intf);
+ if (size <= 0) {
+ dev_err(&intf->dev, "%s: Failed to get manifest size (%d)\n",
+ __func__, size);
+ if (size)
+ return size;
+ else
+ return -EINVAL;
+ }
+
+ manifest = kmalloc(size, GFP_KERNEL);
+ if (!manifest)
+ return -ENOMEM;
+
+ /* Get manifest using control protocol on CPort */
+ ret = gb_control_get_manifest_operation(intf, manifest, size);
+ if (ret) {
+ dev_err(&intf->dev, "%s: Failed to get manifest\n", __func__);
+ goto free_manifest;
}
/*
- * Parse the manifest and build up our data structures
- * representing what's in it.
+ * Parse the manifest and build up our data structures representing
+ * what's in it.
*/
- if (!gb_manifest_parse(intf, data, size)) {
- dev_err(hd->parent, "manifest error\n");
- goto err_parse;
+ if (!gb_manifest_parse(intf, manifest, size)) {
+ dev_err(&intf->dev, "%s: Failed to parse manifest\n", __func__);
+ ret = -EINVAL;
+ goto free_manifest;
}
+ ret = gb_bundles_init(intf, device_id);
+ if (ret)
+ dev_err(&intf->dev,
+ "Error %d initializing bundles for interface %hu\n",
+ ret, intf->interface_id);
+
/*
* XXX
* We've successfully parsed the manifest. Now we need to
@@ -197,10 +258,9 @@ void gb_interface_add(struct greybus_host_device *hd, u8 interface_id, u8 *data,
* configuring the switch to allow them to communicate).
*/
- return;
-
-err_parse:
- gb_interface_destroy(intf);
+free_manifest:
+ kfree(manifest);
+ return ret;
}
void gb_interface_remove(struct greybus_host_device *hd, u8 interface_id)