diff options
author | Viresh Kumar <viresh.kumar@linaro.org> | 2016-05-14 23:42:22 +0530 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@google.com> | 2016-05-15 00:23:52 +0200 |
commit | 04f0e6ebd1a2ca3a1f1a356e9a07ef1797ef1b7c (patch) | |
tree | 18dbcd5ac2ca664710aa1c32ee9237914b4c183b | |
parent | 013e665372733fafd08599f0fc58ff5f450e4694 (diff) |
greybus: fw-management: Add ioctl to initiate mode-switch
Once the interface firmware is loaded successfully to a module,
userspace can ask it to mode switch to the newly loaded firmware.
This patch provides a new ioctl to initiate mode switch.
Userspace can initiate a mode switch if it has previously loaded the
interface firmware successfully, otherwise the firmware core rejects it.
Also, once the mode-switch is initiated, disallow any more interactions
from the userspace.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
Tested-by: Karthik Ravi Shankar <karthikrs@google.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@google.com>
-rw-r--r-- | drivers/staging/greybus/fw-management.c | 20 | ||||
-rw-r--r-- | drivers/staging/greybus/greybus_firmware.h | 1 |
2 files changed, 21 insertions, 0 deletions
diff --git a/drivers/staging/greybus/fw-management.c b/drivers/staging/greybus/fw-management.c index 2db5a11c5a1d..7c2226ab5d5c 100644 --- a/drivers/staging/greybus/fw-management.c +++ b/drivers/staging/greybus/fw-management.c @@ -34,6 +34,8 @@ struct fw_mgmt { unsigned int timeout_jiffies; /* Interface Firmware specific fields */ + bool mode_switch_started; + bool intf_fw_loaded; u8 intf_fw_request_id; u8 intf_fw_status; u16 intf_fw_major; @@ -123,6 +125,7 @@ static int fw_mgmt_load_and_validate_operation(struct fw_mgmt *fw_mgmt, } fw_mgmt->intf_fw_request_id = ret; + fw_mgmt->intf_fw_loaded = false; request.request_id = ret; ret = gb_operation_sync(fw_mgmt->connection, @@ -183,6 +186,8 @@ static int fw_mgmt_interface_fw_loaded_operation(struct gb_operation *op) dev_err(fw_mgmt->parent, "failed to validate interface firmware, status:%02x\n", fw_mgmt->intf_fw_status); + else + fw_mgmt->intf_fw_loaded = true; complete(&fw_mgmt->completion); @@ -329,6 +334,10 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, unsigned int timeout; int ret; + /* Reject any operations after mode-switch has started */ + if (fw_mgmt->mode_switch_started) + return -EBUSY; + switch (cmd) { case FW_MGMT_IOC_GET_INTF_FW: ret = fw_mgmt_interface_fw_version_operation(fw_mgmt, &fw_info); @@ -408,6 +417,17 @@ static int fw_mgmt_ioctl(struct fw_mgmt *fw_mgmt, unsigned int cmd, fw_mgmt->timeout_jiffies = msecs_to_jiffies(timeout); return 0; + case FW_MGMT_IOC_MODE_SWITCH: + if (!fw_mgmt->intf_fw_loaded) { + dev_err(fw_mgmt->parent, + "Firmware not loaded for mode-switch\n"); + return -EPERM; + } + + fw_mgmt->mode_switch_started = true; + + /* FIXME: Initiate mode-switch from here */ + return 0; default: return -ENOTTY; } diff --git a/drivers/staging/greybus/greybus_firmware.h b/drivers/staging/greybus/greybus_firmware.h index 9c5ad75438ae..4e194f21d475 100644 --- a/drivers/staging/greybus/greybus_firmware.h +++ b/drivers/staging/greybus/greybus_firmware.h @@ -79,6 +79,7 @@ struct fw_mgmt_ioc_backend_fw_update { #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) +#define FW_MGMT_IOC_MODE_SWITCH _IO(FW_MGMT_IOCTL_BASE, 5) #endif /* __GREYBUS_FIRMWARE_USER_H */ |