Commit 04f0e6eb authored by Viresh Kumar's avatar Viresh Kumar Committed by Greg Kroah-Hartman
Browse files

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: default avatarViresh Kumar <viresh.kumar@linaro.org>
Tested-by: default avatarKarthik Ravi Shankar <karthikrs@google.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@google.com>
parent 013e6653
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -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);
@@ -407,6 +416,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;
+1 −0
Original line number Diff line number Diff line
@@ -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 */