diff options
author | Alexander Usyskin <alexander.usyskin@intel.com> | 2018-06-24 17:11:41 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-07-03 07:11:20 -0400 |
commit | 3cfaeb33530592b02b2ceb76b379364c55ca612e (patch) | |
tree | 16b29db30b99b2a233b0817a6f694d6c15bf02b0 | |
parent | 9a7c0b69b6e765c655133ef530876aea3da71d58 (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-mei | 11 | ||||
-rw-r--r-- | drivers/misc/mei/bus-fixup.c | 86 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 30 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 25 |
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 | |||
58 | What: /sys/class/mei/meiN/fw_ver | ||
59 | Date: May 2018 | ||
60 | KernelVersion: 4.18 | ||
61 | Contact: Tomas Winkler <tomas.winkler@intel.com> | ||
62 | Description: 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 | ||
99 | struct mkhi_fw_ver_block { | ||
100 | u16 minor; | ||
101 | u8 major; | ||
102 | u8 platform; | ||
103 | u16 buildno; | ||
104 | u16 hotfix; | ||
105 | } __packed; | ||
106 | |||
107 | struct 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 | ||
101 | struct mkhi_msg_hdr { | 115 | struct 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 */ | ||
161 | static 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 | |||
142 | static void mei_mkhi_fix(struct mei_cl_device *cldev) | 213 | static 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 | } |
813 | static DEVICE_ATTR_RW(tx_queue_limit); | 813 | static 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 | */ | ||
824 | static 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 | } | ||
840 | static DEVICE_ATTR_RO(fw_ver); | ||
841 | |||
815 | static struct attribute *mei_attrs[] = { | 842 | static 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 | }; |
822 | ATTRIBUTE_GROUPS(mei); | 850 | ATTRIBUTE_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 { | |||
355 | const char *mei_pg_state_str(enum mei_pg_state state); | 355 | const 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 | */ | ||
366 | struct 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); |