mei: expose fw version to sysfs
The ME FW version is constantly used by detection and update tools. To improve the reliability and simplify these tools provide a sysfs interface to access version of the platform ME firmware in the following format: <platform>:<major>.<minor>.<milestone>.<build>. There can be up to three such blocks for different FW components. Signed-off-by: Alexander Usyskin <alexander.usyskin@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
9a7c0b69b6
commit
3cfaeb3353
|
@ -54,3 +54,14 @@ Description: Configure tx queue limit
|
|||
|
||||
Set maximal number of pending writes
|
||||
per opened session.
|
||||
|
||||
What: /sys/class/mei/meiN/fw_ver
|
||||
Date: May 2018
|
||||
KernelVersion: 4.18
|
||||
Contact: Tomas Winkler <tomas.winkler@intel.com>
|
||||
Description: Display the ME firmware version.
|
||||
|
||||
The version of the platform ME firmware is in format:
|
||||
<platform>:<major>.<minor>.<milestone>.<build_no>.
|
||||
There can be up to three such blocks for different
|
||||
FW components.
|
||||
|
|
|
@ -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 < 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 (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);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*
|
||||
* Intel Management Engine Interface (Intel MEI) Linux driver
|
||||
* Copyright (c) 2003-2012, 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,
|
||||
|
@ -812,11 +812,39 @@ static ssize_t tx_queue_limit_store(struct device *device,
|
|||
}
|
||||
static DEVICE_ATTR_RW(tx_queue_limit);
|
||||
|
||||
/**
|
||||
* fw_ver_show - display ME FW version
|
||||
*
|
||||
* @device: device pointer
|
||||
* @attr: attribute pointer
|
||||
* @buf: char out buffer
|
||||
*
|
||||
* Return: number of the bytes printed into buf or error
|
||||
*/
|
||||
static ssize_t fw_ver_show(struct device *device,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct mei_device *dev = dev_get_drvdata(device);
|
||||
struct mei_fw_version *ver;
|
||||
ssize_t cnt = 0;
|
||||
int i;
|
||||
|
||||
ver = dev->fw_ver;
|
||||
|
||||
for (i = 0; i < MEI_MAX_FW_VER_BLOCKS; i++)
|
||||
cnt += scnprintf(buf + cnt, PAGE_SIZE - cnt, "%u:%u.%u.%u.%u\n",
|
||||
ver[i].platform, ver[i].major, ver[i].minor,
|
||||
ver[i].hotfix, ver[i].buildno);
|
||||
return cnt;
|
||||
}
|
||||
static DEVICE_ATTR_RO(fw_ver);
|
||||
|
||||
static struct attribute *mei_attrs[] = {
|
||||
&dev_attr_fw_status.attr,
|
||||
&dev_attr_hbm_ver.attr,
|
||||
&dev_attr_hbm_ver_drv.attr,
|
||||
&dev_attr_tx_queue_limit.attr,
|
||||
&dev_attr_fw_ver.attr,
|
||||
NULL
|
||||
};
|
||||
ATTRIBUTE_GROUPS(mei);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
/*
|
||||
*
|
||||
* Intel Management Engine Interface (Intel MEI) Linux driver
|
||||
* Copyright (c) 2003-2012, 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,
|
||||
|
@ -354,6 +354,25 @@ enum mei_pg_state {
|
|||
|
||||
const char *mei_pg_state_str(enum mei_pg_state state);
|
||||
|
||||
/**
|
||||
* struct mei_fw_version - MEI FW version struct
|
||||
*
|
||||
* @platform: platform identifier
|
||||
* @major: major version field
|
||||
* @minor: minor version field
|
||||
* @buildno: build number version field
|
||||
* @hotfix: hotfix number version field
|
||||
*/
|
||||
struct mei_fw_version {
|
||||
u8 platform;
|
||||
u8 major;
|
||||
u16 minor;
|
||||
u16 buildno;
|
||||
u16 hotfix;
|
||||
};
|
||||
|
||||
#define MEI_MAX_FW_VER_BLOCKS 3
|
||||
|
||||
/**
|
||||
* struct mei_device - MEI private device struct
|
||||
*
|
||||
|
@ -402,6 +421,8 @@ const char *mei_pg_state_str(enum mei_pg_state state);
|
|||
* @hbm_f_ie_supported : hbm feature immediate reply to enum request
|
||||
* @hbm_f_os_supported : hbm feature support OS ver message
|
||||
*
|
||||
* @fw_ver : FW versions
|
||||
*
|
||||
* @me_clients_rwsem: rw lock over me_clients list
|
||||
* @me_clients : list of FW clients
|
||||
* @me_clients_map : FW clients bit map
|
||||
|
@ -478,6 +499,8 @@ struct mei_device {
|
|||
unsigned int hbm_f_ie_supported:1;
|
||||
unsigned int hbm_f_os_supported:1;
|
||||
|
||||
struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS];
|
||||
|
||||
struct rw_semaphore me_clients_rwsem;
|
||||
struct list_head me_clients;
|
||||
DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
|
||||
|
|
Loading…
Reference in New Issue