diff options
Diffstat (limited to 'drivers/misc/mei/bus-fixup.c')
| -rw-r--r-- | drivers/misc/mei/bus-fixup.c | 92 | 
1 files changed, 83 insertions, 9 deletions
| diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c index 0208c4b027c5..a6f41f96f2a1 100644 --- a/drivers/misc/mei/bus-fixup.c +++ b/drivers/misc/mei/bus-fixup.c @@ -1,7 +1,7 @@  /*   *   * Intel Management Engine Interface (Intel MEI) Linux driver - * Copyright (c) 2003-2013, Intel Corporation. + * Copyright (c) 2003-2018, Intel Corporation.   *   * This program is free software; you can redistribute it and/or modify it   * under the terms and conditions of the GNU General Public License, @@ -96,8 +96,22 @@ struct mkhi_fwcaps {  	u8 data[0];  } __packed; +struct mkhi_fw_ver_block { +	u16 minor; +	u8 major; +	u8 platform; +	u16 buildno; +	u16 hotfix; +} __packed; + +struct mkhi_fw_ver { +	struct mkhi_fw_ver_block ver[MEI_MAX_FW_VER_BLOCKS]; +} __packed; +  #define MKHI_FWCAPS_GROUP_ID 0x3  #define MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD 6 +#define MKHI_GEN_GROUP_ID 0xFF +#define MKHI_GEN_GET_FW_VERSION_CMD 0x2  struct mkhi_msg_hdr {  	u8  group_id;  	u8  command; @@ -139,21 +153,81 @@ static int mei_osver(struct mei_cl_device *cldev)  	return __mei_cl_send(cldev->cl, buf, size, mode);  } +#define MKHI_FWVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \ +			    sizeof(struct mkhi_fw_ver)) +#define MKHI_FWVER_LEN(__num) (sizeof(struct mkhi_msg_hdr) + \ +			       sizeof(struct mkhi_fw_ver_block) * (__num)) +#define MKHI_RCV_TIMEOUT 500 /* receive timeout in msec */ +static int mei_fwver(struct mei_cl_device *cldev) +{ +	char buf[MKHI_FWVER_BUF_LEN]; +	struct mkhi_msg *req; +	struct mkhi_fw_ver *fwver; +	int bytes_recv, ret, i; + +	memset(buf, 0, sizeof(buf)); + +	req = (struct mkhi_msg *)buf; +	req->hdr.group_id = MKHI_GEN_GROUP_ID; +	req->hdr.command = MKHI_GEN_GET_FW_VERSION_CMD; + +	ret = __mei_cl_send(cldev->cl, buf, sizeof(struct mkhi_msg_hdr), +			    MEI_CL_IO_TX_BLOCKING); +	if (ret < 0) { +		dev_err(&cldev->dev, "Could not send ReqFWVersion cmd\n"); +		return ret; +	} + +	ret = 0; +	bytes_recv = __mei_cl_recv(cldev->cl, buf, sizeof(buf), 0, +				   MKHI_RCV_TIMEOUT); +	if (bytes_recv < 0 || (size_t)bytes_recv < MKHI_FWVER_LEN(1)) { +		/* +		 * Should be at least one version block, +		 * error out if nothing found +		 */ +		dev_err(&cldev->dev, "Could not read FW version\n"); +		return -EIO; +	} + +	fwver = (struct mkhi_fw_ver *)req->data; +	memset(cldev->bus->fw_ver, 0, sizeof(cldev->bus->fw_ver)); +	for (i = 0; i < MEI_MAX_FW_VER_BLOCKS; i++) { +		if ((size_t)bytes_recv < MKHI_FWVER_LEN(i + 1)) +			break; +		dev_dbg(&cldev->dev, "FW version%d %d:%d.%d.%d.%d\n", +			i, fwver->ver[i].platform, +			fwver->ver[i].major, fwver->ver[i].minor, +			fwver->ver[i].hotfix, fwver->ver[i].buildno); + +		cldev->bus->fw_ver[i].platform = fwver->ver[i].platform; +		cldev->bus->fw_ver[i].major = fwver->ver[i].major; +		cldev->bus->fw_ver[i].minor = fwver->ver[i].minor; +		cldev->bus->fw_ver[i].hotfix = fwver->ver[i].hotfix; +		cldev->bus->fw_ver[i].buildno = fwver->ver[i].buildno; +	} + +	return ret; +} +  static void mei_mkhi_fix(struct mei_cl_device *cldev)  {  	int ret; -	if (!cldev->bus->hbm_f_os_supported) -		return; -  	ret = mei_cldev_enable(cldev);  	if (ret)  		return; -	ret = mei_osver(cldev); +	ret = mei_fwver(cldev);  	if (ret < 0) -		dev_err(&cldev->dev, "OS version command failed %d\n", ret); +		dev_err(&cldev->dev, "FW version command failed %d\n", ret); +	if (cldev->bus->hbm_f_os_supported) { +		ret = mei_osver(cldev); +		if (ret < 0) +			dev_err(&cldev->dev, "OS version command failed %d\n", +				ret); +	}  	mei_cldev_disable(cldev);  } @@ -266,8 +340,8 @@ static int mei_nfc_if_version(struct mei_cl *cl,  		return -ENOMEM;  	ret = 0; -	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0); -	if (bytes_recv < if_version_length) { +	bytes_recv = __mei_cl_recv(cl, (u8 *)reply, if_version_length, 0, 0); +	if (bytes_recv < 0 || (size_t)bytes_recv < if_version_length) {  		dev_err(bus->dev, "Could not read IF version\n");  		ret = -EIO;  		goto err; @@ -410,7 +484,7 @@ void mei_cl_bus_dev_fixup(struct mei_cl_device *cldev)  {  	struct mei_fixup *f;  	const uuid_le *uuid = mei_me_cl_uuid(cldev->me_cl); -	int i; +	size_t i;  	for (i = 0; i < ARRAY_SIZE(mei_fixups); i++) { |