diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 642a393bd15f..7cbe71d581ac 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -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; diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 1b6882186459..82796512075b 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -72,14 +72,29 @@ #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) diff --git a/drivers/staging/greybus/greybus_protocols.h b/drivers/staging/greybus/greybus_protocols.h index e51c2b14875f..edbc5dfc448f 100644 --- a/drivers/staging/greybus/greybus_protocols.h +++ b/drivers/staging/greybus/greybus_protocols.h @@ -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 */