summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Usyskin <alexander.usyskin@intel.com>2018-06-24 17:11:41 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-03 07:11:20 -0400
commit3cfaeb33530592b02b2ceb76b379364c55ca612e (patch)
tree16b29db30b99b2a233b0817a6f694d6c15bf02b0
parent9a7c0b69b6e765c655133ef530876aea3da71d58 (diff)
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>
-rw-r--r--Documentation/ABI/testing/sysfs-class-mei11
-rw-r--r--drivers/misc/mei/bus-fixup.c86
-rw-r--r--drivers/misc/mei/main.c30
-rw-r--r--drivers/misc/mei/mei_dev.h25
4 files changed, 144 insertions, 8 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-mei b/Documentation/ABI/testing/sysfs-class-mei
index 81ff6abf9673..17d7444a2397 100644
--- a/Documentation/ABI/testing/sysfs-class-mei
+++ b/Documentation/ABI/testing/sysfs-class-mei
@@ -54,3 +54,14 @@ Description: Configure tx queue limit
54 54
55 Set maximal number of pending writes 55 Set maximal number of pending writes
56 per opened session. 56 per opened session.
57
58What: /sys/class/mei/meiN/fw_ver
59Date: May 2018
60KernelVersion: 4.18
61Contact: Tomas Winkler <tomas.winkler@intel.com>
62Description: Display the ME firmware version.
63
64 The version of the platform ME firmware is in format:
65 <platform>:<major>.<minor>.<milestone>.<build_no>.
66 There can be up to three such blocks for different
67 FW components.
diff --git a/drivers/misc/mei/bus-fixup.c b/drivers/misc/mei/bus-fixup.c
index b17c46a43812..e45fe826d87d 100644
--- a/drivers/misc/mei/bus-fixup.c
+++ b/drivers/misc/mei/bus-fixup.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * 2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver 3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2013, Intel Corporation. 4 * Copyright (c) 2003-2018, Intel Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -96,8 +96,22 @@ struct mkhi_fwcaps {
96 u8 data[0]; 96 u8 data[0];
97} __packed; 97} __packed;
98 98
99struct mkhi_fw_ver_block {
100 u16 minor;
101 u8 major;
102 u8 platform;
103 u16 buildno;
104 u16 hotfix;
105} __packed;
106
107struct mkhi_fw_ver {
108 struct mkhi_fw_ver_block ver[MEI_MAX_FW_VER_BLOCKS];
109} __packed;
110
99#define MKHI_FWCAPS_GROUP_ID 0x3 111#define MKHI_FWCAPS_GROUP_ID 0x3
100#define MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD 6 112#define MKHI_FWCAPS_SET_OS_VER_APP_RULE_CMD 6
113#define MKHI_GEN_GROUP_ID 0xFF
114#define MKHI_GEN_GET_FW_VERSION_CMD 0x2
101struct mkhi_msg_hdr { 115struct mkhi_msg_hdr {
102 u8 group_id; 116 u8 group_id;
103 u8 command; 117 u8 command;
@@ -139,21 +153,81 @@ static int mei_osver(struct mei_cl_device *cldev)
139 return __mei_cl_send(cldev->cl, buf, size, mode); 153 return __mei_cl_send(cldev->cl, buf, size, mode);
140} 154}
141 155
156#define MKHI_FWVER_BUF_LEN (sizeof(struct mkhi_msg_hdr) + \
157 sizeof(struct mkhi_fw_ver))
158#define MKHI_FWVER_LEN(__num) (sizeof(struct mkhi_msg_hdr) + \
159 sizeof(struct mkhi_fw_ver_block) * (__num))
160#define MKHI_RCV_TIMEOUT 500 /* receive timeout in msec */
161static int mei_fwver(struct mei_cl_device *cldev)
162{
163 char buf[MKHI_FWVER_BUF_LEN];
164 struct mkhi_msg *req;
165 struct mkhi_fw_ver *fwver;
166 int bytes_recv, ret, i;
167
168 memset(buf, 0, sizeof(buf));
169
170 req = (struct mkhi_msg *)buf;
171 req->hdr.group_id = MKHI_GEN_GROUP_ID;
172 req->hdr.command = MKHI_GEN_GET_FW_VERSION_CMD;
173
174 ret = __mei_cl_send(cldev->cl, buf, sizeof(struct mkhi_msg_hdr),
175 MEI_CL_IO_TX_BLOCKING);
176 if (ret < 0) {
177 dev_err(&cldev->dev, "Could not send ReqFWVersion cmd\n");
178 return ret;
179 }
180
181 ret = 0;
182 bytes_recv = __mei_cl_recv(cldev->cl, buf, sizeof(buf), 0,
183 MKHI_RCV_TIMEOUT);
184 if (bytes_recv < MKHI_FWVER_LEN(1)) {
185 /*
186 * Should be at least one version block,
187 * error out if nothing found
188 */
189 dev_err(&cldev->dev, "Could not read FW version\n");
190 return -EIO;
191 }
192
193 fwver = (struct mkhi_fw_ver *)req->data;
194 memset(cldev->bus->fw_ver, 0, sizeof(cldev->bus->fw_ver));
195 for (i = 0; i < MEI_MAX_FW_VER_BLOCKS; i++) {
196 if (bytes_recv < MKHI_FWVER_LEN(i + 1))
197 break;
198 dev_dbg(&cldev->dev, "FW version%d %d:%d.%d.%d.%d\n",
199 i, fwver->ver[i].platform,
200 fwver->ver[i].major, fwver->ver[i].minor,
201 fwver->ver[i].hotfix, fwver->ver[i].buildno);
202
203 cldev->bus->fw_ver[i].platform = fwver->ver[i].platform;
204 cldev->bus->fw_ver[i].major = fwver->ver[i].major;
205 cldev->bus->fw_ver[i].minor = fwver->ver[i].minor;
206 cldev->bus->fw_ver[i].hotfix = fwver->ver[i].hotfix;
207 cldev->bus->fw_ver[i].buildno = fwver->ver[i].buildno;
208 }
209
210 return ret;
211}
212
142static void mei_mkhi_fix(struct mei_cl_device *cldev) 213static void mei_mkhi_fix(struct mei_cl_device *cldev)
143{ 214{
144 int ret; 215 int ret;
145 216
146 if (!cldev->bus->hbm_f_os_supported)
147 return;
148
149 ret = mei_cldev_enable(cldev); 217 ret = mei_cldev_enable(cldev);
150 if (ret) 218 if (ret)
151 return; 219 return;
152 220
153 ret = mei_osver(cldev); 221 ret = mei_fwver(cldev);
154 if (ret < 0) 222 if (ret < 0)
155 dev_err(&cldev->dev, "OS version command failed %d\n", ret); 223 dev_err(&cldev->dev, "FW version command failed %d\n", ret);
156 224
225 if (cldev->bus->hbm_f_os_supported) {
226 ret = mei_osver(cldev);
227 if (ret < 0)
228 dev_err(&cldev->dev, "OS version command failed %d\n",
229 ret);
230 }
157 mei_cldev_disable(cldev); 231 mei_cldev_disable(cldev);
158} 232}
159 233
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
index 7465f17e1559..f690918f7817 100644
--- a/drivers/misc/mei/main.c
+++ b/drivers/misc/mei/main.c
@@ -1,7 +1,7 @@
1/* 1/*
2 * 2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver 3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation. 4 * Copyright (c) 2003-2018, Intel Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * 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,
812} 812}
813static DEVICE_ATTR_RW(tx_queue_limit); 813static DEVICE_ATTR_RW(tx_queue_limit);
814 814
815/**
816 * fw_ver_show - display ME FW version
817 *
818 * @device: device pointer
819 * @attr: attribute pointer
820 * @buf: char out buffer
821 *
822 * Return: number of the bytes printed into buf or error
823 */
824static ssize_t fw_ver_show(struct device *device,
825 struct device_attribute *attr, char *buf)
826{
827 struct mei_device *dev = dev_get_drvdata(device);
828 struct mei_fw_version *ver;
829 ssize_t cnt = 0;
830 int i;
831
832 ver = dev->fw_ver;
833
834 for (i = 0; i < MEI_MAX_FW_VER_BLOCKS; i++)
835 cnt += scnprintf(buf + cnt, PAGE_SIZE - cnt, "%u:%u.%u.%u.%u\n",
836 ver[i].platform, ver[i].major, ver[i].minor,
837 ver[i].hotfix, ver[i].buildno);
838 return cnt;
839}
840static DEVICE_ATTR_RO(fw_ver);
841
815static struct attribute *mei_attrs[] = { 842static struct attribute *mei_attrs[] = {
816 &dev_attr_fw_status.attr, 843 &dev_attr_fw_status.attr,
817 &dev_attr_hbm_ver.attr, 844 &dev_attr_hbm_ver.attr,
818 &dev_attr_hbm_ver_drv.attr, 845 &dev_attr_hbm_ver_drv.attr,
819 &dev_attr_tx_queue_limit.attr, 846 &dev_attr_tx_queue_limit.attr,
847 &dev_attr_fw_ver.attr,
820 NULL 848 NULL
821}; 849};
822ATTRIBUTE_GROUPS(mei); 850ATTRIBUTE_GROUPS(mei);
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
index 4058ab5ad2d8..d522585b71b7 100644
--- a/drivers/misc/mei/mei_dev.h
+++ b/drivers/misc/mei/mei_dev.h
@@ -1,7 +1,7 @@
1/* 1/*
2 * 2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver 3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation. 4 * Copyright (c) 2003-2018, Intel Corporation.
5 * 5 *
6 * This program is free software; you can redistribute it and/or modify it 6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License, 7 * under the terms and conditions of the GNU General Public License,
@@ -355,6 +355,25 @@ enum mei_pg_state {
355const char *mei_pg_state_str(enum mei_pg_state state); 355const char *mei_pg_state_str(enum mei_pg_state state);
356 356
357/** 357/**
358 * struct mei_fw_version - MEI FW version struct
359 *
360 * @platform: platform identifier
361 * @major: major version field
362 * @minor: minor version field
363 * @buildno: build number version field
364 * @hotfix: hotfix number version field
365 */
366struct mei_fw_version {
367 u8 platform;
368 u8 major;
369 u16 minor;
370 u16 buildno;
371 u16 hotfix;
372};
373
374#define MEI_MAX_FW_VER_BLOCKS 3
375
376/**
358 * struct mei_device - MEI private device struct 377 * struct mei_device - MEI private device struct
359 * 378 *
360 * @dev : device on a bus 379 * @dev : device on a bus
@@ -402,6 +421,8 @@ const char *mei_pg_state_str(enum mei_pg_state state);
402 * @hbm_f_ie_supported : hbm feature immediate reply to enum request 421 * @hbm_f_ie_supported : hbm feature immediate reply to enum request
403 * @hbm_f_os_supported : hbm feature support OS ver message 422 * @hbm_f_os_supported : hbm feature support OS ver message
404 * 423 *
424 * @fw_ver : FW versions
425 *
405 * @me_clients_rwsem: rw lock over me_clients list 426 * @me_clients_rwsem: rw lock over me_clients list
406 * @me_clients : list of FW clients 427 * @me_clients : list of FW clients
407 * @me_clients_map : FW clients bit map 428 * @me_clients_map : FW clients bit map
@@ -478,6 +499,8 @@ struct mei_device {
478 unsigned int hbm_f_ie_supported:1; 499 unsigned int hbm_f_ie_supported:1;
479 unsigned int hbm_f_os_supported:1; 500 unsigned int hbm_f_os_supported:1;
480 501
502 struct mei_fw_version fw_ver[MEI_MAX_FW_VER_BLOCKS];
503
481 struct rw_semaphore me_clients_rwsem; 504 struct rw_semaphore me_clients_rwsem;
482 struct list_head me_clients; 505 struct list_head me_clients;
483 DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX); 506 DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);