From d39bf704acbd254576e3fc880ec13e6cd09e88c7 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 28 Dec 2015 11:59:01 +0530 Subject: [PATCH] greybus: interface: Fetch and expose version of interface's firmware The version of the currently running firmware on the module is useful for userspace as it can be used to find if an update is available or not. This patch fetches interface's version with a new control operation and exposes the same in userspace. Signed-off-by: Viresh Kumar Reviewed-by: Johan Hovold Signed-off-by: Greg Kroah-Hartman --- .../greybus/Documentation/sysfs-bus-greybus | 8 +++++ drivers/staging/greybus/control.c | 29 +++++++++++++++++++ drivers/staging/greybus/control.h | 1 + drivers/staging/greybus/greybus_protocols.h | 7 +++++ drivers/staging/greybus/interface.c | 15 ++++++++++ drivers/staging/greybus/interface.h | 3 ++ 6 files changed, 63 insertions(+) diff --git a/drivers/staging/greybus/Documentation/sysfs-bus-greybus b/drivers/staging/greybus/Documentation/sysfs-bus-greybus index 0d16d7649a5a..9ce36ddfb4da 100644 --- a/drivers/staging/greybus/Documentation/sysfs-bus-greybus +++ b/drivers/staging/greybus/Documentation/sysfs-bus-greybus @@ -73,6 +73,14 @@ Contact: Greg Kroah-Hartman Description: Vendor ID string of a Greybus interface block. +What: /sys/bus/greybus/device/N-I/version +Date: October 2015 +KernelVersion: 4.XX +Contact: Greg Kroah-Hartman +Description: + Interface version represented as <16 bit major number>.<16 bit + minor number>. + What: /sys/bus/greybus/device/N-I.B Date: October 2015 KernelVersion: 4.XX diff --git a/drivers/staging/greybus/control.c b/drivers/staging/greybus/control.c index 09ff79753313..4d65dbff6e93 100644 --- a/drivers/staging/greybus/control.c +++ b/drivers/staging/greybus/control.c @@ -59,6 +59,35 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id) sizeof(request), NULL, 0); } +int gb_control_get_interface_version_operation(struct gb_interface *intf) +{ + struct gb_control_interface_version_response response; + struct gb_connection *connection = intf->control->connection; + int ret; + + /* The ES3 bootrom fails to boot if this request it sent to it */ + if (intf->boot_over_unipro) + return 0; + + ret = gb_operation_sync(connection, GB_CONTROL_TYPE_INTERFACE_VERSION, + NULL, 0, &response, sizeof(response)); + if (ret) { + dev_err(&connection->intf->dev, + "failed to get interface version: %d\n", ret); + /* + * FIXME: Return success until the time we bump version of + * control protocol. The interface-version is already set to + * 0.0, so no need to update that. + */ + return 0; + } + + intf->version_major = le16_to_cpu(response.major); + intf->version_minor = le16_to_cpu(response.minor); + + return 0; +} + struct gb_control *gb_control_create(struct gb_interface *intf) { struct gb_control *control; diff --git a/drivers/staging/greybus/control.h b/drivers/staging/greybus/control.h index da0fa6652dca..7cb3dd2290d7 100644 --- a/drivers/staging/greybus/control.h +++ b/drivers/staging/greybus/control.h @@ -24,6 +24,7 @@ int gb_control_disconnected_operation(struct gb_control *control, u16 cport_id); int gb_control_get_manifest_size_operation(struct gb_interface *intf); int gb_control_get_manifest_operation(struct gb_interface *intf, void *manifest, size_t size); +int gb_control_get_interface_version_operation(struct gb_interface *intf); int gb_control_protocol_init(void); void gb_control_protocol_exit(void); diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index f66f4d784f27..a0bddaa36629 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -125,6 +125,7 @@ struct gb_protocol_version_response { #define GB_CONTROL_TYPE_GET_MANIFEST 0x04 #define GB_CONTROL_TYPE_CONNECTED 0x05 #define GB_CONTROL_TYPE_DISCONNECTED 0x06 +#define GB_CONTROL_TYPE_INTERFACE_VERSION 0x0a /* Control protocol manifest get size request has no payload*/ struct gb_control_get_manifest_size_response { @@ -146,6 +147,12 @@ struct gb_control_disconnected_request { } __packed; /* Control protocol [dis]connected response has no payload */ +/* Control protocol interface version request has no payload */ +struct gb_control_interface_version_response { + __le16 major; + __le16 minor; +} __packed; + /* Firmware Protocol */ diff --git a/drivers/staging/greybus/interface.c b/drivers/staging/greybus/interface.c index 69eb7886ceae..edac2383e492 100644 --- a/drivers/staging/greybus/interface.c +++ b/drivers/staging/greybus/interface.c @@ -29,6 +29,16 @@ gb_interface_attr(vendor_string, "%s"); gb_interface_attr(product_string, "%s"); gb_interface_attr(serial_number, "0x%016llx"); +static ssize_t version_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct gb_interface *intf = to_gb_interface(dev); + + return scnprintf(buf, PAGE_SIZE, "%u.%u\n", intf->version_major, + intf->version_minor); +} +static DEVICE_ATTR_RO(version); + static struct attribute *interface_attrs[] = { &dev_attr_ddbl1_manufacturer_id.attr, &dev_attr_ddbl1_product_id.attr, @@ -38,6 +48,7 @@ static struct attribute *interface_attrs[] = { &dev_attr_vendor_string.attr, &dev_attr_product_string.attr, &dev_attr_serial_number.attr, + &dev_attr_version.attr, NULL, }; ATTRIBUTE_GROUPS(interface); @@ -214,6 +225,10 @@ int gb_interface_init(struct gb_interface *intf, u8 device_id) goto free_manifest; } + ret = gb_control_get_interface_version_operation(intf); + if (ret) + goto free_manifest; + /* Register the interface and its bundles. */ ret = device_add(&intf->dev); if (ret) { diff --git a/drivers/staging/greybus/interface.h b/drivers/staging/greybus/interface.h index a1a1f9f5c2cb..4168a5752808 100644 --- a/drivers/staging/greybus/interface.h +++ b/drivers/staging/greybus/interface.h @@ -32,6 +32,9 @@ struct gb_interface { u32 product_id; u64 serial_number; + u16 version_major; + u16 version_minor; + struct gb_host_device *hd; /* The interface needs to boot over unipro */ -- 2.20.1