greybus: firmware: Add 'status' byte to backend fw version response
authorViresh Kumar <viresh.kumar@linaro.org>
Mon, 25 Jul 2016 21:38:08 +0000 (14:38 -0700)
committerGreg Kroah-Hartman <gregkh@google.com>
Tue, 26 Jul 2016 23:16:15 +0000 (16:16 -0700)
The backend processor may not be ready to return the version of firmware
it is running by the time AP requests for it. The greybus specification
is updated to return 1-byte 'status' to return the error type, RETRY is
one of them.

This patch implements that in greybus now.

Note that the version structure was common across interface and backend
version requests earlier, but that is changing as well.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
drivers/staging/greybus/fw-management.c
drivers/staging/greybus/greybus_firmware.h
drivers/staging/greybus/greybus_protocols.h

index 642a393..7cbe71d 100644 (file)
@@ -103,7 +103,7 @@ unlock:
 }
 
 static int fw_mgmt_interface_fw_version_operation(struct fw_mgmt *fw_mgmt,
-               struct fw_mgmt_ioc_get_fw *fw_info)
+               struct fw_mgmt_ioc_get_intf_version *fw_info)
 {
        struct gb_connection *connection = fw_mgmt->connection;
        struct gb_fw_mgmt_interface_fw_version_response response;
@@ -241,7 +241,7 @@ static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op)
 }
 
 static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt,
-               struct fw_mgmt_ioc_get_fw *fw_info)
+               struct fw_mgmt_ioc_get_backend_version *fw_info)
 {
        struct gb_connection *connection = fw_mgmt->connection;
        struct gb_fw_mgmt_backend_fw_version_request request;
@@ -269,8 +269,29 @@ static int fw_mgmt_backend_fw_version_operation(struct fw_mgmt *fw_mgmt,
                return ret;
        }
 
-       fw_info->major = le16_to_cpu(response.major);
-       fw_info->minor = le16_to_cpu(response.minor);
+       fw_info->status = response.status;
+
+       /* Reset version as that should be non-zero only for success case */
+       fw_info->major = 0;
+       fw_info->minor = 0;
+
+       switch (fw_info->status) {
+       case GB_FW_BACKEND_VERSION_STATUS_SUCCESS:
+               fw_info->major = le16_to_cpu(response.major);
+               fw_info->minor = le16_to_cpu(response.minor);
+               break;
+       case GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE:
+       case GB_FW_BACKEND_VERSION_STATUS_RETRY:
+               break;
+       case GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED:
+               dev_err(fw_mgmt->parent,
+                       "Firmware with tag %s is not supported by Interface\n",
+                       fw_info->firmware_tag);
+               break;
+       default:
+               dev_err(fw_mgmt->parent, "Invalid status received: %u\n",
+                       fw_info->status);
+       }
 
        return 0;
 }
@@ -387,7 +408,8 @@ static int fw_mgmt_release(struct inode *inode, struct file *file)
 static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd,
                         void __user *buf)
 {
-       struct fw_mgmt_ioc_get_fw fw_info;
+       struct fw_mgmt_ioc_get_intf_version intf_fw_info;
+       struct fw_mgmt_ioc_get_backend_version backend_fw_info;
        struct fw_mgmt_ioc_intf_load_and_validate intf_load;
        struct fw_mgmt_ioc_backend_fw_update backend_update;
        unsigned int timeout;
@@ -399,23 +421,27 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd,
 
        switch (cmd) {
        case FW_MGMT_IOC_GET_INTF_FW:
-               ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, &fw_info);
+               ret = fw_mgmt_interface_fw_version_operation(fw_mgmt,
+                                                            &intf_fw_info);
                if (ret)
                        return ret;
 
-               if (copy_to_user(buf, &fw_info, sizeof(fw_info)))
+               if (copy_to_user(buf, &intf_fw_info, sizeof(intf_fw_info)))
                        return -EFAULT;
 
                return 0;
        case FW_MGMT_IOC_GET_BACKEND_FW:
-               if (copy_from_user(&fw_info, buf, sizeof(fw_info)))
+               if (copy_from_user(&backend_fw_info, buf,
+                                  sizeof(backend_fw_info)))
                        return -EFAULT;
 
-               ret = fw_mgmt_backend_fw_version_operation(fw_mgmt, &fw_info);
+               ret = fw_mgmt_backend_fw_version_operation(fw_mgmt,
+                                                          &backend_fw_info);
                if (ret)
                        return ret;
 
-               if (copy_to_user(buf, &fw_info, sizeof(fw_info)))
+               if (copy_to_user(buf, &backend_fw_info,
+                                sizeof(backend_fw_info)))
                        return -EFAULT;
 
                return 0;
index 1b68821..8279651 100644 (file)
 #define GB_FW_U_BACKEND_FW_STATUS_FAIL_FETCH   0x03
 #define GB_FW_U_BACKEND_FW_STATUS_FAIL_WRITE   0x04
 #define GB_FW_U_BACKEND_FW_STATUS_INT          0x05
+#define GB_FW_U_BACKEND_FW_STATUS_RETRY                0x06
+#define GB_FW_U_BACKEND_FW_STATUS_NOT_SUPPORTED        0x07
+
+#define GB_FW_U_BACKEND_VERSION_STATUS_SUCCESS         0x01
+#define GB_FW_U_BACKEND_VERSION_STATUS_NOT_AVAILABLE   0x02
+#define GB_FW_U_BACKEND_VERSION_STATUS_NOT_SUPPORTED   0x03
+#define GB_FW_U_BACKEND_VERSION_STATUS_RETRY           0x04
+#define GB_FW_U_BACKEND_VERSION_STATUS_FAIL_INT                0x05
 
 /* IOCTL support */
-struct fw_mgmt_ioc_get_fw {
+struct fw_mgmt_ioc_get_intf_version {
        __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN];
        __u16 major;
        __u16 minor;
 } __attribute__ ((__packed__));
 
+struct fw_mgmt_ioc_get_backend_version {
+       __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN];
+       __u16 major;
+       __u16 minor;
+       __u8 status;
+} __attribute__ ((__packed__));
+
 struct fw_mgmt_ioc_intf_load_and_validate {
        __u8 firmware_tag[GB_FIRMWARE_U_TAG_MAX_LEN];
        __u8 load_method;
@@ -94,8 +109,8 @@ struct fw_mgmt_ioc_backend_fw_update {
 } __attribute__ ((__packed__));
 
 #define FW_MGMT_IOCTL_BASE                     'F'
-#define FW_MGMT_IOC_GET_INTF_FW                        _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_fw)
-#define FW_MGMT_IOC_GET_BACKEND_FW             _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_fw)
+#define FW_MGMT_IOC_GET_INTF_FW                        _IOR(FW_MGMT_IOCTL_BASE, 0, struct fw_mgmt_ioc_get_intf_version)
+#define FW_MGMT_IOC_GET_BACKEND_FW             _IOWR(FW_MGMT_IOCTL_BASE, 1, struct fw_mgmt_ioc_get_backend_version)
 #define FW_MGMT_IOC_INTF_LOAD_AND_VALIDATE     _IOWR(FW_MGMT_IOCTL_BASE, 2, struct fw_mgmt_ioc_intf_load_and_validate)
 #define FW_MGMT_IOC_INTF_BACKEND_FW_UPDATE     _IOWR(FW_MGMT_IOCTL_BASE, 3, struct fw_mgmt_ioc_backend_fw_update)
 #define FW_MGMT_IOC_SET_TIMEOUT_MS             _IOW(FW_MGMT_IOCTL_BASE, 4, unsigned int)
index e51c2b1..edbc5df 100644 (file)
@@ -370,6 +370,12 @@ struct gb_fw_download_release_firmware_request {
 #define GB_FW_BACKEND_FW_STATUS_RETRY          0x06
 #define GB_FW_BACKEND_FW_STATUS_NOT_SUPPORTED  0x07
 
+#define GB_FW_BACKEND_VERSION_STATUS_SUCCESS           0x01
+#define GB_FW_BACKEND_VERSION_STATUS_NOT_AVAILABLE     0x02
+#define GB_FW_BACKEND_VERSION_STATUS_NOT_SUPPORTED     0x03
+#define GB_FW_BACKEND_VERSION_STATUS_RETRY             0x04
+#define GB_FW_BACKEND_VERSION_STATUS_FAIL_INT          0x05
+
 /* firmware management interface firmware version request has no payload */
 struct gb_fw_mgmt_interface_fw_version_response {
        __u8                    firmware_tag[GB_FIRMWARE_TAG_MAX_LEN];
@@ -402,6 +408,7 @@ struct gb_fw_mgmt_backend_fw_version_request {
 struct gb_fw_mgmt_backend_fw_version_response {
        __le16                  major;
        __le16                  minor;
+       __u8                    status;
 } __packed;
 
 /* firmware management backend firmware update request */