summaryrefslogtreecommitdiff
path: root/drivers/staging/greybus/fw-management.c
diff options
context:
space:
mode:
authorViresh Kumar <viresh.kumar@linaro.org>2016-05-14 23:42:22 +0530
committerGreg Kroah-Hartman <gregkh@google.com>2016-05-15 00:23:52 +0200
commit04f0e6ebd1a2ca3a1f1a356e9a07ef1797ef1b7c (patch)
tree18dbcd5ac2ca664710aa1c32ee9237914b4c183b /drivers/staging/greybus/fw-management.c
parent013e665372733fafd08599f0fc58ff5f450e4694 (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>
Diffstat (limited to 'drivers/staging/greybus/fw-management.c')
-rw-r--r--drivers/staging/greybus/fw-management.c20
1 files changed, 20 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;
}