aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 19:34:21 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-22 19:34:21 -0400
commitfb09bafda67041b74a668dc9d77735e36bd33d3b (patch)
tree2dd32b65062a95045468fdcab366ecdb8e4fcac6 /drivers/misc
parent94b5aff4c6f72fee6b0f49d49e4fa8b204e8ded9 (diff)
parentc3c6cc91b0ae7b3d598488ad0b593bafba4a0817 (diff)
Merge tag 'staging-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging
Pull staging tree changes from Greg Kroah-Hartman: "Here is the big staging tree pull request for the 3.5-rc1 merge window. Loads of changes here, and we just narrowly added more lines than we added: 622 files changed, 28356 insertions(+), 26059 deletions(-) But, good news is that there is a number of subsystems that moved out of the staging tree, to their respective "real" portions of the kernel. Code that moved out was: - iio core code - mei driver - vme core and bridge drivers There was one broken network driver that moved into staging as a step before it is removed from the tree (pc300), and there was a few new drivers added to the tree: - new iio drivers - gdm72xx wimax USB driver - ipack subsystem and 2 drivers All of the movements around have acks from the various subsystem maintainers, and all of this has been in the linux-next tree for a while. Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>" Fixed up various trivial conflicts, along with a non-trivial one found in -next and pointed out by Olof Johanssen: a clean - but incorrect - merge of the arch/arm/boot/dts/at91sam9g20.dtsi file. Fix up manually as per Stephen Rothwell. * tag 'staging-3.5-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/staging: (536 commits) Staging: bcm: Remove two unused variables from Adapter.h Staging: bcm: Removes the volatile type definition from Adapter.h Staging: bcm: Rename all "INT" to "int" in Adapter.h Staging: bcm: Fix warning: __packed vs. __attribute__((packed)) in Adapter.h Staging: bcm: Correctly format all comments in Adapter.h Staging: bcm: Fix all whitespace issues in Adapter.h Staging: bcm: Properly format braces in Adapter.h Staging: ipack/bridges/tpci200: remove unneeded casts Staging: ipack/bridges/tpci200: remove TPCI200_SHORTNAME constant Staging: ipack: remove board_name and bus_name fields from struct ipack_device Staging: ipack: improve the register of a bus and a device in the bus. staging: comedi: cleanup all the comedi_driver 'detach' functions staging: comedi: remove all 'default N' in Kconfig staging: line6/config.h: Delete unused header staging: gdm72xx depends on NET staging: gdm72xx: Set up parent link in sysfs for gdm72xx devices staging: drm/omap: initial dmabuf/prime import support staging: drm/omap: dmabuf/prime mmap support pstore/ram: Add ECC support pstore/ram: Switch to persistent_ram routines ...
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/mei/Kconfig28
-rw-r--r--drivers/misc/mei/Makefile11
-rw-r--r--drivers/misc/mei/hw.h332
-rw-r--r--drivers/misc/mei/init.c735
-rw-r--r--drivers/misc/mei/interface.c428
-rw-r--r--drivers/misc/mei/interface.h75
-rw-r--r--drivers/misc/mei/interrupt.c1590
-rw-r--r--drivers/misc/mei/iorw.c590
-rw-r--r--drivers/misc/mei/main.c1230
-rw-r--r--drivers/misc/mei/mei_dev.h428
-rw-r--r--drivers/misc/mei/wd.c379
13 files changed, 5828 insertions, 0 deletions
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 757fbd0f2a1..2661f6e366f 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -516,4 +516,5 @@ source "drivers/misc/ti-st/Kconfig"
516source "drivers/misc/lis3lv02d/Kconfig" 516source "drivers/misc/lis3lv02d/Kconfig"
517source "drivers/misc/carma/Kconfig" 517source "drivers/misc/carma/Kconfig"
518source "drivers/misc/altera-stapl/Kconfig" 518source "drivers/misc/altera-stapl/Kconfig"
519source "drivers/misc/mei/Kconfig"
519endmenu 520endmenu
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 162861788c6..456972faaeb 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -50,3 +50,4 @@ obj-y += lis3lv02d/
50obj-y += carma/ 50obj-y += carma/
51obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o 51obj-$(CONFIG_USB_SWITCH_FSA9480) += fsa9480.o
52obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/ 52obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
53obj-$(CONFIG_INTEL_MEI) += mei/
diff --git a/drivers/misc/mei/Kconfig b/drivers/misc/mei/Kconfig
new file mode 100644
index 00000000000..47d78a72db2
--- /dev/null
+++ b/drivers/misc/mei/Kconfig
@@ -0,0 +1,28 @@
1config INTEL_MEI
2 tristate "Intel Management Engine Interface (Intel MEI)"
3 depends on X86 && PCI && EXPERIMENTAL && WATCHDOG_CORE
4 help
5 The Intel Management Engine (Intel ME) provides Manageability,
6 Security and Media services for system containing Intel chipsets.
7 if selected /dev/mei misc device will be created.
8
9 Supported Chipsets are:
10 7 Series Chipset Family
11 6 Series Chipset Family
12 5 Series Chipset Family
13 4 Series Chipset Family
14 Mobile 4 Series Chipset Family
15 ICH9
16 82946GZ/GL
17 82G35 Express
18 82Q963/Q965
19 82P965/G965
20 Mobile PM965/GM965
21 Mobile GME965/GLE960
22 82Q35 Express
23 82G33/G31/P35/P31 Express
24 82Q33 Express
25 82X38/X48 Express
26
27 For more information see
28 <http://software.intel.com/en-us/manageability/>
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile
new file mode 100644
index 00000000000..57168db6c7e
--- /dev/null
+++ b/drivers/misc/mei/Makefile
@@ -0,0 +1,11 @@
1#
2# Makefile - Intel Management Engine Interface (Intel MEI) Linux driver
3# Copyright (c) 2010-2011, Intel Corporation.
4#
5obj-$(CONFIG_INTEL_MEI) += mei.o
6mei-objs := init.o
7mei-objs += interrupt.o
8mei-objs += interface.o
9mei-objs += iorw.o
10mei-objs += main.o
11mei-objs += wd.o
diff --git a/drivers/misc/mei/hw.h b/drivers/misc/mei/hw.h
new file mode 100644
index 00000000000..24c4c962819
--- /dev/null
+++ b/drivers/misc/mei/hw.h
@@ -0,0 +1,332 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17#ifndef _MEI_HW_TYPES_H_
18#define _MEI_HW_TYPES_H_
19
20#include <linux/uuid.h>
21
22/*
23 * Timeouts
24 */
25#define MEI_INTEROP_TIMEOUT (HZ * 7)
26#define MEI_CONNECT_TIMEOUT 3 /* at least 2 seconds */
27
28#define CONNECT_TIMEOUT 15 /* HPS definition */
29#define INIT_CLIENTS_TIMEOUT 15 /* HPS definition */
30
31#define IAMTHIF_STALL_TIMER 12 /* seconds */
32#define IAMTHIF_READ_TIMER 10000 /* ms */
33
34/*
35 * Internal Clients Number
36 */
37#define MEI_WD_HOST_CLIENT_ID 1
38#define MEI_IAMTHIF_HOST_CLIENT_ID 2
39
40/*
41 * MEI device IDs
42 */
43#define MEI_DEV_ID_82946GZ 0x2974 /* 82946GZ/GL */
44#define MEI_DEV_ID_82G35 0x2984 /* 82G35 Express */
45#define MEI_DEV_ID_82Q965 0x2994 /* 82Q963/Q965 */
46#define MEI_DEV_ID_82G965 0x29A4 /* 82P965/G965 */
47
48#define MEI_DEV_ID_82GM965 0x2A04 /* Mobile PM965/GM965 */
49#define MEI_DEV_ID_82GME965 0x2A14 /* Mobile GME965/GLE960 */
50
51#define MEI_DEV_ID_ICH9_82Q35 0x29B4 /* 82Q35 Express */
52#define MEI_DEV_ID_ICH9_82G33 0x29C4 /* 82G33/G31/P35/P31 Express */
53#define MEI_DEV_ID_ICH9_82Q33 0x29D4 /* 82Q33 Express */
54#define MEI_DEV_ID_ICH9_82X38 0x29E4 /* 82X38/X48 Express */
55#define MEI_DEV_ID_ICH9_3200 0x29F4 /* 3200/3210 Server */
56
57#define MEI_DEV_ID_ICH9_6 0x28B4 /* Bearlake */
58#define MEI_DEV_ID_ICH9_7 0x28C4 /* Bearlake */
59#define MEI_DEV_ID_ICH9_8 0x28D4 /* Bearlake */
60#define MEI_DEV_ID_ICH9_9 0x28E4 /* Bearlake */
61#define MEI_DEV_ID_ICH9_10 0x28F4 /* Bearlake */
62
63#define MEI_DEV_ID_ICH9M_1 0x2A44 /* Cantiga */
64#define MEI_DEV_ID_ICH9M_2 0x2A54 /* Cantiga */
65#define MEI_DEV_ID_ICH9M_3 0x2A64 /* Cantiga */
66#define MEI_DEV_ID_ICH9M_4 0x2A74 /* Cantiga */
67
68#define MEI_DEV_ID_ICH10_1 0x2E04 /* Eaglelake */
69#define MEI_DEV_ID_ICH10_2 0x2E14 /* Eaglelake */
70#define MEI_DEV_ID_ICH10_3 0x2E24 /* Eaglelake */
71#define MEI_DEV_ID_ICH10_4 0x2E34 /* Eaglelake */
72
73#define MEI_DEV_ID_IBXPK_1 0x3B64 /* Calpella */
74#define MEI_DEV_ID_IBXPK_2 0x3B65 /* Calpella */
75
76#define MEI_DEV_ID_CPT_1 0x1C3A /* Cougerpoint */
77#define MEI_DEV_ID_PBG_1 0x1D3A /* PBG */
78
79#define MEI_DEV_ID_PPT_1 0x1E3A /* Pantherpoint PPT */
80#define MEI_DEV_ID_PPT_2 0x1CBA /* Pantherpoint PPT */
81#define MEI_DEV_ID_PPT_3 0x1DBA /* Pantherpoint PPT */
82
83
84/*
85 * MEI HW Section
86 */
87
88/* MEI registers */
89/* H_CB_WW - Host Circular Buffer (CB) Write Window register */
90#define H_CB_WW 0
91/* H_CSR - Host Control Status register */
92#define H_CSR 4
93/* ME_CB_RW - ME Circular Buffer Read Window register (read only) */
94#define ME_CB_RW 8
95/* ME_CSR_HA - ME Control Status Host Access register (read only) */
96#define ME_CSR_HA 0xC
97
98
99/* register bits of H_CSR (Host Control Status register) */
100/* Host Circular Buffer Depth - maximum number of 32-bit entries in CB */
101#define H_CBD 0xFF000000
102/* Host Circular Buffer Write Pointer */
103#define H_CBWP 0x00FF0000
104/* Host Circular Buffer Read Pointer */
105#define H_CBRP 0x0000FF00
106/* Host Reset */
107#define H_RST 0x00000010
108/* Host Ready */
109#define H_RDY 0x00000008
110/* Host Interrupt Generate */
111#define H_IG 0x00000004
112/* Host Interrupt Status */
113#define H_IS 0x00000002
114/* Host Interrupt Enable */
115#define H_IE 0x00000001
116
117
118/* register bits of ME_CSR_HA (ME Control Status Host Access register) */
119/* ME CB (Circular Buffer) Depth HRA (Host Read Access) - host read only
120access to ME_CBD */
121#define ME_CBD_HRA 0xFF000000
122/* ME CB Write Pointer HRA - host read only access to ME_CBWP */
123#define ME_CBWP_HRA 0x00FF0000
124/* ME CB Read Pointer HRA - host read only access to ME_CBRP */
125#define ME_CBRP_HRA 0x0000FF00
126/* ME Reset HRA - host read only access to ME_RST */
127#define ME_RST_HRA 0x00000010
128/* ME Ready HRA - host read only access to ME_RDY */
129#define ME_RDY_HRA 0x00000008
130/* ME Interrupt Generate HRA - host read only access to ME_IG */
131#define ME_IG_HRA 0x00000004
132/* ME Interrupt Status HRA - host read only access to ME_IS */
133#define ME_IS_HRA 0x00000002
134/* ME Interrupt Enable HRA - host read only access to ME_IE */
135#define ME_IE_HRA 0x00000001
136
137/*
138 * MEI Version
139 */
140#define HBM_MINOR_VERSION 0
141#define HBM_MAJOR_VERSION 1
142#define HBM_TIMEOUT 1 /* 1 second */
143
144/* Host bus message command opcode */
145#define MEI_HBM_CMD_OP_MSK 0x7f
146/* Host bus message command RESPONSE */
147#define MEI_HBM_CMD_RES_MSK 0x80
148
149/*
150 * MEI Bus Message Command IDs
151 */
152#define HOST_START_REQ_CMD 0x01
153#define HOST_START_RES_CMD 0x81
154
155#define HOST_STOP_REQ_CMD 0x02
156#define HOST_STOP_RES_CMD 0x82
157
158#define ME_STOP_REQ_CMD 0x03
159
160#define HOST_ENUM_REQ_CMD 0x04
161#define HOST_ENUM_RES_CMD 0x84
162
163#define HOST_CLIENT_PROPERTIES_REQ_CMD 0x05
164#define HOST_CLIENT_PROPERTIES_RES_CMD 0x85
165
166#define CLIENT_CONNECT_REQ_CMD 0x06
167#define CLIENT_CONNECT_RES_CMD 0x86
168
169#define CLIENT_DISCONNECT_REQ_CMD 0x07
170#define CLIENT_DISCONNECT_RES_CMD 0x87
171
172#define MEI_FLOW_CONTROL_CMD 0x08
173
174/*
175 * MEI Stop Reason
176 * used by hbm_host_stop_request.reason
177 */
178enum mei_stop_reason_types {
179 DRIVER_STOP_REQUEST = 0x00,
180 DEVICE_D1_ENTRY = 0x01,
181 DEVICE_D2_ENTRY = 0x02,
182 DEVICE_D3_ENTRY = 0x03,
183 SYSTEM_S1_ENTRY = 0x04,
184 SYSTEM_S2_ENTRY = 0x05,
185 SYSTEM_S3_ENTRY = 0x06,
186 SYSTEM_S4_ENTRY = 0x07,
187 SYSTEM_S5_ENTRY = 0x08
188};
189
190/*
191 * Client Connect Status
192 * used by hbm_client_connect_response.status
193 */
194enum client_connect_status_types {
195 CCS_SUCCESS = 0x00,
196 CCS_NOT_FOUND = 0x01,
197 CCS_ALREADY_STARTED = 0x02,
198 CCS_OUT_OF_RESOURCES = 0x03,
199 CCS_MESSAGE_SMALL = 0x04
200};
201
202/*
203 * Client Disconnect Status
204 */
205enum client_disconnect_status_types {
206 CDS_SUCCESS = 0x00
207};
208
209/*
210 * MEI BUS Interface Section
211 */
212struct mei_msg_hdr {
213 u32 me_addr:8;
214 u32 host_addr:8;
215 u32 length:9;
216 u32 reserved:6;
217 u32 msg_complete:1;
218} __packed;
219
220
221struct mei_bus_message {
222 u8 hbm_cmd;
223 u8 data[0];
224} __packed;
225
226struct hbm_version {
227 u8 minor_version;
228 u8 major_version;
229} __packed;
230
231struct hbm_host_version_request {
232 u8 hbm_cmd;
233 u8 reserved;
234 struct hbm_version host_version;
235} __packed;
236
237struct hbm_host_version_response {
238 u8 hbm_cmd;
239 u8 host_version_supported;
240 struct hbm_version me_max_version;
241} __packed;
242
243struct hbm_host_stop_request {
244 u8 hbm_cmd;
245 u8 reason;
246 u8 reserved[2];
247} __packed;
248
249struct hbm_host_stop_response {
250 u8 hbm_cmd;
251 u8 reserved[3];
252} __packed;
253
254struct hbm_me_stop_request {
255 u8 hbm_cmd;
256 u8 reason;
257 u8 reserved[2];
258} __packed;
259
260struct hbm_host_enum_request {
261 u8 hbm_cmd;
262 u8 reserved[3];
263} __packed;
264
265struct hbm_host_enum_response {
266 u8 hbm_cmd;
267 u8 reserved[3];
268 u8 valid_addresses[32];
269} __packed;
270
271struct mei_client_properties {
272 uuid_le protocol_name;
273 u8 protocol_version;
274 u8 max_number_of_connections;
275 u8 fixed_address;
276 u8 single_recv_buf;
277 u32 max_msg_length;
278} __packed;
279
280struct hbm_props_request {
281 u8 hbm_cmd;
282 u8 address;
283 u8 reserved[2];
284} __packed;
285
286
287struct hbm_props_response {
288 u8 hbm_cmd;
289 u8 address;
290 u8 status;
291 u8 reserved[1];
292 struct mei_client_properties client_properties;
293} __packed;
294
295struct hbm_client_connect_request {
296 u8 hbm_cmd;
297 u8 me_addr;
298 u8 host_addr;
299 u8 reserved;
300} __packed;
301
302struct hbm_client_connect_response {
303 u8 hbm_cmd;
304 u8 me_addr;
305 u8 host_addr;
306 u8 status;
307} __packed;
308
309struct hbm_client_disconnect_request {
310 u8 hbm_cmd;
311 u8 me_addr;
312 u8 host_addr;
313 u8 reserved[1];
314} __packed;
315
316#define MEI_FC_MESSAGE_RESERVED_LENGTH 5
317
318struct hbm_flow_control {
319 u8 hbm_cmd;
320 u8 me_addr;
321 u8 host_addr;
322 u8 reserved[MEI_FC_MESSAGE_RESERVED_LENGTH];
323} __packed;
324
325struct mei_me_client {
326 struct mei_client_properties props;
327 u8 client_id;
328 u8 mei_flow_ctrl_creds;
329} __packed;
330
331
332#endif
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c
new file mode 100644
index 00000000000..a7d0bb0880e
--- /dev/null
+++ b/drivers/misc/mei/init.c
@@ -0,0 +1,735 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17#include <linux/pci.h>
18#include <linux/sched.h>
19#include <linux/wait.h>
20#include <linux/delay.h>
21
22#include "mei_dev.h"
23#include "hw.h"
24#include "interface.h"
25#include <linux/mei.h>
26
27const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac,
28 0xa8, 0x46, 0xe0, 0xff, 0x65,
29 0x81, 0x4c);
30
31/**
32 * mei_io_list_init - Sets up a queue list.
33 *
34 * @list: An instance io list structure
35 * @dev: the device structure
36 */
37void mei_io_list_init(struct mei_io_list *list)
38{
39 /* initialize our queue list */
40 INIT_LIST_HEAD(&list->mei_cb.cb_list);
41}
42
43/**
44 * mei_io_list_flush - removes list entry belonging to cl.
45 *
46 * @list: An instance of our list structure
47 * @cl: private data of the file object
48 */
49void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl)
50{
51 struct mei_cl_cb *pos;
52 struct mei_cl_cb *next;
53
54 list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) {
55 if (pos->file_private) {
56 struct mei_cl *cl_tmp;
57 cl_tmp = (struct mei_cl *)pos->file_private;
58 if (mei_cl_cmp_id(cl, cl_tmp))
59 list_del(&pos->cb_list);
60 }
61 }
62}
63/**
64 * mei_cl_flush_queues - flushes queue lists belonging to cl.
65 *
66 * @dev: the device structure
67 * @cl: private data of the file object
68 */
69int mei_cl_flush_queues(struct mei_cl *cl)
70{
71 if (!cl || !cl->dev)
72 return -EINVAL;
73
74 dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n");
75 mei_io_list_flush(&cl->dev->read_list, cl);
76 mei_io_list_flush(&cl->dev->write_list, cl);
77 mei_io_list_flush(&cl->dev->write_waiting_list, cl);
78 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl);
79 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl);
80 mei_io_list_flush(&cl->dev->amthi_cmd_list, cl);
81 mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl);
82 return 0;
83}
84
85
86
87/**
88 * mei_reset_iamthif_params - initializes mei device iamthif
89 *
90 * @dev: the device structure
91 */
92static void mei_reset_iamthif_params(struct mei_device *dev)
93{
94 /* reset iamthif parameters. */
95 dev->iamthif_current_cb = NULL;
96 dev->iamthif_msg_buf_size = 0;
97 dev->iamthif_msg_buf_index = 0;
98 dev->iamthif_canceled = false;
99 dev->iamthif_ioctl = false;
100 dev->iamthif_state = MEI_IAMTHIF_IDLE;
101 dev->iamthif_timer = 0;
102}
103
104/**
105 * init_mei_device - allocates and initializes the mei device structure
106 *
107 * @pdev: The pci device structure
108 *
109 * returns The mei_device_device pointer on success, NULL on failure.
110 */
111struct mei_device *mei_device_init(struct pci_dev *pdev)
112{
113 struct mei_device *dev;
114
115 dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL);
116 if (!dev)
117 return NULL;
118
119 /* setup our list array */
120 INIT_LIST_HEAD(&dev->file_list);
121 INIT_LIST_HEAD(&dev->wd_cl.link);
122 INIT_LIST_HEAD(&dev->iamthif_cl.link);
123 mutex_init(&dev->device_lock);
124 init_waitqueue_head(&dev->wait_recvd_msg);
125 init_waitqueue_head(&dev->wait_stop_wd);
126 dev->mei_state = MEI_INITIALIZING;
127 dev->iamthif_state = MEI_IAMTHIF_IDLE;
128 dev->wd_interface_reg = false;
129
130
131 mei_io_list_init(&dev->read_list);
132 mei_io_list_init(&dev->write_list);
133 mei_io_list_init(&dev->write_waiting_list);
134 mei_io_list_init(&dev->ctrl_wr_list);
135 mei_io_list_init(&dev->ctrl_rd_list);
136 mei_io_list_init(&dev->amthi_cmd_list);
137 mei_io_list_init(&dev->amthi_read_complete_list);
138 dev->pdev = pdev;
139 return dev;
140}
141
142/**
143 * mei_hw_init - initializes host and fw to start work.
144 *
145 * @dev: the device structure
146 *
147 * returns 0 on success, <0 on failure.
148 */
149int mei_hw_init(struct mei_device *dev)
150{
151 int err = 0;
152 int ret;
153
154 mutex_lock(&dev->device_lock);
155
156 dev->host_hw_state = mei_hcsr_read(dev);
157 dev->me_hw_state = mei_mecsr_read(dev);
158 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n",
159 dev->host_hw_state, dev->me_hw_state);
160
161 /* acknowledge interrupt and stop interupts */
162 if ((dev->host_hw_state & H_IS) == H_IS)
163 mei_reg_write(dev, H_CSR, dev->host_hw_state);
164
165 dev->recvd_msg = false;
166 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n");
167
168 mei_reset(dev, 1);
169
170 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
171 dev->host_hw_state, dev->me_hw_state);
172
173 /* wait for ME to turn on ME_RDY */
174 if (!dev->recvd_msg) {
175 mutex_unlock(&dev->device_lock);
176 err = wait_event_interruptible_timeout(dev->wait_recvd_msg,
177 dev->recvd_msg, MEI_INTEROP_TIMEOUT);
178 mutex_lock(&dev->device_lock);
179 }
180
181 if (err <= 0 && !dev->recvd_msg) {
182 dev->mei_state = MEI_DISABLED;
183 dev_dbg(&dev->pdev->dev,
184 "wait_event_interruptible_timeout failed"
185 "on wait for ME to turn on ME_RDY.\n");
186 ret = -ENODEV;
187 goto out;
188 }
189
190 if (!(((dev->host_hw_state & H_RDY) == H_RDY) &&
191 ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) {
192 dev->mei_state = MEI_DISABLED;
193 dev_dbg(&dev->pdev->dev,
194 "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
195 dev->host_hw_state, dev->me_hw_state);
196
197 if (!(dev->host_hw_state & H_RDY))
198 dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n");
199
200 if (!(dev->me_hw_state & ME_RDY_HRA))
201 dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n");
202
203 dev_err(&dev->pdev->dev, "link layer initialization failed.\n");
204 ret = -ENODEV;
205 goto out;
206 }
207
208 if (dev->version.major_version != HBM_MAJOR_VERSION ||
209 dev->version.minor_version != HBM_MINOR_VERSION) {
210 dev_dbg(&dev->pdev->dev, "MEI start failed.\n");
211 ret = -ENODEV;
212 goto out;
213 }
214
215 dev->recvd_msg = false;
216 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
217 dev->host_hw_state, dev->me_hw_state);
218 dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n");
219 dev_dbg(&dev->pdev->dev, "link layer has been established.\n");
220 dev_dbg(&dev->pdev->dev, "MEI start success.\n");
221 ret = 0;
222
223out:
224 mutex_unlock(&dev->device_lock);
225 return ret;
226}
227
228/**
229 * mei_hw_reset - resets fw via mei csr register.
230 *
231 * @dev: the device structure
232 * @interrupts_enabled: if interrupt should be enabled after reset.
233 */
234static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled)
235{
236 dev->host_hw_state |= (H_RST | H_IG);
237
238 if (interrupts_enabled)
239 mei_enable_interrupts(dev);
240 else
241 mei_disable_interrupts(dev);
242}
243
244/**
245 * mei_reset - resets host and fw.
246 *
247 * @dev: the device structure
248 * @interrupts_enabled: if interrupt should be enabled after reset.
249 */
250void mei_reset(struct mei_device *dev, int interrupts_enabled)
251{
252 struct mei_cl *cl_pos = NULL;
253 struct mei_cl *cl_next = NULL;
254 struct mei_cl_cb *cb_pos = NULL;
255 struct mei_cl_cb *cb_next = NULL;
256 bool unexpected;
257
258 if (dev->mei_state == MEI_RECOVERING_FROM_RESET) {
259 dev->need_reset = true;
260 return;
261 }
262
263 unexpected = (dev->mei_state != MEI_INITIALIZING &&
264 dev->mei_state != MEI_DISABLED &&
265 dev->mei_state != MEI_POWER_DOWN &&
266 dev->mei_state != MEI_POWER_UP);
267
268 dev->host_hw_state = mei_hcsr_read(dev);
269
270 dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n",
271 dev->host_hw_state);
272
273 mei_hw_reset(dev, interrupts_enabled);
274
275 dev->host_hw_state &= ~H_RST;
276 dev->host_hw_state |= H_IG;
277
278 mei_hcsr_set(dev);
279
280 dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n",
281 dev->host_hw_state);
282
283 dev->need_reset = false;
284
285 if (dev->mei_state != MEI_INITIALIZING) {
286 if (dev->mei_state != MEI_DISABLED &&
287 dev->mei_state != MEI_POWER_DOWN)
288 dev->mei_state = MEI_RESETING;
289
290 list_for_each_entry_safe(cl_pos,
291 cl_next, &dev->file_list, link) {
292 cl_pos->state = MEI_FILE_DISCONNECTED;
293 cl_pos->mei_flow_ctrl_creds = 0;
294 cl_pos->read_cb = NULL;
295 cl_pos->timer_count = 0;
296 }
297 /* remove entry if already in list */
298 dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n");
299 mei_remove_client_from_file_list(dev,
300 dev->wd_cl.host_client_id);
301
302 mei_remove_client_from_file_list(dev,
303 dev->iamthif_cl.host_client_id);
304
305 mei_reset_iamthif_params(dev);
306 dev->wd_due_counter = 0;
307 dev->extra_write_index = 0;
308 }
309
310 dev->me_clients_num = 0;
311 dev->rd_msg_hdr = 0;
312 dev->stop = false;
313 dev->wd_pending = false;
314
315 /* update the state of the registers after reset */
316 dev->host_hw_state = mei_hcsr_read(dev);
317 dev->me_hw_state = mei_mecsr_read(dev);
318
319 dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n",
320 dev->host_hw_state, dev->me_hw_state);
321
322 if (unexpected)
323 dev_warn(&dev->pdev->dev, "unexpected reset.\n");
324
325 /* Wake up all readings so they can be interrupted */
326 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
327 if (waitqueue_active(&cl_pos->rx_wait)) {
328 dev_dbg(&dev->pdev->dev, "Waking up client!\n");
329 wake_up_interruptible(&cl_pos->rx_wait);
330 }
331 }
332 /* remove all waiting requests */
333 list_for_each_entry_safe(cb_pos, cb_next,
334 &dev->write_list.mei_cb.cb_list, cb_list) {
335 list_del(&cb_pos->cb_list);
336 mei_free_cb_private(cb_pos);
337 }
338}
339
340
341
342/**
343 * host_start_message - mei host sends start message.
344 *
345 * @dev: the device structure
346 *
347 * returns none.
348 */
349void mei_host_start_message(struct mei_device *dev)
350{
351 struct mei_msg_hdr *mei_hdr;
352 struct hbm_host_version_request *host_start_req;
353
354 /* host start message */
355 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
356 mei_hdr->host_addr = 0;
357 mei_hdr->me_addr = 0;
358 mei_hdr->length = sizeof(struct hbm_host_version_request);
359 mei_hdr->msg_complete = 1;
360 mei_hdr->reserved = 0;
361
362 host_start_req =
363 (struct hbm_host_version_request *) &dev->wr_msg_buf[1];
364 memset(host_start_req, 0, sizeof(struct hbm_host_version_request));
365 host_start_req->hbm_cmd = HOST_START_REQ_CMD;
366 host_start_req->host_version.major_version = HBM_MAJOR_VERSION;
367 host_start_req->host_version.minor_version = HBM_MINOR_VERSION;
368 dev->recvd_msg = false;
369 if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req,
370 mei_hdr->length)) {
371 dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n");
372 dev->mei_state = MEI_RESETING;
373 mei_reset(dev, 1);
374 }
375 dev->init_clients_state = MEI_START_MESSAGE;
376 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
377 return ;
378}
379
380/**
381 * host_enum_clients_message - host sends enumeration client request message.
382 *
383 * @dev: the device structure
384 *
385 * returns none.
386 */
387void mei_host_enum_clients_message(struct mei_device *dev)
388{
389 struct mei_msg_hdr *mei_hdr;
390 struct hbm_host_enum_request *host_enum_req;
391 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
392 /* enumerate clients */
393 mei_hdr->host_addr = 0;
394 mei_hdr->me_addr = 0;
395 mei_hdr->length = sizeof(struct hbm_host_enum_request);
396 mei_hdr->msg_complete = 1;
397 mei_hdr->reserved = 0;
398
399 host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1];
400 memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request));
401 host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD;
402 if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req,
403 mei_hdr->length)) {
404 dev->mei_state = MEI_RESETING;
405 dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
406 mei_reset(dev, 1);
407 }
408 dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE;
409 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
410 return;
411}
412
413
414/**
415 * allocate_me_clients_storage - allocates storage for me clients
416 *
417 * @dev: the device structure
418 *
419 * returns none.
420 */
421void mei_allocate_me_clients_storage(struct mei_device *dev)
422{
423 struct mei_me_client *clients;
424 int b;
425
426 /* count how many ME clients we have */
427 for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX)
428 dev->me_clients_num++;
429
430 if (dev->me_clients_num <= 0)
431 return ;
432
433
434 if (dev->me_clients != NULL) {
435 kfree(dev->me_clients);
436 dev->me_clients = NULL;
437 }
438 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n",
439 dev->me_clients_num * sizeof(struct mei_me_client));
440 /* allocate storage for ME clients representation */
441 clients = kcalloc(dev->me_clients_num,
442 sizeof(struct mei_me_client), GFP_KERNEL);
443 if (!clients) {
444 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n");
445 dev->mei_state = MEI_RESETING;
446 mei_reset(dev, 1);
447 return ;
448 }
449 dev->me_clients = clients;
450 return ;
451}
452/**
453 * host_client_properties - reads properties for client
454 *
455 * @dev: the device structure
456 *
457 * returns:
458 * < 0 - Error.
459 * = 0 - no more clients.
460 * = 1 - still have clients to send properties request.
461 */
462int mei_host_client_properties(struct mei_device *dev)
463{
464 struct mei_msg_hdr *mei_header;
465 struct hbm_props_request *host_cli_req;
466 int b;
467 u8 client_num = dev->me_client_presentation_num;
468
469 b = dev->me_client_index;
470 b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b);
471 if (b < MEI_CLIENTS_MAX) {
472 dev->me_clients[client_num].client_id = b;
473 dev->me_clients[client_num].mei_flow_ctrl_creds = 0;
474 mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
475 mei_header->host_addr = 0;
476 mei_header->me_addr = 0;
477 mei_header->length = sizeof(struct hbm_props_request);
478 mei_header->msg_complete = 1;
479 mei_header->reserved = 0;
480
481 host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1];
482
483 memset(host_cli_req, 0, sizeof(struct hbm_props_request));
484
485 host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD;
486 host_cli_req->address = b;
487
488 if (mei_write_message(dev, mei_header,
489 (unsigned char *)host_cli_req,
490 mei_header->length)) {
491 dev->mei_state = MEI_RESETING;
492 dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n");
493 mei_reset(dev, 1);
494 return -EIO;
495 }
496
497 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT;
498 dev->me_client_index = b;
499 return 1;
500 }
501
502 return 0;
503}
504
505/**
506 * mei_init_file_private - initializes private file structure.
507 *
508 * @priv: private file structure to be initialized
509 * @file: the file structure
510 */
511void mei_cl_init(struct mei_cl *priv, struct mei_device *dev)
512{
513 memset(priv, 0, sizeof(struct mei_cl));
514 init_waitqueue_head(&priv->wait);
515 init_waitqueue_head(&priv->rx_wait);
516 init_waitqueue_head(&priv->tx_wait);
517 INIT_LIST_HEAD(&priv->link);
518 priv->reading_state = MEI_IDLE;
519 priv->writing_state = MEI_IDLE;
520 priv->dev = dev;
521}
522
523int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid)
524{
525 int i, res = -1;
526
527 for (i = 0; i < dev->me_clients_num; ++i)
528 if (uuid_le_cmp(cuuid,
529 dev->me_clients[i].props.protocol_name) == 0) {
530 res = i;
531 break;
532 }
533
534 return res;
535}
536
537
538/**
539 * mei_find_me_client_update_filext - searches for ME client guid
540 * sets client_id in mei_file_private if found
541 * @dev: the device structure
542 * @priv: private file structure to set client_id in
543 * @cguid: searched guid of ME client
544 * @client_id: id of host client to be set in file private structure
545 *
546 * returns ME client index
547 */
548u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv,
549 const uuid_le *cguid, u8 client_id)
550{
551 int i;
552
553 if (!dev || !priv || !cguid)
554 return 0;
555
556 /* check for valid client id */
557 i = mei_find_me_client_index(dev, *cguid);
558 if (i >= 0) {
559 priv->me_client_id = dev->me_clients[i].client_id;
560 priv->state = MEI_FILE_CONNECTING;
561 priv->host_client_id = client_id;
562
563 list_add_tail(&priv->link, &dev->file_list);
564 return (u8)i;
565 }
566
567 return 0;
568}
569
570/**
571 * host_init_iamthif - mei initialization iamthif client.
572 *
573 * @dev: the device structure
574 *
575 */
576void mei_host_init_iamthif(struct mei_device *dev)
577{
578 u8 i;
579 unsigned char *msg_buf;
580
581 mei_cl_init(&dev->iamthif_cl, dev);
582 dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
583
584 /* find ME amthi client */
585 i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl,
586 &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID);
587 if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) {
588 dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n");
589 return;
590 }
591
592 /* Assign iamthif_mtu to the value received from ME */
593
594 dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length;
595 dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n",
596 dev->me_clients[i].props.max_msg_length);
597
598 kfree(dev->iamthif_msg_buf);
599 dev->iamthif_msg_buf = NULL;
600
601 /* allocate storage for ME message buffer */
602 msg_buf = kcalloc(dev->iamthif_mtu,
603 sizeof(unsigned char), GFP_KERNEL);
604 if (!msg_buf) {
605 dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n");
606 return;
607 }
608
609 dev->iamthif_msg_buf = msg_buf;
610
611 if (mei_connect(dev, &dev->iamthif_cl)) {
612 dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n");
613 dev->iamthif_cl.state = MEI_FILE_DISCONNECTED;
614 dev->iamthif_cl.host_client_id = 0;
615 } else {
616 dev->iamthif_cl.timer_count = CONNECT_TIMEOUT;
617 }
618}
619
620/**
621 * mei_alloc_file_private - allocates a private file structure and sets it up.
622 * @file: the file structure
623 *
624 * returns The allocated file or NULL on failure
625 */
626struct mei_cl *mei_cl_allocate(struct mei_device *dev)
627{
628 struct mei_cl *cl;
629
630 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL);
631 if (!cl)
632 return NULL;
633
634 mei_cl_init(cl, dev);
635
636 return cl;
637}
638
639
640
641/**
642 * mei_disconnect_host_client - sends disconnect message to fw from host client.
643 *
644 * @dev: the device structure
645 * @cl: private data of the file object
646 *
647 * Locking: called under "dev->device_lock" lock
648 *
649 * returns 0 on success, <0 on failure.
650 */
651int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl)
652{
653 int rets, err;
654 long timeout = 15; /* 15 seconds */
655 struct mei_cl_cb *cb;
656
657 if (!dev || !cl)
658 return -ENODEV;
659
660 if (cl->state != MEI_FILE_DISCONNECTING)
661 return 0;
662
663 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
664 if (!cb)
665 return -ENOMEM;
666
667 INIT_LIST_HEAD(&cb->cb_list);
668 cb->file_private = cl;
669 cb->major_file_operations = MEI_CLOSE;
670 if (dev->mei_host_buffer_is_empty) {
671 dev->mei_host_buffer_is_empty = false;
672 if (mei_disconnect(dev, cl)) {
673 rets = -ENODEV;
674 dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n");
675 goto free;
676 }
677 mdelay(10); /* Wait for hardware disconnection ready */
678 list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list);
679 } else {
680 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n");
681 list_add_tail(&cb->cb_list,
682 &dev->ctrl_wr_list.mei_cb.cb_list);
683 }
684 mutex_unlock(&dev->device_lock);
685
686 err = wait_event_timeout(dev->wait_recvd_msg,
687 (MEI_FILE_DISCONNECTED == cl->state),
688 timeout * HZ);
689
690 mutex_lock(&dev->device_lock);
691 if (MEI_FILE_DISCONNECTED == cl->state) {
692 rets = 0;
693 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n");
694 } else {
695 rets = -ENODEV;
696 if (MEI_FILE_DISCONNECTED != cl->state)
697 dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n");
698
699 if (err)
700 dev_dbg(&dev->pdev->dev,
701 "wait failed disconnect err=%08x\n",
702 err);
703
704 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n");
705 }
706
707 mei_io_list_flush(&dev->ctrl_rd_list, cl);
708 mei_io_list_flush(&dev->ctrl_wr_list, cl);
709free:
710 mei_free_cb_private(cb);
711 return rets;
712}
713
714/**
715 * mei_remove_client_from_file_list -
716 * removes file private data from device file list
717 *
718 * @dev: the device structure
719 * @host_client_id: host client id to be removed
720 */
721void mei_remove_client_from_file_list(struct mei_device *dev,
722 u8 host_client_id)
723{
724 struct mei_cl *cl_pos = NULL;
725 struct mei_cl *cl_next = NULL;
726 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
727 if (host_client_id == cl_pos->host_client_id) {
728 dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n",
729 cl_pos->host_client_id,
730 cl_pos->me_client_id);
731 list_del_init(&cl_pos->link);
732 break;
733 }
734 }
735}
diff --git a/drivers/misc/mei/interface.c b/drivers/misc/mei/interface.c
new file mode 100644
index 00000000000..428d21e3641
--- /dev/null
+++ b/drivers/misc/mei/interface.c
@@ -0,0 +1,428 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17#include <linux/pci.h>
18#include "mei_dev.h"
19#include <linux/mei.h>
20#include "interface.h"
21
22
23
24/**
25 * mei_set_csr_register - writes H_CSR register to the mei device,
26 * and ignores the H_IS bit for it is write-one-to-zero.
27 *
28 * @dev: the device structure
29 */
30void mei_hcsr_set(struct mei_device *dev)
31{
32 if ((dev->host_hw_state & H_IS) == H_IS)
33 dev->host_hw_state &= ~H_IS;
34 mei_reg_write(dev, H_CSR, dev->host_hw_state);
35 dev->host_hw_state = mei_hcsr_read(dev);
36}
37
38/**
39 * mei_csr_enable_interrupts - enables mei device interrupts
40 *
41 * @dev: the device structure
42 */
43void mei_enable_interrupts(struct mei_device *dev)
44{
45 dev->host_hw_state |= H_IE;
46 mei_hcsr_set(dev);
47}
48
49/**
50 * mei_csr_disable_interrupts - disables mei device interrupts
51 *
52 * @dev: the device structure
53 */
54void mei_disable_interrupts(struct mei_device *dev)
55{
56 dev->host_hw_state &= ~H_IE;
57 mei_hcsr_set(dev);
58}
59
60/**
61 * _host_get_filled_slots - gets number of device filled buffer slots
62 *
63 * @device: the device structure
64 *
65 * returns number of filled slots
66 */
67static unsigned char _host_get_filled_slots(const struct mei_device *dev)
68{
69 char read_ptr, write_ptr;
70
71 read_ptr = (char) ((dev->host_hw_state & H_CBRP) >> 8);
72 write_ptr = (char) ((dev->host_hw_state & H_CBWP) >> 16);
73
74 return (unsigned char) (write_ptr - read_ptr);
75}
76
77/**
78 * mei_host_buffer_is_empty - checks if host buffer is empty.
79 *
80 * @dev: the device structure
81 *
82 * returns 1 if empty, 0 - otherwise.
83 */
84int mei_host_buffer_is_empty(struct mei_device *dev)
85{
86 unsigned char filled_slots;
87
88 dev->host_hw_state = mei_hcsr_read(dev);
89 filled_slots = _host_get_filled_slots(dev);
90
91 if (filled_slots == 0)
92 return 1;
93
94 return 0;
95}
96
97/**
98 * mei_count_empty_write_slots - counts write empty slots.
99 *
100 * @dev: the device structure
101 *
102 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise empty slots count
103 */
104int mei_count_empty_write_slots(struct mei_device *dev)
105{
106 unsigned char buffer_depth, filled_slots, empty_slots;
107
108 dev->host_hw_state = mei_hcsr_read(dev);
109 buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
110 filled_slots = _host_get_filled_slots(dev);
111 empty_slots = buffer_depth - filled_slots;
112
113 /* check for overflow */
114 if (filled_slots > buffer_depth)
115 return -EOVERFLOW;
116
117 return empty_slots;
118}
119
120/**
121 * mei_write_message - writes a message to mei device.
122 *
123 * @dev: the device structure
124 * @header: header of message
125 * @write_buffer: message buffer will be written
126 * @write_length: message size will be written
127 *
128 * This function returns -EIO if write has failed
129 */
130int mei_write_message(struct mei_device *dev,
131 struct mei_msg_hdr *header,
132 unsigned char *write_buffer,
133 unsigned long write_length)
134{
135 u32 temp_msg = 0;
136 unsigned long bytes_written = 0;
137 unsigned char buffer_depth, filled_slots, empty_slots;
138 unsigned long dw_to_write;
139
140 dev->host_hw_state = mei_hcsr_read(dev);
141
142 dev_dbg(&dev->pdev->dev,
143 "host_hw_state = 0x%08x.\n",
144 dev->host_hw_state);
145
146 dev_dbg(&dev->pdev->dev,
147 "mei_write_message header=%08x.\n",
148 *((u32 *) header));
149
150 buffer_depth = (unsigned char) ((dev->host_hw_state & H_CBD) >> 24);
151 filled_slots = _host_get_filled_slots(dev);
152 empty_slots = buffer_depth - filled_slots;
153 dev_dbg(&dev->pdev->dev,
154 "filled = %hu, empty = %hu.\n",
155 filled_slots, empty_slots);
156
157 dw_to_write = ((write_length + 3) / 4);
158
159 if (dw_to_write > empty_slots)
160 return -EIO;
161
162 mei_reg_write(dev, H_CB_WW, *((u32 *) header));
163
164 while (write_length >= 4) {
165 mei_reg_write(dev, H_CB_WW,
166 *(u32 *) (write_buffer + bytes_written));
167 bytes_written += 4;
168 write_length -= 4;
169 }
170
171 if (write_length > 0) {
172 memcpy(&temp_msg, &write_buffer[bytes_written], write_length);
173 mei_reg_write(dev, H_CB_WW, temp_msg);
174 }
175
176 dev->host_hw_state |= H_IG;
177 mei_hcsr_set(dev);
178 dev->me_hw_state = mei_mecsr_read(dev);
179 if ((dev->me_hw_state & ME_RDY_HRA) != ME_RDY_HRA)
180 return -EIO;
181
182 return 0;
183}
184
185/**
186 * mei_count_full_read_slots - counts read full slots.
187 *
188 * @dev: the device structure
189 *
190 * returns -1(ESLOTS_OVERFLOW) if overflow, otherwise filled slots count
191 */
192int mei_count_full_read_slots(struct mei_device *dev)
193{
194 char read_ptr, write_ptr;
195 unsigned char buffer_depth, filled_slots;
196
197 dev->me_hw_state = mei_mecsr_read(dev);
198 buffer_depth = (unsigned char)((dev->me_hw_state & ME_CBD_HRA) >> 24);
199 read_ptr = (char) ((dev->me_hw_state & ME_CBRP_HRA) >> 8);
200 write_ptr = (char) ((dev->me_hw_state & ME_CBWP_HRA) >> 16);
201 filled_slots = (unsigned char) (write_ptr - read_ptr);
202
203 /* check for overflow */
204 if (filled_slots > buffer_depth)
205 return -EOVERFLOW;
206
207 dev_dbg(&dev->pdev->dev, "filled_slots =%08x\n", filled_slots);
208 return (int)filled_slots;
209}
210
211/**
212 * mei_read_slots - reads a message from mei device.
213 *
214 * @dev: the device structure
215 * @buffer: message buffer will be written
216 * @buffer_length: message size will be read
217 */
218void mei_read_slots(struct mei_device *dev, unsigned char *buffer,
219 unsigned long buffer_length)
220{
221 u32 *reg_buf = (u32 *)buffer;
222
223 for (; buffer_length >= sizeof(u32); buffer_length -= sizeof(u32))
224 *reg_buf++ = mei_mecbrw_read(dev);
225
226 if (buffer_length > 0) {
227 u32 reg = mei_mecbrw_read(dev);
228 memcpy(reg_buf, &reg, buffer_length);
229 }
230
231 dev->host_hw_state |= H_IG;
232 mei_hcsr_set(dev);
233}
234
235/**
236 * mei_flow_ctrl_creds - checks flow_control credentials.
237 *
238 * @dev: the device structure
239 * @cl: private data of the file object
240 *
241 * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise.
242 * -ENOENT if mei_cl is not present
243 * -EINVAL if single_recv_buf == 0
244 */
245int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl)
246{
247 int i;
248
249 if (!dev->me_clients_num)
250 return 0;
251
252 if (cl->mei_flow_ctrl_creds > 0)
253 return 1;
254
255 for (i = 0; i < dev->me_clients_num; i++) {
256 struct mei_me_client *me_cl = &dev->me_clients[i];
257 if (me_cl->client_id == cl->me_client_id) {
258 if (me_cl->mei_flow_ctrl_creds) {
259 if (WARN_ON(me_cl->props.single_recv_buf == 0))
260 return -EINVAL;
261 return 1;
262 } else {
263 return 0;
264 }
265 }
266 }
267 return -ENOENT;
268}
269
270/**
271 * mei_flow_ctrl_reduce - reduces flow_control.
272 *
273 * @dev: the device structure
274 * @cl: private data of the file object
275 * @returns
276 * 0 on success
277 * -ENOENT when me client is not found
278 * -EINVAL when ctrl credits are <= 0
279 */
280int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl)
281{
282 int i;
283
284 if (!dev->me_clients_num)
285 return -ENOENT;
286
287 for (i = 0; i < dev->me_clients_num; i++) {
288 struct mei_me_client *me_cl = &dev->me_clients[i];
289 if (me_cl->client_id == cl->me_client_id) {
290 if (me_cl->props.single_recv_buf != 0) {
291 if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0))
292 return -EINVAL;
293 dev->me_clients[i].mei_flow_ctrl_creds--;
294 } else {
295 if (WARN_ON(cl->mei_flow_ctrl_creds <= 0))
296 return -EINVAL;
297 cl->mei_flow_ctrl_creds--;
298 }
299 return 0;
300 }
301 }
302 return -ENOENT;
303}
304
305/**
306 * mei_send_flow_control - sends flow control to fw.
307 *
308 * @dev: the device structure
309 * @cl: private data of the file object
310 *
311 * This function returns -EIO on write failure
312 */
313int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl)
314{
315 struct mei_msg_hdr *mei_hdr;
316 struct hbm_flow_control *mei_flow_control;
317
318 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
319 mei_hdr->host_addr = 0;
320 mei_hdr->me_addr = 0;
321 mei_hdr->length = sizeof(struct hbm_flow_control);
322 mei_hdr->msg_complete = 1;
323 mei_hdr->reserved = 0;
324
325 mei_flow_control = (struct hbm_flow_control *) &dev->wr_msg_buf[1];
326 memset(mei_flow_control, 0, sizeof(*mei_flow_control));
327 mei_flow_control->host_addr = cl->host_client_id;
328 mei_flow_control->me_addr = cl->me_client_id;
329 mei_flow_control->hbm_cmd = MEI_FLOW_CONTROL_CMD;
330 memset(mei_flow_control->reserved, 0,
331 sizeof(mei_flow_control->reserved));
332 dev_dbg(&dev->pdev->dev, "sending flow control host client = %d, ME client = %d\n",
333 cl->host_client_id, cl->me_client_id);
334
335 return mei_write_message(dev, mei_hdr,
336 (unsigned char *) mei_flow_control,
337 sizeof(struct hbm_flow_control));
338}
339
340/**
341 * mei_other_client_is_connecting - checks if other
342 * client with the same client id is connected.
343 *
344 * @dev: the device structure
345 * @cl: private data of the file object
346 *
347 * returns 1 if other client is connected, 0 - otherwise.
348 */
349int mei_other_client_is_connecting(struct mei_device *dev,
350 struct mei_cl *cl)
351{
352 struct mei_cl *cl_pos = NULL;
353 struct mei_cl *cl_next = NULL;
354
355 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
356 if ((cl_pos->state == MEI_FILE_CONNECTING) &&
357 (cl_pos != cl) &&
358 cl->me_client_id == cl_pos->me_client_id)
359 return 1;
360
361 }
362 return 0;
363}
364
365/**
366 * mei_disconnect - sends disconnect message to fw.
367 *
368 * @dev: the device structure
369 * @cl: private data of the file object
370 *
371 * This function returns -EIO on write failure
372 */
373int mei_disconnect(struct mei_device *dev, struct mei_cl *cl)
374{
375 struct mei_msg_hdr *mei_hdr;
376 struct hbm_client_disconnect_request *mei_cli_disconnect;
377
378 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
379 mei_hdr->host_addr = 0;
380 mei_hdr->me_addr = 0;
381 mei_hdr->length = sizeof(struct hbm_client_disconnect_request);
382 mei_hdr->msg_complete = 1;
383 mei_hdr->reserved = 0;
384
385 mei_cli_disconnect =
386 (struct hbm_client_disconnect_request *) &dev->wr_msg_buf[1];
387 memset(mei_cli_disconnect, 0, sizeof(*mei_cli_disconnect));
388 mei_cli_disconnect->host_addr = cl->host_client_id;
389 mei_cli_disconnect->me_addr = cl->me_client_id;
390 mei_cli_disconnect->hbm_cmd = CLIENT_DISCONNECT_REQ_CMD;
391 mei_cli_disconnect->reserved[0] = 0;
392
393 return mei_write_message(dev, mei_hdr,
394 (unsigned char *) mei_cli_disconnect,
395 sizeof(struct hbm_client_disconnect_request));
396}
397
398/**
399 * mei_connect - sends connect message to fw.
400 *
401 * @dev: the device structure
402 * @cl: private data of the file object
403 *
404 * This function returns -EIO on write failure
405 */
406int mei_connect(struct mei_device *dev, struct mei_cl *cl)
407{
408 struct mei_msg_hdr *mei_hdr;
409 struct hbm_client_connect_request *mei_cli_connect;
410
411 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
412 mei_hdr->host_addr = 0;
413 mei_hdr->me_addr = 0;
414 mei_hdr->length = sizeof(struct hbm_client_connect_request);
415 mei_hdr->msg_complete = 1;
416 mei_hdr->reserved = 0;
417
418 mei_cli_connect =
419 (struct hbm_client_connect_request *) &dev->wr_msg_buf[1];
420 mei_cli_connect->host_addr = cl->host_client_id;
421 mei_cli_connect->me_addr = cl->me_client_id;
422 mei_cli_connect->hbm_cmd = CLIENT_CONNECT_REQ_CMD;
423 mei_cli_connect->reserved = 0;
424
425 return mei_write_message(dev, mei_hdr,
426 (unsigned char *) mei_cli_connect,
427 sizeof(struct hbm_client_connect_request));
428}
diff --git a/drivers/misc/mei/interface.h b/drivers/misc/mei/interface.h
new file mode 100644
index 00000000000..ddff5d16616
--- /dev/null
+++ b/drivers/misc/mei/interface.h
@@ -0,0 +1,75 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17
18
19#ifndef _MEI_INTERFACE_H_
20#define _MEI_INTERFACE_H_
21
22#include <linux/mei.h>
23#include "mei_dev.h"
24
25
26#define AMT_WD_DEFAULT_TIMEOUT 120 /* seconds */
27#define AMT_WD_MIN_TIMEOUT 120 /* seconds */
28#define AMT_WD_MAX_TIMEOUT 65535 /* seconds */
29
30#define MEI_WATCHDOG_DATA_SIZE 16
31#define MEI_START_WD_DATA_SIZE 20
32#define MEI_WD_PARAMS_SIZE 4
33
34
35void mei_read_slots(struct mei_device *dev,
36 unsigned char *buffer,
37 unsigned long buffer_length);
38
39int mei_write_message(struct mei_device *dev,
40 struct mei_msg_hdr *header,
41 unsigned char *write_buffer,
42 unsigned long write_length);
43
44int mei_host_buffer_is_empty(struct mei_device *dev);
45
46int mei_count_full_read_slots(struct mei_device *dev);
47
48int mei_count_empty_write_slots(struct mei_device *dev);
49
50int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl);
51
52int mei_wd_send(struct mei_device *dev);
53int mei_wd_stop(struct mei_device *dev, bool preserve);
54int mei_wd_host_init(struct mei_device *dev);
55/*
56 * mei_watchdog_register - Registering watchdog interface
57 * once we got connection to the WD Client
58 * @dev - mei device
59 */
60void mei_watchdog_register(struct mei_device *dev);
61/*
62 * mei_watchdog_unregister - Unregistering watchdog interface
63 * @dev - mei device
64 */
65void mei_watchdog_unregister(struct mei_device *dev);
66
67int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl);
68
69int mei_send_flow_control(struct mei_device *dev, struct mei_cl *cl);
70
71int mei_disconnect(struct mei_device *dev, struct mei_cl *cl);
72int mei_other_client_is_connecting(struct mei_device *dev, struct mei_cl *cl);
73int mei_connect(struct mei_device *dev, struct mei_cl *cl);
74
75#endif /* _MEI_INTERFACE_H_ */
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c
new file mode 100644
index 00000000000..93936f1b75e
--- /dev/null
+++ b/drivers/misc/mei/interrupt.c
@@ -0,0 +1,1590 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17
18#include <linux/pci.h>
19#include <linux/kthread.h>
20#include <linux/interrupt.h>
21#include <linux/fs.h>
22#include <linux/jiffies.h>
23
24#include "mei_dev.h"
25#include <linux/mei.h>
26#include "hw.h"
27#include "interface.h"
28
29
30/**
31 * mei_interrupt_quick_handler - The ISR of the MEI device
32 *
33 * @irq: The irq number
34 * @dev_id: pointer to the device structure
35 *
36 * returns irqreturn_t
37 */
38irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id)
39{
40 struct mei_device *dev = (struct mei_device *) dev_id;
41 u32 csr_reg = mei_hcsr_read(dev);
42
43 if ((csr_reg & H_IS) != H_IS)
44 return IRQ_NONE;
45
46 /* clear H_IS bit in H_CSR */
47 mei_reg_write(dev, H_CSR, csr_reg);
48
49 return IRQ_WAKE_THREAD;
50}
51
52/**
53 * _mei_cmpl - processes completed operation.
54 *
55 * @cl: private data of the file object.
56 * @cb_pos: callback block.
57 */
58static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
59{
60 if (cb_pos->major_file_operations == MEI_WRITE) {
61 mei_free_cb_private(cb_pos);
62 cb_pos = NULL;
63 cl->writing_state = MEI_WRITE_COMPLETE;
64 if (waitqueue_active(&cl->tx_wait))
65 wake_up_interruptible(&cl->tx_wait);
66
67 } else if (cb_pos->major_file_operations == MEI_READ &&
68 MEI_READING == cl->reading_state) {
69 cl->reading_state = MEI_READ_COMPLETE;
70 if (waitqueue_active(&cl->rx_wait))
71 wake_up_interruptible(&cl->rx_wait);
72
73 }
74}
75
76/**
77 * _mei_cmpl_iamthif - processes completed iamthif operation.
78 *
79 * @dev: the device structure.
80 * @cb_pos: callback block.
81 */
82static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos)
83{
84 if (dev->iamthif_canceled != 1) {
85 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE;
86 dev->iamthif_stall_timer = 0;
87 memcpy(cb_pos->response_buffer.data,
88 dev->iamthif_msg_buf,
89 dev->iamthif_msg_buf_index);
90 list_add_tail(&cb_pos->cb_list,
91 &dev->amthi_read_complete_list.mei_cb.cb_list);
92 dev_dbg(&dev->pdev->dev, "amthi read completed.\n");
93 dev->iamthif_timer = jiffies;
94 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
95 dev->iamthif_timer);
96 } else {
97 mei_run_next_iamthif_cmd(dev);
98 }
99
100 dev_dbg(&dev->pdev->dev, "completing amthi call back.\n");
101 wake_up_interruptible(&dev->iamthif_cl.wait);
102}
103
104
105/**
106 * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to
107 * handle the read amthi message data processing.
108 *
109 * @complete_list: An instance of our list structure
110 * @dev: the device structure
111 * @mei_hdr: header of amthi message
112 *
113 * returns 0 on success, <0 on failure.
114 */
115static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list,
116 struct mei_device *dev,
117 struct mei_msg_hdr *mei_hdr)
118{
119 struct mei_cl *cl;
120 struct mei_cl_cb *cb;
121 unsigned char *buffer;
122
123 BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id);
124 BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING);
125
126 buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index;
127 BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length);
128
129 mei_read_slots(dev, buffer, mei_hdr->length);
130
131 dev->iamthif_msg_buf_index += mei_hdr->length;
132
133 if (!mei_hdr->msg_complete)
134 return 0;
135
136 dev_dbg(&dev->pdev->dev,
137 "amthi_message_buffer_index =%d\n",
138 mei_hdr->length);
139
140 dev_dbg(&dev->pdev->dev, "completed amthi read.\n ");
141 if (!dev->iamthif_current_cb)
142 return -ENODEV;
143
144 cb = dev->iamthif_current_cb;
145 dev->iamthif_current_cb = NULL;
146
147 cl = (struct mei_cl *)cb->file_private;
148 if (!cl)
149 return -ENODEV;
150
151 dev->iamthif_stall_timer = 0;
152 cb->information = dev->iamthif_msg_buf_index;
153 cb->read_time = jiffies;
154 if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) {
155 /* found the iamthif cb */
156 dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n ");
157 dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n ");
158 list_add_tail(&cb->cb_list,
159 &complete_list->mei_cb.cb_list);
160 }
161 return 0;
162}
163
164/**
165 * _mei_irq_thread_state_ok - checks if mei header matches file private data
166 *
167 * @cl: private data of the file object
168 * @mei_hdr: header of mei client message
169 *
170 * returns !=0 if matches, 0 if no match.
171 */
172static int _mei_irq_thread_state_ok(struct mei_cl *cl,
173 struct mei_msg_hdr *mei_hdr)
174{
175 return (cl->host_client_id == mei_hdr->host_addr &&
176 cl->me_client_id == mei_hdr->me_addr &&
177 cl->state == MEI_FILE_CONNECTED &&
178 MEI_READ_COMPLETE != cl->reading_state);
179}
180
181/**
182 * mei_irq_thread_read_client_message - bottom half read routine after ISR to
183 * handle the read mei client message data processing.
184 *
185 * @complete_list: An instance of our list structure
186 * @dev: the device structure
187 * @mei_hdr: header of mei client message
188 *
189 * returns 0 on success, <0 on failure.
190 */
191static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list,
192 struct mei_device *dev,
193 struct mei_msg_hdr *mei_hdr)
194{
195 struct mei_cl *cl;
196 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
197 unsigned char *buffer = NULL;
198
199 dev_dbg(&dev->pdev->dev, "start client msg\n");
200 if (list_empty(&dev->read_list.mei_cb.cb_list))
201 goto quit;
202
203 list_for_each_entry_safe(cb_pos, cb_next,
204 &dev->read_list.mei_cb.cb_list, cb_list) {
205 cl = (struct mei_cl *)cb_pos->file_private;
206 if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) {
207 cl->reading_state = MEI_READING;
208 buffer = cb_pos->response_buffer.data + cb_pos->information;
209
210 if (cb_pos->response_buffer.size <
211 mei_hdr->length + cb_pos->information) {
212 dev_dbg(&dev->pdev->dev, "message overflow.\n");
213 list_del(&cb_pos->cb_list);
214 return -ENOMEM;
215 }
216 if (buffer)
217 mei_read_slots(dev, buffer, mei_hdr->length);
218
219 cb_pos->information += mei_hdr->length;
220 if (mei_hdr->msg_complete) {
221 cl->status = 0;
222 list_del(&cb_pos->cb_list);
223 dev_dbg(&dev->pdev->dev,
224 "completed read host client = %d,"
225 "ME client = %d, "
226 "data length = %lu\n",
227 cl->host_client_id,
228 cl->me_client_id,
229 cb_pos->information);
230
231 *(cb_pos->response_buffer.data +
232 cb_pos->information) = '\0';
233 dev_dbg(&dev->pdev->dev, "cb_pos->res_buffer - %s\n",
234 cb_pos->response_buffer.data);
235 list_add_tail(&cb_pos->cb_list,
236 &complete_list->mei_cb.cb_list);
237 }
238
239 break;
240 }
241
242 }
243
244quit:
245 dev_dbg(&dev->pdev->dev, "message read\n");
246 if (!buffer) {
247 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
248 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n",
249 *(u32 *) dev->rd_msg_buf);
250 }
251
252 return 0;
253}
254
255/**
256 * _mei_irq_thread_iamthif_read - prepares to read iamthif data.
257 *
258 * @dev: the device structure.
259 * @slots: free slots.
260 *
261 * returns 0, OK; otherwise, error.
262 */
263static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots)
264{
265
266 if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr)
267 + sizeof(struct hbm_flow_control))) {
268 return -EMSGSIZE;
269 }
270 *slots -= (sizeof(struct mei_msg_hdr) +
271 sizeof(struct hbm_flow_control) + 3) / 4;
272 if (mei_send_flow_control(dev, &dev->iamthif_cl)) {
273 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n");
274 return -EIO;
275 }
276
277 dev_dbg(&dev->pdev->dev, "iamthif flow control success\n");
278 dev->iamthif_state = MEI_IAMTHIF_READING;
279 dev->iamthif_flow_control_pending = false;
280 dev->iamthif_msg_buf_index = 0;
281 dev->iamthif_msg_buf_size = 0;
282 dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER;
283 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
284 return 0;
285}
286
287/**
288 * _mei_irq_thread_close - processes close related operation.
289 *
290 * @dev: the device structure.
291 * @slots: free slots.
292 * @cb_pos: callback block.
293 * @cl: private data of the file object.
294 * @cmpl_list: complete list.
295 *
296 * returns 0, OK; otherwise, error.
297 */
298static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots,
299 struct mei_cl_cb *cb_pos,
300 struct mei_cl *cl,
301 struct mei_io_list *cmpl_list)
302{
303 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
304 sizeof(struct hbm_client_disconnect_request))) {
305 *slots -= (sizeof(struct mei_msg_hdr) +
306 sizeof(struct hbm_client_disconnect_request) + 3) / 4;
307
308 if (mei_disconnect(dev, cl)) {
309 cl->status = 0;
310 cb_pos->information = 0;
311 list_move_tail(&cb_pos->cb_list,
312 &cmpl_list->mei_cb.cb_list);
313 return -EMSGSIZE;
314 } else {
315 cl->state = MEI_FILE_DISCONNECTING;
316 cl->status = 0;
317 cb_pos->information = 0;
318 list_move_tail(&cb_pos->cb_list,
319 &dev->ctrl_rd_list.mei_cb.cb_list);
320 cl->timer_count = MEI_CONNECT_TIMEOUT;
321 }
322 } else {
323 /* return the cancel routine */
324 return -EBADMSG;
325 }
326
327 return 0;
328}
329
330/**
331 * is_treat_specially_client - checks if the message belongs
332 * to the file private data.
333 *
334 * @cl: private data of the file object
335 * @rs: connect response bus message
336 *
337 */
338static bool is_treat_specially_client(struct mei_cl *cl,
339 struct hbm_client_connect_response *rs)
340{
341
342 if (cl->host_client_id == rs->host_addr &&
343 cl->me_client_id == rs->me_addr) {
344 if (!rs->status) {
345 cl->state = MEI_FILE_CONNECTED;
346 cl->status = 0;
347
348 } else {
349 cl->state = MEI_FILE_DISCONNECTED;
350 cl->status = -ENODEV;
351 }
352 cl->timer_count = 0;
353
354 return true;
355 }
356 return false;
357}
358
359/**
360 * mei_client_connect_response - connects to response irq routine
361 *
362 * @dev: the device structure
363 * @rs: connect response bus message
364 */
365static void mei_client_connect_response(struct mei_device *dev,
366 struct hbm_client_connect_response *rs)
367{
368
369 struct mei_cl *cl;
370 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
371
372 dev_dbg(&dev->pdev->dev,
373 "connect_response:\n"
374 "ME Client = %d\n"
375 "Host Client = %d\n"
376 "Status = %d\n",
377 rs->me_addr,
378 rs->host_addr,
379 rs->status);
380
381 /* if WD or iamthif client treat specially */
382
383 if (is_treat_specially_client(&(dev->wd_cl), rs)) {
384 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
385 mei_watchdog_register(dev);
386
387 /* next step in the state maching */
388 mei_host_init_iamthif(dev);
389 return;
390 }
391
392 if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
393 dev->iamthif_state = MEI_IAMTHIF_IDLE;
394 return;
395 }
396 list_for_each_entry_safe(cb_pos, cb_next,
397 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
398
399 cl = (struct mei_cl *)cb_pos->file_private;
400 if (!cl) {
401 list_del(&cb_pos->cb_list);
402 return;
403 }
404 if (MEI_IOCTL == cb_pos->major_file_operations) {
405 if (is_treat_specially_client(cl, rs)) {
406 list_del(&cb_pos->cb_list);
407 cl->status = 0;
408 cl->timer_count = 0;
409 break;
410 }
411 }
412 }
413}
414
415/**
416 * mei_client_disconnect_response - disconnects from response irq routine
417 *
418 * @dev: the device structure
419 * @rs: disconnect response bus message
420 */
421static void mei_client_disconnect_response(struct mei_device *dev,
422 struct hbm_client_connect_response *rs)
423{
424 struct mei_cl *cl;
425 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
426
427 dev_dbg(&dev->pdev->dev,
428 "disconnect_response:\n"
429 "ME Client = %d\n"
430 "Host Client = %d\n"
431 "Status = %d\n",
432 rs->me_addr,
433 rs->host_addr,
434 rs->status);
435
436 list_for_each_entry_safe(cb_pos, cb_next,
437 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) {
438 cl = (struct mei_cl *)cb_pos->file_private;
439
440 if (!cl) {
441 list_del(&cb_pos->cb_list);
442 return;
443 }
444
445 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
446 if (cl->host_client_id == rs->host_addr &&
447 cl->me_client_id == rs->me_addr) {
448
449 list_del(&cb_pos->cb_list);
450 if (!rs->status)
451 cl->state = MEI_FILE_DISCONNECTED;
452
453 cl->status = 0;
454 cl->timer_count = 0;
455 break;
456 }
457 }
458}
459
460/**
461 * same_flow_addr - tells if they have the same address.
462 *
463 * @file: private data of the file object.
464 * @flow: flow control.
465 *
466 * returns !=0, same; 0,not.
467 */
468static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
469{
470 return (cl->host_client_id == flow->host_addr &&
471 cl->me_client_id == flow->me_addr);
472}
473
474/**
475 * add_single_flow_creds - adds single buffer credentials.
476 *
477 * @file: private data ot the file object.
478 * @flow: flow control.
479 */
480static void add_single_flow_creds(struct mei_device *dev,
481 struct hbm_flow_control *flow)
482{
483 struct mei_me_client *client;
484 int i;
485
486 for (i = 0; i < dev->me_clients_num; i++) {
487 client = &dev->me_clients[i];
488 if (client && flow->me_addr == client->client_id) {
489 if (client->props.single_recv_buf) {
490 client->mei_flow_ctrl_creds++;
491 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
492 flow->me_addr);
493 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
494 client->mei_flow_ctrl_creds);
495 } else {
496 BUG(); /* error in flow control */
497 }
498 }
499 }
500}
501
502/**
503 * mei_client_flow_control_response - flow control response irq routine
504 *
505 * @dev: the device structure
506 * @flow_control: flow control response bus message
507 */
508static void mei_client_flow_control_response(struct mei_device *dev,
509 struct hbm_flow_control *flow_control)
510{
511 struct mei_cl *cl_pos = NULL;
512 struct mei_cl *cl_next = NULL;
513
514 if (!flow_control->host_addr) {
515 /* single receive buffer */
516 add_single_flow_creds(dev, flow_control);
517 } else {
518 /* normal connection */
519 list_for_each_entry_safe(cl_pos, cl_next,
520 &dev->file_list, link) {
521 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
522
523 dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
524 cl_pos->host_client_id,
525 cl_pos->me_client_id);
526 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
527 flow_control->host_addr,
528 flow_control->me_addr);
529 if (same_flow_addr(cl_pos, flow_control)) {
530 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n",
531 flow_control->host_addr,
532 flow_control->me_addr);
533 cl_pos->mei_flow_ctrl_creds++;
534 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
535 cl_pos->mei_flow_ctrl_creds);
536 break;
537 }
538 }
539 }
540}
541
542/**
543 * same_disconn_addr - tells if they have the same address
544 *
545 * @file: private data of the file object.
546 * @disconn: disconnection request.
547 *
548 * returns !=0, same; 0,not.
549 */
550static int same_disconn_addr(struct mei_cl *cl,
551 struct hbm_client_disconnect_request *disconn)
552{
553 return (cl->host_client_id == disconn->host_addr &&
554 cl->me_client_id == disconn->me_addr);
555}
556
557/**
558 * mei_client_disconnect_request - disconnects from request irq routine
559 *
560 * @dev: the device structure.
561 * @disconnect_req: disconnect request bus message.
562 */
563static void mei_client_disconnect_request(struct mei_device *dev,
564 struct hbm_client_disconnect_request *disconnect_req)
565{
566 struct mei_msg_hdr *mei_hdr;
567 struct hbm_client_connect_response *disconnect_res;
568 struct mei_cl *cl_pos = NULL;
569 struct mei_cl *cl_next = NULL;
570
571 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
572 if (same_disconn_addr(cl_pos, disconnect_req)) {
573 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
574 disconnect_req->host_addr,
575 disconnect_req->me_addr);
576 cl_pos->state = MEI_FILE_DISCONNECTED;
577 cl_pos->timer_count = 0;
578 if (cl_pos == &dev->wd_cl) {
579 dev->wd_due_counter = 0;
580 dev->wd_pending = false;
581 } else if (cl_pos == &dev->iamthif_cl)
582 dev->iamthif_timer = 0;
583
584 /* prepare disconnect response */
585 mei_hdr =
586 (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
587 mei_hdr->host_addr = 0;
588 mei_hdr->me_addr = 0;
589 mei_hdr->length =
590 sizeof(struct hbm_client_connect_response);
591 mei_hdr->msg_complete = 1;
592 mei_hdr->reserved = 0;
593
594 disconnect_res =
595 (struct hbm_client_connect_response *)
596 &dev->ext_msg_buf[1];
597 disconnect_res->host_addr = cl_pos->host_client_id;
598 disconnect_res->me_addr = cl_pos->me_client_id;
599 disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
600 disconnect_res->status = 0;
601 dev->extra_write_index = 2;
602 break;
603 }
604 }
605}
606
607
608/**
609 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
610 * handle the read bus message cmd processing.
611 *
612 * @dev: the device structure
613 * @mei_hdr: header of bus message
614 */
615static void mei_irq_thread_read_bus_message(struct mei_device *dev,
616 struct mei_msg_hdr *mei_hdr)
617{
618 struct mei_bus_message *mei_msg;
619 struct hbm_host_version_response *version_res;
620 struct hbm_client_connect_response *connect_res;
621 struct hbm_client_connect_response *disconnect_res;
622 struct hbm_flow_control *flow_control;
623 struct hbm_props_response *props_res;
624 struct hbm_host_enum_response *enum_res;
625 struct hbm_client_disconnect_request *disconnect_req;
626 struct hbm_host_stop_request *host_stop_req;
627 int res;
628
629
630 /* read the message to our buffer */
631 BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
632 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
633 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
634
635 switch (mei_msg->hbm_cmd) {
636 case HOST_START_RES_CMD:
637 version_res = (struct hbm_host_version_response *) mei_msg;
638 if (version_res->host_version_supported) {
639 dev->version.major_version = HBM_MAJOR_VERSION;
640 dev->version.minor_version = HBM_MINOR_VERSION;
641 if (dev->mei_state == MEI_INIT_CLIENTS &&
642 dev->init_clients_state == MEI_START_MESSAGE) {
643 dev->init_clients_timer = 0;
644 mei_host_enum_clients_message(dev);
645 } else {
646 dev->recvd_msg = false;
647 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
648 mei_reset(dev, 1);
649 return;
650 }
651 } else {
652 dev->version = version_res->me_max_version;
653 /* send stop message */
654 mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
655 mei_hdr->host_addr = 0;
656 mei_hdr->me_addr = 0;
657 mei_hdr->length = sizeof(struct hbm_host_stop_request);
658 mei_hdr->msg_complete = 1;
659 mei_hdr->reserved = 0;
660
661 host_stop_req = (struct hbm_host_stop_request *)
662 &dev->wr_msg_buf[1];
663
664 memset(host_stop_req,
665 0,
666 sizeof(struct hbm_host_stop_request));
667 host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
668 host_stop_req->reason = DRIVER_STOP_REQUEST;
669 mei_write_message(dev, mei_hdr,
670 (unsigned char *) (host_stop_req),
671 mei_hdr->length);
672 dev_dbg(&dev->pdev->dev, "version mismatch.\n");
673 return;
674 }
675
676 dev->recvd_msg = true;
677 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
678 break;
679
680 case CLIENT_CONNECT_RES_CMD:
681 connect_res =
682 (struct hbm_client_connect_response *) mei_msg;
683 mei_client_connect_response(dev, connect_res);
684 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
685 wake_up(&dev->wait_recvd_msg);
686 break;
687
688 case CLIENT_DISCONNECT_RES_CMD:
689 disconnect_res =
690 (struct hbm_client_connect_response *) mei_msg;
691 mei_client_disconnect_response(dev, disconnect_res);
692 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
693 wake_up(&dev->wait_recvd_msg);
694 break;
695
696 case MEI_FLOW_CONTROL_CMD:
697 flow_control = (struct hbm_flow_control *) mei_msg;
698 mei_client_flow_control_response(dev, flow_control);
699 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
700 break;
701
702 case HOST_CLIENT_PROPERTIES_RES_CMD:
703 props_res = (struct hbm_props_response *)mei_msg;
704 if (props_res->status || !dev->me_clients) {
705 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
706 mei_reset(dev, 1);
707 return;
708 }
709 if (dev->me_clients[dev->me_client_presentation_num]
710 .client_id == props_res->address) {
711
712 dev->me_clients[dev->me_client_presentation_num].props
713 = props_res->client_properties;
714
715 if (dev->mei_state == MEI_INIT_CLIENTS &&
716 dev->init_clients_state ==
717 MEI_CLIENT_PROPERTIES_MESSAGE) {
718 dev->me_client_index++;
719 dev->me_client_presentation_num++;
720
721 /** Send Client Properties request **/
722 res = mei_host_client_properties(dev);
723 if (res < 0) {
724 dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed");
725 return;
726 } else if (!res) {
727 /*
728 * No more clients to send to.
729 * Clear Map for indicating now ME clients
730 * with associated host client
731 */
732 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX);
733 dev->open_handle_count = 0;
734
735 /*
736 * Reserving the first three client IDs
737 * Client Id 0 - Reserved for MEI Bus Message communications
738 * Client Id 1 - Reserved for Watchdog
739 * Client ID 2 - Reserved for AMTHI
740 */
741 bitmap_set(dev->host_clients_map, 0, 3);
742 dev->mei_state = MEI_ENABLED;
743
744 /* if wd initialization fails, initialization the AMTHI client,
745 * otherwise the AMTHI client will be initialized after the WD client connect response
746 * will be received
747 */
748 if (mei_wd_host_init(dev))
749 mei_host_init_iamthif(dev);
750 }
751
752 } else {
753 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message");
754 mei_reset(dev, 1);
755 return;
756 }
757 } else {
758 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n");
759 mei_reset(dev, 1);
760 return;
761 }
762 break;
763
764 case HOST_ENUM_RES_CMD:
765 enum_res = (struct hbm_host_enum_response *) mei_msg;
766 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
767 if (dev->mei_state == MEI_INIT_CLIENTS &&
768 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
769 dev->init_clients_timer = 0;
770 dev->me_client_presentation_num = 0;
771 dev->me_client_index = 0;
772 mei_allocate_me_clients_storage(dev);
773 dev->init_clients_state =
774 MEI_CLIENT_PROPERTIES_MESSAGE;
775 mei_host_client_properties(dev);
776 } else {
777 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
778 mei_reset(dev, 1);
779 return;
780 }
781 break;
782
783 case HOST_STOP_RES_CMD:
784 dev->mei_state = MEI_DISABLED;
785 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
786 mei_reset(dev, 1);
787 break;
788
789 case CLIENT_DISCONNECT_REQ_CMD:
790 /* search for client */
791 disconnect_req =
792 (struct hbm_client_disconnect_request *) mei_msg;
793 mei_client_disconnect_request(dev, disconnect_req);
794 break;
795
796 case ME_STOP_REQ_CMD:
797 /* prepare stop request */
798 mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0];
799 mei_hdr->host_addr = 0;
800 mei_hdr->me_addr = 0;
801 mei_hdr->length = sizeof(struct hbm_host_stop_request);
802 mei_hdr->msg_complete = 1;
803 mei_hdr->reserved = 0;
804 host_stop_req =
805 (struct hbm_host_stop_request *) &dev->ext_msg_buf[1];
806 memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request));
807 host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
808 host_stop_req->reason = DRIVER_STOP_REQUEST;
809 host_stop_req->reserved[0] = 0;
810 host_stop_req->reserved[1] = 0;
811 dev->extra_write_index = 2;
812 break;
813
814 default:
815 BUG();
816 break;
817
818 }
819}
820
821
822/**
823 * _mei_hb_read - processes read related operation.
824 *
825 * @dev: the device structure.
826 * @slots: free slots.
827 * @cb_pos: callback block.
828 * @cl: private data of the file object.
829 * @cmpl_list: complete list.
830 *
831 * returns 0, OK; otherwise, error.
832 */
833static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots,
834 struct mei_cl_cb *cb_pos,
835 struct mei_cl *cl,
836 struct mei_io_list *cmpl_list)
837{
838 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
839 sizeof(struct hbm_flow_control))) {
840 /* return the cancel routine */
841 list_del(&cb_pos->cb_list);
842 return -EBADMSG;
843 }
844
845 *slots -= (sizeof(struct mei_msg_hdr) +
846 sizeof(struct hbm_flow_control) + 3) / 4;
847 if (mei_send_flow_control(dev, cl)) {
848 cl->status = -ENODEV;
849 cb_pos->information = 0;
850 list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list);
851 return -ENODEV;
852 }
853 list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list);
854
855 return 0;
856}
857
858
859/**
860 * _mei_irq_thread_ioctl - processes ioctl related operation.
861 *
862 * @dev: the device structure.
863 * @slots: free slots.
864 * @cb_pos: callback block.
865 * @cl: private data of the file object.
866 * @cmpl_list: complete list.
867 *
868 * returns 0, OK; otherwise, error.
869 */
870static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots,
871 struct mei_cl_cb *cb_pos,
872 struct mei_cl *cl,
873 struct mei_io_list *cmpl_list)
874{
875 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
876 sizeof(struct hbm_client_connect_request))) {
877 cl->state = MEI_FILE_CONNECTING;
878 *slots -= (sizeof(struct mei_msg_hdr) +
879 sizeof(struct hbm_client_connect_request) + 3) / 4;
880 if (mei_connect(dev, cl)) {
881 cl->status = -ENODEV;
882 cb_pos->information = 0;
883 list_del(&cb_pos->cb_list);
884 return -ENODEV;
885 } else {
886 list_move_tail(&cb_pos->cb_list,
887 &dev->ctrl_rd_list.mei_cb.cb_list);
888 cl->timer_count = MEI_CONNECT_TIMEOUT;
889 }
890 } else {
891 /* return the cancel routine */
892 list_del(&cb_pos->cb_list);
893 return -EBADMSG;
894 }
895
896 return 0;
897}
898
899/**
900 * _mei_irq_thread_cmpl - processes completed and no-iamthif operation.
901 *
902 * @dev: the device structure.
903 * @slots: free slots.
904 * @cb_pos: callback block.
905 * @cl: private data of the file object.
906 * @cmpl_list: complete list.
907 *
908 * returns 0, OK; otherwise, error.
909 */
910static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots,
911 struct mei_cl_cb *cb_pos,
912 struct mei_cl *cl,
913 struct mei_io_list *cmpl_list)
914{
915 struct mei_msg_hdr *mei_hdr;
916
917 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
918 (cb_pos->request_buffer.size -
919 cb_pos->information))) {
920 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
921 mei_hdr->host_addr = cl->host_client_id;
922 mei_hdr->me_addr = cl->me_client_id;
923 mei_hdr->length = cb_pos->request_buffer.size -
924 cb_pos->information;
925 mei_hdr->msg_complete = 1;
926 mei_hdr->reserved = 0;
927 dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d"
928 "mei_hdr->msg_complete = %d\n",
929 cb_pos->request_buffer.size,
930 mei_hdr->msg_complete);
931 dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n",
932 cb_pos->information);
933 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
934 mei_hdr->length);
935 *slots -= (sizeof(struct mei_msg_hdr) +
936 mei_hdr->length + 3) / 4;
937 if (mei_write_message(dev, mei_hdr,
938 (unsigned char *)
939 (cb_pos->request_buffer.data +
940 cb_pos->information),
941 mei_hdr->length)) {
942 cl->status = -ENODEV;
943 list_move_tail(&cb_pos->cb_list,
944 &cmpl_list->mei_cb.cb_list);
945 return -ENODEV;
946 } else {
947 if (mei_flow_ctrl_reduce(dev, cl))
948 return -ENODEV;
949 cl->status = 0;
950 cb_pos->information += mei_hdr->length;
951 list_move_tail(&cb_pos->cb_list,
952 &dev->write_waiting_list.mei_cb.cb_list);
953 }
954 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
955 /* buffer is still empty */
956 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
957 mei_hdr->host_addr = cl->host_client_id;
958 mei_hdr->me_addr = cl->me_client_id;
959 mei_hdr->length =
960 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
961 mei_hdr->msg_complete = 0;
962 mei_hdr->reserved = 0;
963
964 (*slots) -= (sizeof(struct mei_msg_hdr) +
965 mei_hdr->length + 3) / 4;
966 if (mei_write_message(dev, mei_hdr,
967 (unsigned char *)
968 (cb_pos->request_buffer.data +
969 cb_pos->information),
970 mei_hdr->length)) {
971 cl->status = -ENODEV;
972 list_move_tail(&cb_pos->cb_list,
973 &cmpl_list->mei_cb.cb_list);
974 return -ENODEV;
975 } else {
976 cb_pos->information += mei_hdr->length;
977 dev_dbg(&dev->pdev->dev,
978 "cb_pos->request_buffer.size =%d"
979 " mei_hdr->msg_complete = %d\n",
980 cb_pos->request_buffer.size,
981 mei_hdr->msg_complete);
982 dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n",
983 cb_pos->information);
984 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
985 mei_hdr->length);
986 }
987 return -EMSGSIZE;
988 } else {
989 return -EBADMSG;
990 }
991
992 return 0;
993}
994
995/**
996 * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation.
997 *
998 * @dev: the device structure.
999 * @slots: free slots.
1000 * @cb_pos: callback block.
1001 * @cl: private data of the file object.
1002 * @cmpl_list: complete list.
1003 *
1004 * returns 0, OK; otherwise, error.
1005 */
1006static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots,
1007 struct mei_cl_cb *cb_pos,
1008 struct mei_cl *cl,
1009 struct mei_io_list *cmpl_list)
1010{
1011 struct mei_msg_hdr *mei_hdr;
1012
1013 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) +
1014 dev->iamthif_msg_buf_size -
1015 dev->iamthif_msg_buf_index)) {
1016 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1017 mei_hdr->host_addr = cl->host_client_id;
1018 mei_hdr->me_addr = cl->me_client_id;
1019 mei_hdr->length = dev->iamthif_msg_buf_size -
1020 dev->iamthif_msg_buf_index;
1021 mei_hdr->msg_complete = 1;
1022 mei_hdr->reserved = 0;
1023
1024 *slots -= (sizeof(struct mei_msg_hdr) +
1025 mei_hdr->length + 3) / 4;
1026
1027 if (mei_write_message(dev, mei_hdr,
1028 (dev->iamthif_msg_buf +
1029 dev->iamthif_msg_buf_index),
1030 mei_hdr->length)) {
1031 dev->iamthif_state = MEI_IAMTHIF_IDLE;
1032 cl->status = -ENODEV;
1033 list_del(&cb_pos->cb_list);
1034 return -ENODEV;
1035 } else {
1036 if (mei_flow_ctrl_reduce(dev, cl))
1037 return -ENODEV;
1038 dev->iamthif_msg_buf_index += mei_hdr->length;
1039 cb_pos->information = dev->iamthif_msg_buf_index;
1040 cl->status = 0;
1041 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
1042 dev->iamthif_flow_control_pending = true;
1043 /* save iamthif cb sent to amthi client */
1044 dev->iamthif_current_cb = cb_pos;
1045 list_move_tail(&cb_pos->cb_list,
1046 &dev->write_waiting_list.mei_cb.cb_list);
1047
1048 }
1049 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) {
1050 /* buffer is still empty */
1051 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
1052 mei_hdr->host_addr = cl->host_client_id;
1053 mei_hdr->me_addr = cl->me_client_id;
1054 mei_hdr->length =
1055 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
1056 mei_hdr->msg_complete = 0;
1057 mei_hdr->reserved = 0;
1058
1059 *slots -= (sizeof(struct mei_msg_hdr) +
1060 mei_hdr->length + 3) / 4;
1061
1062 if (mei_write_message(dev, mei_hdr,
1063 (dev->iamthif_msg_buf +
1064 dev->iamthif_msg_buf_index),
1065 mei_hdr->length)) {
1066 cl->status = -ENODEV;
1067 list_del(&cb_pos->cb_list);
1068 } else {
1069 dev->iamthif_msg_buf_index += mei_hdr->length;
1070 }
1071 return -EMSGSIZE;
1072 } else {
1073 return -EBADMSG;
1074 }
1075
1076 return 0;
1077}
1078
1079/**
1080 * mei_irq_thread_read_handler - bottom half read routine after ISR to
1081 * handle the read processing.
1082 *
1083 * @cmpl_list: An instance of our list structure
1084 * @dev: the device structure
1085 * @slots: slots to read.
1086 *
1087 * returns 0 on success, <0 on failure.
1088 */
1089static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list,
1090 struct mei_device *dev,
1091 s32 *slots)
1092{
1093 struct mei_msg_hdr *mei_hdr;
1094 struct mei_cl *cl_pos = NULL;
1095 struct mei_cl *cl_next = NULL;
1096 int ret = 0;
1097
1098 if (!dev->rd_msg_hdr) {
1099 dev->rd_msg_hdr = mei_mecbrw_read(dev);
1100 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
1101 (*slots)--;
1102 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
1103 }
1104 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
1105 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length);
1106
1107 if (mei_hdr->reserved || !dev->rd_msg_hdr) {
1108 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
1109 ret = -EBADMSG;
1110 goto end;
1111 }
1112
1113 if (mei_hdr->host_addr || mei_hdr->me_addr) {
1114 list_for_each_entry_safe(cl_pos, cl_next,
1115 &dev->file_list, link) {
1116 dev_dbg(&dev->pdev->dev,
1117 "list_for_each_entry_safe read host"
1118 " client = %d, ME client = %d\n",
1119 cl_pos->host_client_id,
1120 cl_pos->me_client_id);
1121 if (cl_pos->host_client_id == mei_hdr->host_addr &&
1122 cl_pos->me_client_id == mei_hdr->me_addr)
1123 break;
1124 }
1125
1126 if (&cl_pos->link == &dev->file_list) {
1127 dev_dbg(&dev->pdev->dev, "corrupted message header\n");
1128 ret = -EBADMSG;
1129 goto end;
1130 }
1131 }
1132 if (((*slots) * sizeof(u32)) < mei_hdr->length) {
1133 dev_dbg(&dev->pdev->dev,
1134 "we can't read the message slots =%08x.\n",
1135 *slots);
1136 /* we can't read the message */
1137 ret = -ERANGE;
1138 goto end;
1139 }
1140
1141 /* decide where to read the message too */
1142 if (!mei_hdr->host_addr) {
1143 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
1144 mei_irq_thread_read_bus_message(dev, mei_hdr);
1145 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
1146 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
1147 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
1148 (dev->iamthif_state == MEI_IAMTHIF_READING)) {
1149 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
1150 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
1151 mei_hdr->length);
1152 ret = mei_irq_thread_read_amthi_message(cmpl_list,
1153 dev, mei_hdr);
1154 if (ret)
1155 goto end;
1156
1157 } else {
1158 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
1159 ret = mei_irq_thread_read_client_message(cmpl_list,
1160 dev, mei_hdr);
1161 if (ret)
1162 goto end;
1163
1164 }
1165
1166 /* reset the number of slots and header */
1167 *slots = mei_count_full_read_slots(dev);
1168 dev->rd_msg_hdr = 0;
1169
1170 if (*slots == -EOVERFLOW) {
1171 /* overflow - reset */
1172 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n");
1173 /* set the event since message has been read */
1174 ret = -ERANGE;
1175 goto end;
1176 }
1177end:
1178 return ret;
1179}
1180
1181
1182/**
1183 * mei_irq_thread_write_handler - bottom half write routine after
1184 * ISR to handle the write processing.
1185 *
1186 * @cmpl_list: An instance of our list structure
1187 * @dev: the device structure
1188 * @slots: slots to write.
1189 *
1190 * returns 0 on success, <0 on failure.
1191 */
1192static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list,
1193 struct mei_device *dev,
1194 s32 *slots)
1195{
1196
1197 struct mei_cl *cl;
1198 struct mei_cl_cb *pos = NULL, *next = NULL;
1199 struct mei_io_list *list;
1200 int ret;
1201
1202 if (!mei_host_buffer_is_empty(dev)) {
1203 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
1204 return 0;
1205 }
1206 *slots = mei_count_empty_write_slots(dev);
1207 /* complete all waiting for write CB */
1208 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n");
1209
1210 list = &dev->write_waiting_list;
1211 list_for_each_entry_safe(pos, next,
1212 &list->mei_cb.cb_list, cb_list) {
1213 cl = (struct mei_cl *)pos->file_private;
1214 if (cl == NULL)
1215 continue;
1216
1217 cl->status = 0;
1218 list_del(&pos->cb_list);
1219 if (MEI_WRITING == cl->writing_state &&
1220 (pos->major_file_operations == MEI_WRITE) &&
1221 (cl != &dev->iamthif_cl)) {
1222 dev_dbg(&dev->pdev->dev,
1223 "MEI WRITE COMPLETE\n");
1224 cl->writing_state = MEI_WRITE_COMPLETE;
1225 list_add_tail(&pos->cb_list,
1226 &cmpl_list->mei_cb.cb_list);
1227 }
1228 if (cl == &dev->iamthif_cl) {
1229 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n");
1230 if (dev->iamthif_flow_control_pending) {
1231 ret = _mei_irq_thread_iamthif_read(
1232 dev, slots);
1233 if (ret)
1234 return ret;
1235 }
1236 }
1237 }
1238
1239 if (dev->stop && !dev->wd_pending) {
1240 dev->wd_stopped = true;
1241 wake_up_interruptible(&dev->wait_stop_wd);
1242 return 0;
1243 }
1244
1245 if (dev->extra_write_index) {
1246 dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n",
1247 dev->extra_write_index);
1248 mei_write_message(dev,
1249 (struct mei_msg_hdr *) &dev->ext_msg_buf[0],
1250 (unsigned char *) &dev->ext_msg_buf[1],
1251 (dev->extra_write_index - 1) * sizeof(u32));
1252 *slots -= dev->extra_write_index;
1253 dev->extra_write_index = 0;
1254 }
1255 if (dev->mei_state == MEI_ENABLED) {
1256 if (dev->wd_pending &&
1257 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
1258 if (mei_wd_send(dev))
1259 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
1260 else
1261 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
1262 return -ENODEV;
1263
1264 dev->wd_pending = false;
1265
1266 if (dev->wd_timeout) {
1267 *slots -= (sizeof(struct mei_msg_hdr) +
1268 MEI_START_WD_DATA_SIZE + 3) / 4;
1269 dev->wd_due_counter = 2;
1270 } else {
1271 *slots -= (sizeof(struct mei_msg_hdr) +
1272 MEI_WD_PARAMS_SIZE + 3) / 4;
1273 dev->wd_due_counter = 0;
1274 }
1275
1276 }
1277 }
1278 if (dev->stop)
1279 return -ENODEV;
1280
1281 /* complete control write list CB */
1282 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n");
1283 list_for_each_entry_safe(pos, next,
1284 &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) {
1285 cl = (struct mei_cl *) pos->file_private;
1286 if (!cl) {
1287 list_del(&pos->cb_list);
1288 return -ENODEV;
1289 }
1290 switch (pos->major_file_operations) {
1291 case MEI_CLOSE:
1292 /* send disconnect message */
1293 ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list);
1294 if (ret)
1295 return ret;
1296
1297 break;
1298 case MEI_READ:
1299 /* send flow control message */
1300 ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list);
1301 if (ret)
1302 return ret;
1303
1304 break;
1305 case MEI_IOCTL:
1306 /* connect message */
1307 if (mei_other_client_is_connecting(dev, cl))
1308 continue;
1309 ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list);
1310 if (ret)
1311 return ret;
1312
1313 break;
1314
1315 default:
1316 BUG();
1317 }
1318
1319 }
1320 /* complete write list CB */
1321 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
1322 list_for_each_entry_safe(pos, next,
1323 &dev->write_list.mei_cb.cb_list, cb_list) {
1324 cl = (struct mei_cl *)pos->file_private;
1325 if (cl == NULL)
1326 continue;
1327
1328 if (cl != &dev->iamthif_cl) {
1329 if (!mei_flow_ctrl_creds(dev, cl)) {
1330 dev_dbg(&dev->pdev->dev,
1331 "No flow control"
1332 " credentials for client"
1333 " %d, not sending.\n",
1334 cl->host_client_id);
1335 continue;
1336 }
1337 ret = _mei_irq_thread_cmpl(dev, slots,
1338 pos,
1339 cl, cmpl_list);
1340 if (ret)
1341 return ret;
1342
1343 } else if (cl == &dev->iamthif_cl) {
1344 /* IAMTHIF IOCTL */
1345 dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n");
1346 if (!mei_flow_ctrl_creds(dev, cl)) {
1347 dev_dbg(&dev->pdev->dev,
1348 "No flow control"
1349 " credentials for amthi"
1350 " client %d.\n",
1351 cl->host_client_id);
1352 continue;
1353 }
1354 ret = _mei_irq_thread_cmpl_iamthif(dev,
1355 slots,
1356 pos,
1357 cl,
1358 cmpl_list);
1359 if (ret)
1360 return ret;
1361
1362 }
1363
1364 }
1365 return 0;
1366}
1367
1368
1369
1370/**
1371 * mei_timer - timer function.
1372 *
1373 * @work: pointer to the work_struct structure
1374 *
1375 * NOTE: This function is called by timer interrupt work
1376 */
1377void mei_timer(struct work_struct *work)
1378{
1379 unsigned long timeout;
1380 struct mei_cl *cl_pos = NULL;
1381 struct mei_cl *cl_next = NULL;
1382 struct list_head *amthi_complete_list = NULL;
1383 struct mei_cl_cb *cb_pos = NULL;
1384 struct mei_cl_cb *cb_next = NULL;
1385
1386 struct mei_device *dev = container_of(work,
1387 struct mei_device, timer_work.work);
1388
1389
1390 mutex_lock(&dev->device_lock);
1391 if (dev->mei_state != MEI_ENABLED) {
1392 if (dev->mei_state == MEI_INIT_CLIENTS) {
1393 if (dev->init_clients_timer) {
1394 if (--dev->init_clients_timer == 0) {
1395 dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n",
1396 dev->init_clients_state);
1397 mei_reset(dev, 1);
1398 }
1399 }
1400 }
1401 goto out;
1402 }
1403 /*** connect/disconnect timeouts ***/
1404 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) {
1405 if (cl_pos->timer_count) {
1406 if (--cl_pos->timer_count == 0) {
1407 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n");
1408 mei_reset(dev, 1);
1409 goto out;
1410 }
1411 }
1412 }
1413
1414 if (dev->iamthif_stall_timer) {
1415 if (--dev->iamthif_stall_timer == 0) {
1416 dev_dbg(&dev->pdev->dev, "resetting because of hang to amthi.\n");
1417 mei_reset(dev, 1);
1418 dev->iamthif_msg_buf_size = 0;
1419 dev->iamthif_msg_buf_index = 0;
1420 dev->iamthif_canceled = false;
1421 dev->iamthif_ioctl = true;
1422 dev->iamthif_state = MEI_IAMTHIF_IDLE;
1423 dev->iamthif_timer = 0;
1424
1425 if (dev->iamthif_current_cb)
1426 mei_free_cb_private(dev->iamthif_current_cb);
1427
1428 dev->iamthif_file_object = NULL;
1429 dev->iamthif_current_cb = NULL;
1430 mei_run_next_iamthif_cmd(dev);
1431 }
1432 }
1433
1434 if (dev->iamthif_timer) {
1435
1436 timeout = dev->iamthif_timer +
1437 msecs_to_jiffies(IAMTHIF_READ_TIMER);
1438
1439 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n",
1440 dev->iamthif_timer);
1441 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout);
1442 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies);
1443 if (time_after(jiffies, timeout)) {
1444 /*
1445 * User didn't read the AMTHI data on time (15sec)
1446 * freeing AMTHI for other requests
1447 */
1448
1449 dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n");
1450
1451 amthi_complete_list = &dev->amthi_read_complete_list.
1452 mei_cb.cb_list;
1453
1454 list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) {
1455
1456 cl_pos = cb_pos->file_object->private_data;
1457
1458 /* Finding the AMTHI entry. */
1459 if (cl_pos == &dev->iamthif_cl)
1460 list_del(&cb_pos->cb_list);
1461 }
1462 if (dev->iamthif_current_cb)
1463 mei_free_cb_private(dev->iamthif_current_cb);
1464
1465 dev->iamthif_file_object->private_data = NULL;
1466 dev->iamthif_file_object = NULL;
1467 dev->iamthif_current_cb = NULL;
1468 dev->iamthif_timer = 0;
1469 mei_run_next_iamthif_cmd(dev);
1470
1471 }
1472 }
1473out:
1474 schedule_delayed_work(&dev->timer_work, 2 * HZ);
1475 mutex_unlock(&dev->device_lock);
1476}
1477
1478/**
1479 * mei_interrupt_thread_handler - function called after ISR to handle the interrupt
1480 * processing.
1481 *
1482 * @irq: The irq number
1483 * @dev_id: pointer to the device structure
1484 *
1485 * returns irqreturn_t
1486 *
1487 */
1488irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id)
1489{
1490 struct mei_device *dev = (struct mei_device *) dev_id;
1491 struct mei_io_list complete_list;
1492 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL;
1493 struct mei_cl *cl;
1494 s32 slots;
1495 int rets;
1496 bool bus_message_received;
1497
1498
1499 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
1500 /* initialize our complete list */
1501 mutex_lock(&dev->device_lock);
1502 mei_io_list_init(&complete_list);
1503 dev->host_hw_state = mei_hcsr_read(dev);
1504
1505 /* Ack the interrupt here
1506 * In case of MSI we don't go through the quick handler */
1507 if (pci_dev_msi_enabled(dev->pdev))
1508 mei_reg_write(dev, H_CSR, dev->host_hw_state);
1509
1510 dev->me_hw_state = mei_mecsr_read(dev);
1511
1512 /* check if ME wants a reset */
1513 if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
1514 dev->mei_state != MEI_RESETING &&
1515 dev->mei_state != MEI_INITIALIZING) {
1516 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1517 mei_reset(dev, 1);
1518 mutex_unlock(&dev->device_lock);
1519 return IRQ_HANDLED;
1520 }
1521
1522 /* check if we need to start the dev */
1523 if ((dev->host_hw_state & H_RDY) == 0) {
1524 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
1525 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
1526 dev->host_hw_state |= (H_IE | H_IG | H_RDY);
1527 mei_hcsr_set(dev);
1528 dev->mei_state = MEI_INIT_CLIENTS;
1529 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
1530 /* link is established
1531 * start sending messages.
1532 */
1533 mei_host_start_message(dev);
1534 mutex_unlock(&dev->device_lock);
1535 return IRQ_HANDLED;
1536 } else {
1537 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1538 mutex_unlock(&dev->device_lock);
1539 return IRQ_HANDLED;
1540 }
1541 }
1542 /* check slots available for reading */
1543 slots = mei_count_full_read_slots(dev);
1544 dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n",
1545 slots, dev->extra_write_index);
1546 while (slots > 0 && !dev->extra_write_index) {
1547 dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n",
1548 slots, dev->extra_write_index);
1549 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
1550 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
1551 if (rets)
1552 goto end;
1553 }
1554 rets = mei_irq_thread_write_handler(&complete_list, dev, &slots);
1555end:
1556 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1557 dev->host_hw_state = mei_hcsr_read(dev);
1558 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev);
1559
1560 bus_message_received = false;
1561 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
1562 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
1563 bus_message_received = true;
1564 }
1565 mutex_unlock(&dev->device_lock);
1566 if (bus_message_received) {
1567 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n");
1568 wake_up_interruptible(&dev->wait_recvd_msg);
1569 bus_message_received = false;
1570 }
1571 if (list_empty(&complete_list.mei_cb.cb_list))
1572 return IRQ_HANDLED;
1573
1574
1575 list_for_each_entry_safe(cb_pos, cb_next,
1576 &complete_list.mei_cb.cb_list, cb_list) {
1577 cl = (struct mei_cl *)cb_pos->file_private;
1578 list_del(&cb_pos->cb_list);
1579 if (cl) {
1580 if (cl != &dev->iamthif_cl) {
1581 dev_dbg(&dev->pdev->dev, "completing call back.\n");
1582 _mei_cmpl(cl, cb_pos);
1583 cb_pos = NULL;
1584 } else if (cl == &dev->iamthif_cl) {
1585 _mei_cmpl_iamthif(dev, cb_pos);
1586 }
1587 }
1588 }
1589 return IRQ_HANDLED;
1590}
diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c
new file mode 100644
index 00000000000..f9cced69b65
--- /dev/null
+++ b/drivers/misc/mei/iorw.c
@@ -0,0 +1,590 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17
18#include <linux/kernel.h>
19#include <linux/fs.h>
20#include <linux/errno.h>
21#include <linux/types.h>
22#include <linux/fcntl.h>
23#include <linux/aio.h>
24#include <linux/pci.h>
25#include <linux/init.h>
26#include <linux/ioctl.h>
27#include <linux/cdev.h>
28#include <linux/list.h>
29#include <linux/delay.h>
30#include <linux/sched.h>
31#include <linux/uuid.h>
32#include <linux/jiffies.h>
33#include <linux/uaccess.h>
34
35
36#include "mei_dev.h"
37#include "hw.h"
38#include <linux/mei.h>
39#include "interface.h"
40
41
42
43/**
44 * mei_ioctl_connect_client - the connect to fw client IOCTL function
45 *
46 * @dev: the device structure
47 * @data: IOCTL connect data, input and output parameters
48 * @file: private data of the file object
49 *
50 * Locking: called under "dev->device_lock" lock
51 *
52 * returns 0 on success, <0 on failure.
53 */
54int mei_ioctl_connect_client(struct file *file,
55 struct mei_connect_client_data *data)
56{
57 struct mei_device *dev;
58 struct mei_cl_cb *cb;
59 struct mei_client *client;
60 struct mei_cl *cl;
61 struct mei_cl *cl_pos = NULL;
62 struct mei_cl *cl_next = NULL;
63 long timeout = CONNECT_TIMEOUT;
64 int i;
65 int err;
66 int rets;
67
68 cl = file->private_data;
69 if (WARN_ON(!cl || !cl->dev))
70 return -ENODEV;
71
72 dev = cl->dev;
73
74 dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n");
75
76
77 /* buffered ioctl cb */
78 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
79 if (!cb) {
80 rets = -ENOMEM;
81 goto end;
82 }
83 INIT_LIST_HEAD(&cb->cb_list);
84
85 cb->major_file_operations = MEI_IOCTL;
86
87 if (dev->mei_state != MEI_ENABLED) {
88 rets = -ENODEV;
89 goto end;
90 }
91 if (cl->state != MEI_FILE_INITIALIZING &&
92 cl->state != MEI_FILE_DISCONNECTED) {
93 rets = -EBUSY;
94 goto end;
95 }
96
97 /* find ME client we're trying to connect to */
98 i = mei_find_me_client_index(dev, data->in_client_uuid);
99 if (i >= 0 && !dev->me_clients[i].props.fixed_address) {
100 cl->me_client_id = dev->me_clients[i].client_id;
101 cl->state = MEI_FILE_CONNECTING;
102 }
103
104 dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n",
105 cl->me_client_id);
106 dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n",
107 dev->me_clients[i].props.protocol_version);
108 dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n",
109 dev->me_clients[i].props.max_msg_length);
110
111 /* if we're connecting to amthi client then we will use the
112 * existing connection
113 */
114 if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) {
115 dev_dbg(&dev->pdev->dev, "FW Client is amthi\n");
116 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
117 rets = -ENODEV;
118 goto end;
119 }
120 clear_bit(cl->host_client_id, dev->host_clients_map);
121 list_for_each_entry_safe(cl_pos, cl_next,
122 &dev->file_list, link) {
123 if (mei_cl_cmp_id(cl, cl_pos)) {
124 dev_dbg(&dev->pdev->dev,
125 "remove file private data node host"
126 " client = %d, ME client = %d.\n",
127 cl_pos->host_client_id,
128 cl_pos->me_client_id);
129 list_del(&cl_pos->link);
130 }
131
132 }
133 dev_dbg(&dev->pdev->dev, "free file private data memory.\n");
134 kfree(cl);
135
136 cl = NULL;
137 file->private_data = &dev->iamthif_cl;
138
139 client = &data->out_client_properties;
140 client->max_msg_length =
141 dev->me_clients[i].props.max_msg_length;
142 client->protocol_version =
143 dev->me_clients[i].props.protocol_version;
144 rets = dev->iamthif_cl.status;
145
146 goto end;
147 }
148
149 if (cl->state != MEI_FILE_CONNECTING) {
150 rets = -ENODEV;
151 goto end;
152 }
153
154
155 /* prepare the output buffer */
156 client = &data->out_client_properties;
157 client->max_msg_length = dev->me_clients[i].props.max_msg_length;
158 client->protocol_version = dev->me_clients[i].props.protocol_version;
159 dev_dbg(&dev->pdev->dev, "Can connect?\n");
160 if (dev->mei_host_buffer_is_empty
161 && !mei_other_client_is_connecting(dev, cl)) {
162 dev_dbg(&dev->pdev->dev, "Sending Connect Message\n");
163 dev->mei_host_buffer_is_empty = false;
164 if (mei_connect(dev, cl)) {
165 dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n");
166 rets = -ENODEV;
167 goto end;
168 } else {
169 dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n");
170 cl->timer_count = MEI_CONNECT_TIMEOUT;
171 cb->file_private = cl;
172 list_add_tail(&cb->cb_list,
173 &dev->ctrl_rd_list.mei_cb.
174 cb_list);
175 }
176
177
178 } else {
179 dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n");
180 cb->file_private = cl;
181 dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n");
182 list_add_tail(&cb->cb_list,
183 &dev->ctrl_wr_list.mei_cb.cb_list);
184 }
185 mutex_unlock(&dev->device_lock);
186 err = wait_event_timeout(dev->wait_recvd_msg,
187 (MEI_FILE_CONNECTED == cl->state ||
188 MEI_FILE_DISCONNECTED == cl->state),
189 timeout * HZ);
190
191 mutex_lock(&dev->device_lock);
192 if (MEI_FILE_CONNECTED == cl->state) {
193 dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n");
194 rets = cl->status;
195 goto end;
196 } else {
197 dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n",
198 cl->state);
199 if (!err) {
200 dev_dbg(&dev->pdev->dev,
201 "wait_event_interruptible_timeout failed on client"
202 " connect message fw response message.\n");
203 }
204 rets = -EFAULT;
205
206 mei_io_list_flush(&dev->ctrl_rd_list, cl);
207 mei_io_list_flush(&dev->ctrl_wr_list, cl);
208 goto end;
209 }
210 rets = 0;
211end:
212 dev_dbg(&dev->pdev->dev, "free connect cb memory.");
213 kfree(cb);
214 return rets;
215}
216
217/**
218 * find_amthi_read_list_entry - finds a amthilist entry for current file
219 *
220 * @dev: the device structure
221 * @file: pointer to file object
222 *
223 * returns returned a list entry on success, NULL on failure.
224 */
225struct mei_cl_cb *find_amthi_read_list_entry(
226 struct mei_device *dev,
227 struct file *file)
228{
229 struct mei_cl *cl_temp;
230 struct mei_cl_cb *pos = NULL;
231 struct mei_cl_cb *next = NULL;
232
233 list_for_each_entry_safe(pos, next,
234 &dev->amthi_read_complete_list.mei_cb.cb_list, cb_list) {
235 cl_temp = (struct mei_cl *)pos->file_private;
236 if (cl_temp && cl_temp == &dev->iamthif_cl &&
237 pos->file_object == file)
238 return pos;
239 }
240 return NULL;
241}
242
243/**
244 * amthi_read - read data from AMTHI client
245 *
246 * @dev: the device structure
247 * @if_num: minor number
248 * @file: pointer to file object
249 * @*ubuf: pointer to user data in user space
250 * @length: data length to read
251 * @offset: data read offset
252 *
253 * Locking: called under "dev->device_lock" lock
254 *
255 * returns
256 * returned data length on success,
257 * zero if no data to read,
258 * negative on failure.
259 */
260int amthi_read(struct mei_device *dev, struct file *file,
261 char __user *ubuf, size_t length, loff_t *offset)
262{
263 int rets;
264 int wait_ret;
265 struct mei_cl_cb *cb = NULL;
266 struct mei_cl *cl = file->private_data;
267 unsigned long timeout;
268 int i;
269
270 /* Only Posible if we are in timeout */
271 if (!cl || cl != &dev->iamthif_cl) {
272 dev_dbg(&dev->pdev->dev, "bad file ext.\n");
273 return -ETIMEDOUT;
274 }
275
276 for (i = 0; i < dev->me_clients_num; i++) {
277 if (dev->me_clients[i].client_id ==
278 dev->iamthif_cl.me_client_id)
279 break;
280 }
281
282 if (i == dev->me_clients_num) {
283 dev_dbg(&dev->pdev->dev, "amthi client not found.\n");
284 return -ENODEV;
285 }
286 if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id))
287 return -ENODEV;
288
289 dev_dbg(&dev->pdev->dev, "checking amthi data\n");
290 cb = find_amthi_read_list_entry(dev, file);
291
292 /* Check for if we can block or not*/
293 if (cb == NULL && file->f_flags & O_NONBLOCK)
294 return -EAGAIN;
295
296
297 dev_dbg(&dev->pdev->dev, "waiting for amthi data\n");
298 while (cb == NULL) {
299 /* unlock the Mutex */
300 mutex_unlock(&dev->device_lock);
301
302 wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
303 (cb = find_amthi_read_list_entry(dev, file)));
304
305 if (wait_ret)
306 return -ERESTARTSYS;
307
308 dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
309
310 /* Locking again the Mutex */
311 mutex_lock(&dev->device_lock);
312 }
313
314
315 dev_dbg(&dev->pdev->dev, "Got amthi data\n");
316 dev->iamthif_timer = 0;
317
318 if (cb) {
319 timeout = cb->read_time +
320 msecs_to_jiffies(IAMTHIF_READ_TIMER);
321 dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n",
322 timeout);
323
324 if (time_after(jiffies, timeout)) {
325 dev_dbg(&dev->pdev->dev, "amthi Time out\n");
326 /* 15 sec for the message has expired */
327 list_del(&cb->cb_list);
328 rets = -ETIMEDOUT;
329 goto free;
330 }
331 }
332 /* if the whole message will fit remove it from the list */
333 if (cb->information >= *offset && length >= (cb->information - *offset))
334 list_del(&cb->cb_list);
335 else if (cb->information > 0 && cb->information <= *offset) {
336 /* end of the message has been reached */
337 list_del(&cb->cb_list);
338 rets = 0;
339 goto free;
340 }
341 /* else means that not full buffer will be read and do not
342 * remove message from deletion list
343 */
344
345 dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n",
346 cb->response_buffer.size);
347 dev_dbg(&dev->pdev->dev, "amthi cb->information - %lu\n",
348 cb->information);
349
350 /* length is being turncated to PAGE_SIZE, however,
351 * the information may be longer */
352 length = min_t(size_t, length, (cb->information - *offset));
353
354 if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length))
355 rets = -EFAULT;
356 else {
357 rets = length;
358 if ((*offset + length) < cb->information) {
359 *offset += length;
360 goto out;
361 }
362 }
363free:
364 dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n");
365 *offset = 0;
366 mei_free_cb_private(cb);
367out:
368 return rets;
369}
370
371/**
372 * mei_start_read - the start read client message function.
373 *
374 * @dev: the device structure
375 * @if_num: minor number
376 * @cl: private data of the file object
377 *
378 * returns 0 on success, <0 on failure.
379 */
380int mei_start_read(struct mei_device *dev, struct mei_cl *cl)
381{
382 struct mei_cl_cb *cb;
383 int rets = 0;
384 int i;
385
386 if (cl->state != MEI_FILE_CONNECTED)
387 return -ENODEV;
388
389 if (dev->mei_state != MEI_ENABLED)
390 return -ENODEV;
391
392 dev_dbg(&dev->pdev->dev, "check if read is pending.\n");
393 if (cl->read_pending || cl->read_cb) {
394 dev_dbg(&dev->pdev->dev, "read is pending.\n");
395 return -EBUSY;
396 }
397
398 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
399 if (!cb)
400 return -ENOMEM;
401
402 dev_dbg(&dev->pdev->dev, "allocation call back successful. host client = %d, ME client = %d\n",
403 cl->host_client_id, cl->me_client_id);
404
405 for (i = 0; i < dev->me_clients_num; i++) {
406 if (dev->me_clients[i].client_id == cl->me_client_id)
407 break;
408
409 }
410
411 if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
412 rets = -ENODEV;
413 goto unlock;
414 }
415
416 if (i == dev->me_clients_num) {
417 rets = -ENODEV;
418 goto unlock;
419 }
420
421 cb->response_buffer.size = dev->me_clients[i].props.max_msg_length;
422 cb->response_buffer.data =
423 kmalloc(cb->response_buffer.size, GFP_KERNEL);
424 if (!cb->response_buffer.data) {
425 rets = -ENOMEM;
426 goto unlock;
427 }
428 dev_dbg(&dev->pdev->dev, "allocation call back data success.\n");
429 cb->major_file_operations = MEI_READ;
430 /* make sure information is zero before we start */
431 cb->information = 0;
432 cb->file_private = (void *) cl;
433 cl->read_cb = cb;
434 if (dev->mei_host_buffer_is_empty) {
435 dev->mei_host_buffer_is_empty = false;
436 if (mei_send_flow_control(dev, cl)) {
437 rets = -ENODEV;
438 goto unlock;
439 }
440 list_add_tail(&cb->cb_list, &dev->read_list.mei_cb.cb_list);
441 } else {
442 list_add_tail(&cb->cb_list, &dev->ctrl_wr_list.mei_cb.cb_list);
443 }
444 return rets;
445unlock:
446 mei_free_cb_private(cb);
447 return rets;
448}
449
450/**
451 * amthi_write - write iamthif data to amthi client
452 *
453 * @dev: the device structure
454 * @cb: mei call back struct
455 *
456 * returns 0 on success, <0 on failure.
457 */
458int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb)
459{
460 struct mei_msg_hdr mei_hdr;
461 int ret;
462
463 if (!dev || !cb)
464 return -ENODEV;
465
466 dev_dbg(&dev->pdev->dev, "write data to amthi client.\n");
467
468 dev->iamthif_state = MEI_IAMTHIF_WRITING;
469 dev->iamthif_current_cb = cb;
470 dev->iamthif_file_object = cb->file_object;
471 dev->iamthif_canceled = false;
472 dev->iamthif_ioctl = true;
473 dev->iamthif_msg_buf_size = cb->request_buffer.size;
474 memcpy(dev->iamthif_msg_buf, cb->request_buffer.data,
475 cb->request_buffer.size);
476
477 ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl);
478 if (ret < 0)
479 return ret;
480
481 if (ret && dev->mei_host_buffer_is_empty) {
482 ret = 0;
483 dev->mei_host_buffer_is_empty = false;
484 if (cb->request_buffer.size >
485 (((dev->host_hw_state & H_CBD) >> 24) * sizeof(u32))
486 -sizeof(struct mei_msg_hdr)) {
487 mei_hdr.length =
488 (((dev->host_hw_state & H_CBD) >> 24) *
489 sizeof(u32)) - sizeof(struct mei_msg_hdr);
490 mei_hdr.msg_complete = 0;
491 } else {
492 mei_hdr.length = cb->request_buffer.size;
493 mei_hdr.msg_complete = 1;
494 }
495
496 mei_hdr.host_addr = dev->iamthif_cl.host_client_id;
497 mei_hdr.me_addr = dev->iamthif_cl.me_client_id;
498 mei_hdr.reserved = 0;
499 dev->iamthif_msg_buf_index += mei_hdr.length;
500 if (mei_write_message(dev, &mei_hdr,
501 (unsigned char *)(dev->iamthif_msg_buf),
502 mei_hdr.length))
503 return -ENODEV;
504
505 if (mei_hdr.msg_complete) {
506 if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl))
507 return -ENODEV;
508 dev->iamthif_flow_control_pending = true;
509 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL;
510 dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n");
511 dev->iamthif_current_cb = cb;
512 dev->iamthif_file_object = cb->file_object;
513 list_add_tail(&cb->cb_list,
514 &dev->write_waiting_list.mei_cb.cb_list);
515 } else {
516 dev_dbg(&dev->pdev->dev, "message does not complete, "
517 "so add amthi cb to write list.\n");
518 list_add_tail(&cb->cb_list,
519 &dev->write_list.mei_cb.cb_list);
520 }
521 } else {
522 if (!(dev->mei_host_buffer_is_empty))
523 dev_dbg(&dev->pdev->dev, "host buffer is not empty");
524
525 dev_dbg(&dev->pdev->dev, "No flow control credentials, "
526 "so add iamthif cb to write list.\n");
527 list_add_tail(&cb->cb_list, &dev->write_list.mei_cb.cb_list);
528 }
529 return 0;
530}
531
532/**
533 * iamthif_ioctl_send_msg - send cmd data to amthi client
534 *
535 * @dev: the device structure
536 *
537 * returns 0 on success, <0 on failure.
538 */
539void mei_run_next_iamthif_cmd(struct mei_device *dev)
540{
541 struct mei_cl *cl_tmp;
542 struct mei_cl_cb *pos = NULL;
543 struct mei_cl_cb *next = NULL;
544 int status;
545
546 if (!dev)
547 return;
548
549 dev->iamthif_msg_buf_size = 0;
550 dev->iamthif_msg_buf_index = 0;
551 dev->iamthif_canceled = false;
552 dev->iamthif_ioctl = true;
553 dev->iamthif_state = MEI_IAMTHIF_IDLE;
554 dev->iamthif_timer = 0;
555 dev->iamthif_file_object = NULL;
556
557 dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n");
558
559 list_for_each_entry_safe(pos, next,
560 &dev->amthi_cmd_list.mei_cb.cb_list, cb_list) {
561 list_del(&pos->cb_list);
562 cl_tmp = (struct mei_cl *)pos->file_private;
563
564 if (cl_tmp && cl_tmp == &dev->iamthif_cl) {
565 status = amthi_write(dev, pos);
566 if (status) {
567 dev_dbg(&dev->pdev->dev,
568 "amthi write failed status = %d\n",
569 status);
570 return;
571 }
572 break;
573 }
574 }
575}
576
577/**
578 * mei_free_cb_private - free mei_cb_private related memory
579 *
580 * @cb: mei callback struct
581 */
582void mei_free_cb_private(struct mei_cl_cb *cb)
583{
584 if (cb == NULL)
585 return;
586
587 kfree(cb->request_buffer.data);
588 kfree(cb->response_buffer.data);
589 kfree(cb);
590}
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c
new file mode 100644
index 00000000000..c7033322833
--- /dev/null
+++ b/drivers/misc/mei/main.c
@@ -0,0 +1,1230 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
18
19#include <linux/module.h>
20#include <linux/moduleparam.h>
21#include <linux/kernel.h>
22#include <linux/device.h>
23#include <linux/fs.h>
24#include <linux/errno.h>
25#include <linux/types.h>
26#include <linux/fcntl.h>
27#include <linux/aio.h>
28#include <linux/pci.h>
29#include <linux/poll.h>
30#include <linux/init.h>
31#include <linux/ioctl.h>
32#include <linux/cdev.h>
33#include <linux/sched.h>
34#include <linux/uuid.h>
35#include <linux/compat.h>
36#include <linux/jiffies.h>
37#include <linux/interrupt.h>
38#include <linux/miscdevice.h>
39
40#include "mei_dev.h"
41#include <linux/mei.h>
42#include "interface.h"
43
44static const char mei_driver_name[] = "mei";
45
46/* The device pointer */
47/* Currently this driver works as long as there is only a single AMT device. */
48struct pci_dev *mei_device;
49
50/* mei_pci_tbl - PCI Device ID Table */
51static DEFINE_PCI_DEVICE_TABLE(mei_pci_tbl) = {
52 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82946GZ)},
53 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G35)},
54 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82Q965)},
55 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82G965)},
56 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GM965)},
57 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_82GME965)},
58 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q35)},
59 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82G33)},
60 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82Q33)},
61 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_82X38)},
62 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_3200)},
63 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_6)},
64 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_7)},
65 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_8)},
66 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_9)},
67 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9_10)},
68 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_1)},
69 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_2)},
70 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_3)},
71 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH9M_4)},
72 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_1)},
73 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_2)},
74 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_3)},
75 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_ICH10_4)},
76 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_1)},
77 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_IBXPK_2)},
78 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_CPT_1)},
79 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PBG_1)},
80 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_1)},
81 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_2)},
82 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, MEI_DEV_ID_PPT_3)},
83
84 /* required last entry */
85 {0, }
86};
87
88MODULE_DEVICE_TABLE(pci, mei_pci_tbl);
89
90static DEFINE_MUTEX(mei_mutex);
91
92
93/**
94 * mei_clear_list - removes all callbacks associated with file
95 * from mei_cb_list
96 *
97 * @dev: device structure.
98 * @file: file structure
99 * @mei_cb_list: callbacks list
100 *
101 * mei_clear_list is called to clear resources associated with file
102 * when application calls close function or Ctrl-C was pressed
103 *
104 * returns true if callback removed from the list, false otherwise
105 */
106static bool mei_clear_list(struct mei_device *dev,
107 struct file *file, struct list_head *mei_cb_list)
108{
109 struct mei_cl_cb *cb_pos = NULL;
110 struct mei_cl_cb *cb_next = NULL;
111 struct file *file_temp;
112 bool removed = false;
113
114 /* list all list member */
115 list_for_each_entry_safe(cb_pos, cb_next, mei_cb_list, cb_list) {
116 file_temp = (struct file *)cb_pos->file_object;
117 /* check if list member associated with a file */
118 if (file_temp == file) {
119 /* remove member from the list */
120 list_del(&cb_pos->cb_list);
121 /* check if cb equal to current iamthif cb */
122 if (dev->iamthif_current_cb == cb_pos) {
123 dev->iamthif_current_cb = NULL;
124 /* send flow control to iamthif client */
125 mei_send_flow_control(dev, &dev->iamthif_cl);
126 }
127 /* free all allocated buffers */
128 mei_free_cb_private(cb_pos);
129 cb_pos = NULL;
130 removed = true;
131 }
132 }
133 return removed;
134}
135
136/**
137 * mei_clear_lists - removes all callbacks associated with file
138 *
139 * @dev: device structure
140 * @file: file structure
141 *
142 * mei_clear_lists is called to clear resources associated with file
143 * when application calls close function or Ctrl-C was pressed
144 *
145 * returns true if callback removed from the list, false otherwise
146 */
147static bool mei_clear_lists(struct mei_device *dev, struct file *file)
148{
149 bool removed = false;
150
151 /* remove callbacks associated with a file */
152 mei_clear_list(dev, file, &dev->amthi_cmd_list.mei_cb.cb_list);
153 if (mei_clear_list(dev, file,
154 &dev->amthi_read_complete_list.mei_cb.cb_list))
155 removed = true;
156
157 mei_clear_list(dev, file, &dev->ctrl_rd_list.mei_cb.cb_list);
158
159 if (mei_clear_list(dev, file, &dev->ctrl_wr_list.mei_cb.cb_list))
160 removed = true;
161
162 if (mei_clear_list(dev, file, &dev->write_waiting_list.mei_cb.cb_list))
163 removed = true;
164
165 if (mei_clear_list(dev, file, &dev->write_list.mei_cb.cb_list))
166 removed = true;
167
168 /* check if iamthif_current_cb not NULL */
169 if (dev->iamthif_current_cb && !removed) {
170 /* check file and iamthif current cb association */
171 if (dev->iamthif_current_cb->file_object == file) {
172 /* remove cb */
173 mei_free_cb_private(dev->iamthif_current_cb);
174 dev->iamthif_current_cb = NULL;
175 removed = true;
176 }
177 }
178 return removed;
179}
180/**
181 * find_read_list_entry - find read list entry
182 *
183 * @dev: device structure
184 * @file: pointer to file structure
185 *
186 * returns cb on success, NULL on error
187 */
188static struct mei_cl_cb *find_read_list_entry(
189 struct mei_device *dev,
190 struct mei_cl *cl)
191{
192 struct mei_cl_cb *pos = NULL;
193 struct mei_cl_cb *next = NULL;
194
195 dev_dbg(&dev->pdev->dev, "remove read_list CB\n");
196 list_for_each_entry_safe(pos, next,
197 &dev->read_list.mei_cb.cb_list, cb_list) {
198 struct mei_cl *cl_temp;
199 cl_temp = (struct mei_cl *)pos->file_private;
200
201 if (mei_cl_cmp_id(cl, cl_temp))
202 return pos;
203 }
204 return NULL;
205}
206
207/**
208 * mei_open - the open function
209 *
210 * @inode: pointer to inode structure
211 * @file: pointer to file structure
212 *
213 * returns 0 on success, <0 on error
214 */
215static int mei_open(struct inode *inode, struct file *file)
216{
217 struct mei_cl *cl;
218 struct mei_device *dev;
219 unsigned long cl_id;
220 int err;
221
222 err = -ENODEV;
223 if (!mei_device)
224 goto out;
225
226 dev = pci_get_drvdata(mei_device);
227 if (!dev)
228 goto out;
229
230 mutex_lock(&dev->device_lock);
231 err = -ENOMEM;
232 cl = mei_cl_allocate(dev);
233 if (!cl)
234 goto out_unlock;
235
236 err = -ENODEV;
237 if (dev->mei_state != MEI_ENABLED) {
238 dev_dbg(&dev->pdev->dev, "mei_state != MEI_ENABLED mei_state= %d\n",
239 dev->mei_state);
240 goto out_unlock;
241 }
242 err = -EMFILE;
243 if (dev->open_handle_count >= MEI_MAX_OPEN_HANDLE_COUNT)
244 goto out_unlock;
245
246 cl_id = find_first_zero_bit(dev->host_clients_map, MEI_CLIENTS_MAX);
247 if (cl_id >= MEI_CLIENTS_MAX)
248 goto out_unlock;
249
250 cl->host_client_id = cl_id;
251
252 dev_dbg(&dev->pdev->dev, "client_id = %d\n", cl->host_client_id);
253
254 dev->open_handle_count++;
255
256 list_add_tail(&cl->link, &dev->file_list);
257
258 set_bit(cl->host_client_id, dev->host_clients_map);
259 cl->state = MEI_FILE_INITIALIZING;
260 cl->sm_state = 0;
261
262 file->private_data = cl;
263 mutex_unlock(&dev->device_lock);
264
265 return nonseekable_open(inode, file);
266
267out_unlock:
268 mutex_unlock(&dev->device_lock);
269 kfree(cl);
270out:
271 return err;
272}
273
274/**
275 * mei_release - the release function
276 *
277 * @inode: pointer to inode structure
278 * @file: pointer to file structure
279 *
280 * returns 0 on success, <0 on error
281 */
282static int mei_release(struct inode *inode, struct file *file)
283{
284 struct mei_cl *cl = file->private_data;
285 struct mei_cl_cb *cb;
286 struct mei_device *dev;
287 int rets = 0;
288
289 if (WARN_ON(!cl || !cl->dev))
290 return -ENODEV;
291
292 dev = cl->dev;
293
294 mutex_lock(&dev->device_lock);
295 if (cl != &dev->iamthif_cl) {
296 if (cl->state == MEI_FILE_CONNECTED) {
297 cl->state = MEI_FILE_DISCONNECTING;
298 dev_dbg(&dev->pdev->dev,
299 "disconnecting client host client = %d, "
300 "ME client = %d\n",
301 cl->host_client_id,
302 cl->me_client_id);
303 rets = mei_disconnect_host_client(dev, cl);
304 }
305 mei_cl_flush_queues(cl);
306 dev_dbg(&dev->pdev->dev, "remove client host client = %d, ME client = %d\n",
307 cl->host_client_id,
308 cl->me_client_id);
309
310 if (dev->open_handle_count > 0) {
311 clear_bit(cl->host_client_id, dev->host_clients_map);
312 dev->open_handle_count--;
313 }
314 mei_remove_client_from_file_list(dev, cl->host_client_id);
315
316 /* free read cb */
317 cb = NULL;
318 if (cl->read_cb) {
319 cb = find_read_list_entry(dev, cl);
320 /* Remove entry from read list */
321 if (cb)
322 list_del(&cb->cb_list);
323
324 cb = cl->read_cb;
325 cl->read_cb = NULL;
326 }
327
328 file->private_data = NULL;
329
330 if (cb) {
331 mei_free_cb_private(cb);
332 cb = NULL;
333 }
334
335 kfree(cl);
336 } else {
337 if (dev->open_handle_count > 0)
338 dev->open_handle_count--;
339
340 if (dev->iamthif_file_object == file &&
341 dev->iamthif_state != MEI_IAMTHIF_IDLE) {
342
343 dev_dbg(&dev->pdev->dev, "amthi canceled iamthif state %d\n",
344 dev->iamthif_state);
345 dev->iamthif_canceled = true;
346 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) {
347 dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n");
348 mei_run_next_iamthif_cmd(dev);
349 }
350 }
351
352 if (mei_clear_lists(dev, file))
353 dev->iamthif_state = MEI_IAMTHIF_IDLE;
354
355 }
356 mutex_unlock(&dev->device_lock);
357 return rets;
358}
359
360
361/**
362 * mei_read - the read function.
363 *
364 * @file: pointer to file structure
365 * @ubuf: pointer to user buffer
366 * @length: buffer length
367 * @offset: data offset in buffer
368 *
369 * returns >=0 data length on success , <0 on error
370 */
371static ssize_t mei_read(struct file *file, char __user *ubuf,
372 size_t length, loff_t *offset)
373{
374 struct mei_cl *cl = file->private_data;
375 struct mei_cl_cb *cb_pos = NULL;
376 struct mei_cl_cb *cb = NULL;
377 struct mei_device *dev;
378 int i;
379 int rets;
380 int err;
381
382
383 if (WARN_ON(!cl || !cl->dev))
384 return -ENODEV;
385
386 dev = cl->dev;
387
388 mutex_lock(&dev->device_lock);
389 if (dev->mei_state != MEI_ENABLED) {
390 rets = -ENODEV;
391 goto out;
392 }
393
394 if ((cl->sm_state & MEI_WD_STATE_INDEPENDENCE_MSG_SENT) == 0) {
395 /* Do not allow to read watchdog client */
396 i = mei_find_me_client_index(dev, mei_wd_guid);
397 if (i >= 0) {
398 struct mei_me_client *me_client = &dev->me_clients[i];
399
400 if (cl->me_client_id == me_client->client_id) {
401 rets = -EBADF;
402 goto out;
403 }
404 }
405 } else {
406 cl->sm_state &= ~MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
407 }
408
409 if (cl == &dev->iamthif_cl) {
410 rets = amthi_read(dev, file, ubuf, length, offset);
411 goto out;
412 }
413
414 if (cl->read_cb && cl->read_cb->information > *offset) {
415 cb = cl->read_cb;
416 goto copy_buffer;
417 } else if (cl->read_cb && cl->read_cb->information > 0 &&
418 cl->read_cb->information <= *offset) {
419 cb = cl->read_cb;
420 rets = 0;
421 goto free;
422 } else if ((!cl->read_cb || !cl->read_cb->information) &&
423 *offset > 0) {
424 /*Offset needs to be cleaned for contiguous reads*/
425 *offset = 0;
426 rets = 0;
427 goto out;
428 }
429
430 err = mei_start_read(dev, cl);
431 if (err && err != -EBUSY) {
432 dev_dbg(&dev->pdev->dev,
433 "mei start read failure with status = %d\n", err);
434 rets = err;
435 goto out;
436 }
437
438 if (MEI_READ_COMPLETE != cl->reading_state &&
439 !waitqueue_active(&cl->rx_wait)) {
440 if (file->f_flags & O_NONBLOCK) {
441 rets = -EAGAIN;
442 goto out;
443 }
444
445 mutex_unlock(&dev->device_lock);
446
447 if (wait_event_interruptible(cl->rx_wait,
448 (MEI_READ_COMPLETE == cl->reading_state ||
449 MEI_FILE_INITIALIZING == cl->state ||
450 MEI_FILE_DISCONNECTED == cl->state ||
451 MEI_FILE_DISCONNECTING == cl->state))) {
452 if (signal_pending(current))
453 return -EINTR;
454 return -ERESTARTSYS;
455 }
456
457 mutex_lock(&dev->device_lock);
458 if (MEI_FILE_INITIALIZING == cl->state ||
459 MEI_FILE_DISCONNECTED == cl->state ||
460 MEI_FILE_DISCONNECTING == cl->state) {
461 rets = -EBUSY;
462 goto out;
463 }
464 }
465
466 cb = cl->read_cb;
467
468 if (!cb) {
469 rets = -ENODEV;
470 goto out;
471 }
472 if (cl->reading_state != MEI_READ_COMPLETE) {
473 rets = 0;
474 goto out;
475 }
476 /* now copy the data to user space */
477copy_buffer:
478 dev_dbg(&dev->pdev->dev, "cb->response_buffer size - %d\n",
479 cb->response_buffer.size);
480 dev_dbg(&dev->pdev->dev, "cb->information - %lu\n",
481 cb->information);
482 if (length == 0 || ubuf == NULL || *offset > cb->information) {
483 rets = -EMSGSIZE;
484 goto free;
485 }
486
487 /* length is being truncated to PAGE_SIZE, however, */
488 /* information size may be longer */
489 length = min_t(size_t, length, (cb->information - *offset));
490
491 if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) {
492 rets = -EFAULT;
493 goto free;
494 }
495
496 rets = length;
497 *offset += length;
498 if ((unsigned long)*offset < cb->information)
499 goto out;
500
501free:
502 cb_pos = find_read_list_entry(dev, cl);
503 /* Remove entry from read list */
504 if (cb_pos)
505 list_del(&cb_pos->cb_list);
506 mei_free_cb_private(cb);
507 cl->reading_state = MEI_IDLE;
508 cl->read_cb = NULL;
509 cl->read_pending = 0;
510out:
511 dev_dbg(&dev->pdev->dev, "end mei read rets= %d\n", rets);
512 mutex_unlock(&dev->device_lock);
513 return rets;
514}
515
516/**
517 * mei_write - the write function.
518 *
519 * @file: pointer to file structure
520 * @ubuf: pointer to user buffer
521 * @length: buffer length
522 * @offset: data offset in buffer
523 *
524 * returns >=0 data length on success , <0 on error
525 */
526static ssize_t mei_write(struct file *file, const char __user *ubuf,
527 size_t length, loff_t *offset)
528{
529 struct mei_cl *cl = file->private_data;
530 struct mei_cl_cb *write_cb = NULL;
531 struct mei_msg_hdr mei_hdr;
532 struct mei_device *dev;
533 unsigned long timeout = 0;
534 int rets;
535 int i;
536
537 if (WARN_ON(!cl || !cl->dev))
538 return -ENODEV;
539
540 dev = cl->dev;
541
542 mutex_lock(&dev->device_lock);
543
544 if (dev->mei_state != MEI_ENABLED) {
545 mutex_unlock(&dev->device_lock);
546 return -ENODEV;
547 }
548
549 if (cl == &dev->iamthif_cl) {
550 write_cb = find_amthi_read_list_entry(dev, file);
551
552 if (write_cb) {
553 timeout = write_cb->read_time +
554 msecs_to_jiffies(IAMTHIF_READ_TIMER);
555
556 if (time_after(jiffies, timeout) ||
557 cl->reading_state == MEI_READ_COMPLETE) {
558 *offset = 0;
559 list_del(&write_cb->cb_list);
560 mei_free_cb_private(write_cb);
561 write_cb = NULL;
562 }
563 }
564 }
565
566 /* free entry used in read */
567 if (cl->reading_state == MEI_READ_COMPLETE) {
568 *offset = 0;
569 write_cb = find_read_list_entry(dev, cl);
570 if (write_cb) {
571 list_del(&write_cb->cb_list);
572 mei_free_cb_private(write_cb);
573 write_cb = NULL;
574 cl->reading_state = MEI_IDLE;
575 cl->read_cb = NULL;
576 cl->read_pending = 0;
577 }
578 } else if (cl->reading_state == MEI_IDLE && !cl->read_pending)
579 *offset = 0;
580
581
582 write_cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL);
583 if (!write_cb) {
584 mutex_unlock(&dev->device_lock);
585 return -ENOMEM;
586 }
587
588 write_cb->file_object = file;
589 write_cb->file_private = cl;
590 write_cb->request_buffer.data = kmalloc(length, GFP_KERNEL);
591 rets = -ENOMEM;
592 if (!write_cb->request_buffer.data)
593 goto unlock_dev;
594
595 dev_dbg(&dev->pdev->dev, "length =%d\n", (int) length);
596
597 rets = -EFAULT;
598 if (copy_from_user(write_cb->request_buffer.data, ubuf, length))
599 goto unlock_dev;
600
601 cl->sm_state = 0;
602 if (length == 4 &&
603 ((memcmp(mei_wd_state_independence_msg[0],
604 write_cb->request_buffer.data, 4) == 0) ||
605 (memcmp(mei_wd_state_independence_msg[1],
606 write_cb->request_buffer.data, 4) == 0) ||
607 (memcmp(mei_wd_state_independence_msg[2],
608 write_cb->request_buffer.data, 4) == 0)))
609 cl->sm_state |= MEI_WD_STATE_INDEPENDENCE_MSG_SENT;
610
611 INIT_LIST_HEAD(&write_cb->cb_list);
612 if (cl == &dev->iamthif_cl) {
613 write_cb->response_buffer.data =
614 kmalloc(dev->iamthif_mtu, GFP_KERNEL);
615 if (!write_cb->response_buffer.data) {
616 rets = -ENOMEM;
617 goto unlock_dev;
618 }
619 if (dev->mei_state != MEI_ENABLED) {
620 rets = -ENODEV;
621 goto unlock_dev;
622 }
623 for (i = 0; i < dev->me_clients_num; i++) {
624 if (dev->me_clients[i].client_id ==
625 dev->iamthif_cl.me_client_id)
626 break;
627 }
628
629 if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
630 rets = -ENODEV;
631 goto unlock_dev;
632 }
633 if (i == dev->me_clients_num ||
634 (dev->me_clients[i].client_id !=
635 dev->iamthif_cl.me_client_id)) {
636 rets = -ENODEV;
637 goto unlock_dev;
638 } else if (length > dev->me_clients[i].props.max_msg_length ||
639 length <= 0) {
640 rets = -EMSGSIZE;
641 goto unlock_dev;
642 }
643
644 write_cb->response_buffer.size = dev->iamthif_mtu;
645 write_cb->major_file_operations = MEI_IOCTL;
646 write_cb->information = 0;
647 write_cb->request_buffer.size = length;
648 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) {
649 rets = -ENODEV;
650 goto unlock_dev;
651 }
652
653 if (!list_empty(&dev->amthi_cmd_list.mei_cb.cb_list) ||
654 dev->iamthif_state != MEI_IAMTHIF_IDLE) {
655 dev_dbg(&dev->pdev->dev, "amthi_state = %d\n",
656 (int) dev->iamthif_state);
657 dev_dbg(&dev->pdev->dev, "add amthi cb to amthi cmd waiting list\n");
658 list_add_tail(&write_cb->cb_list,
659 &dev->amthi_cmd_list.mei_cb.cb_list);
660 rets = length;
661 } else {
662 dev_dbg(&dev->pdev->dev, "call amthi write\n");
663 rets = amthi_write(dev, write_cb);
664
665 if (rets) {
666 dev_dbg(&dev->pdev->dev, "amthi write failed with status = %d\n",
667 rets);
668 goto unlock_dev;
669 }
670 rets = length;
671 }
672 mutex_unlock(&dev->device_lock);
673 return rets;
674 }
675
676 write_cb->major_file_operations = MEI_WRITE;
677 /* make sure information is zero before we start */
678
679 write_cb->information = 0;
680 write_cb->request_buffer.size = length;
681
682 dev_dbg(&dev->pdev->dev, "host client = %d, ME client = %d\n",
683 cl->host_client_id, cl->me_client_id);
684 if (cl->state != MEI_FILE_CONNECTED) {
685 rets = -ENODEV;
686 dev_dbg(&dev->pdev->dev, "host client = %d, is not connected to ME client = %d",
687 cl->host_client_id,
688 cl->me_client_id);
689 goto unlock_dev;
690 }
691 for (i = 0; i < dev->me_clients_num; i++) {
692 if (dev->me_clients[i].client_id ==
693 cl->me_client_id)
694 break;
695 }
696 if (WARN_ON(dev->me_clients[i].client_id != cl->me_client_id)) {
697 rets = -ENODEV;
698 goto unlock_dev;
699 }
700 if (i == dev->me_clients_num) {
701 rets = -ENODEV;
702 goto unlock_dev;
703 }
704 if (length > dev->me_clients[i].props.max_msg_length || length <= 0) {
705 rets = -EINVAL;
706 goto unlock_dev;
707 }
708 write_cb->file_private = cl;
709
710 rets = mei_flow_ctrl_creds(dev, cl);
711 if (rets < 0)
712 goto unlock_dev;
713
714 if (rets && dev->mei_host_buffer_is_empty) {
715 rets = 0;
716 dev->mei_host_buffer_is_empty = false;
717 if (length > ((((dev->host_hw_state & H_CBD) >> 24) *
718 sizeof(u32)) - sizeof(struct mei_msg_hdr))) {
719
720 mei_hdr.length =
721 (((dev->host_hw_state & H_CBD) >> 24) *
722 sizeof(u32)) -
723 sizeof(struct mei_msg_hdr);
724 mei_hdr.msg_complete = 0;
725 } else {
726 mei_hdr.length = length;
727 mei_hdr.msg_complete = 1;
728 }
729 mei_hdr.host_addr = cl->host_client_id;
730 mei_hdr.me_addr = cl->me_client_id;
731 mei_hdr.reserved = 0;
732 dev_dbg(&dev->pdev->dev, "call mei_write_message header=%08x.\n",
733 *((u32 *) &mei_hdr));
734 if (mei_write_message(dev, &mei_hdr,
735 (unsigned char *) (write_cb->request_buffer.data),
736 mei_hdr.length)) {
737 rets = -ENODEV;
738 goto unlock_dev;
739 }
740 cl->writing_state = MEI_WRITING;
741 write_cb->information = mei_hdr.length;
742 if (mei_hdr.msg_complete) {
743 if (mei_flow_ctrl_reduce(dev, cl)) {
744 rets = -ENODEV;
745 goto unlock_dev;
746 }
747 list_add_tail(&write_cb->cb_list,
748 &dev->write_waiting_list.mei_cb.cb_list);
749 } else {
750 list_add_tail(&write_cb->cb_list,
751 &dev->write_list.mei_cb.cb_list);
752 }
753
754 } else {
755
756 write_cb->information = 0;
757 cl->writing_state = MEI_WRITING;
758 list_add_tail(&write_cb->cb_list,
759 &dev->write_list.mei_cb.cb_list);
760 }
761 mutex_unlock(&dev->device_lock);
762 return length;
763
764unlock_dev:
765 mutex_unlock(&dev->device_lock);
766 mei_free_cb_private(write_cb);
767 return rets;
768}
769
770
771/**
772 * mei_ioctl - the IOCTL function
773 *
774 * @file: pointer to file structure
775 * @cmd: ioctl command
776 * @data: pointer to mei message structure
777 *
778 * returns 0 on success , <0 on error
779 */
780static long mei_ioctl(struct file *file, unsigned int cmd, unsigned long data)
781{
782 struct mei_device *dev;
783 struct mei_cl *cl = file->private_data;
784 struct mei_connect_client_data *connect_data = NULL;
785 int rets;
786
787 if (cmd != IOCTL_MEI_CONNECT_CLIENT)
788 return -EINVAL;
789
790 if (WARN_ON(!cl || !cl->dev))
791 return -ENODEV;
792
793 dev = cl->dev;
794
795 dev_dbg(&dev->pdev->dev, "IOCTL cmd = 0x%x", cmd);
796
797 mutex_lock(&dev->device_lock);
798 if (dev->mei_state != MEI_ENABLED) {
799 rets = -ENODEV;
800 goto out;
801 }
802
803 dev_dbg(&dev->pdev->dev, ": IOCTL_MEI_CONNECT_CLIENT.\n");
804
805 connect_data = kzalloc(sizeof(struct mei_connect_client_data),
806 GFP_KERNEL);
807 if (!connect_data) {
808 rets = -ENOMEM;
809 goto out;
810 }
811 dev_dbg(&dev->pdev->dev, "copy connect data from user\n");
812 if (copy_from_user(connect_data, (char __user *)data,
813 sizeof(struct mei_connect_client_data))) {
814 dev_dbg(&dev->pdev->dev, "failed to copy data from userland\n");
815 rets = -EFAULT;
816 goto out;
817 }
818 rets = mei_ioctl_connect_client(file, connect_data);
819
820 /* if all is ok, copying the data back to user. */
821 if (rets)
822 goto out;
823
824 dev_dbg(&dev->pdev->dev, "copy connect data to user\n");
825 if (copy_to_user((char __user *)data, connect_data,
826 sizeof(struct mei_connect_client_data))) {
827 dev_dbg(&dev->pdev->dev, "failed to copy data to userland\n");
828 rets = -EFAULT;
829 goto out;
830 }
831
832out:
833 kfree(connect_data);
834 mutex_unlock(&dev->device_lock);
835 return rets;
836}
837
838/**
839 * mei_compat_ioctl - the compat IOCTL function
840 *
841 * @file: pointer to file structure
842 * @cmd: ioctl command
843 * @data: pointer to mei message structure
844 *
845 * returns 0 on success , <0 on error
846 */
847#ifdef CONFIG_COMPAT
848static long mei_compat_ioctl(struct file *file,
849 unsigned int cmd, unsigned long data)
850{
851 return mei_ioctl(file, cmd, (unsigned long)compat_ptr(data));
852}
853#endif
854
855
856/**
857 * mei_poll - the poll function
858 *
859 * @file: pointer to file structure
860 * @wait: pointer to poll_table structure
861 *
862 * returns poll mask
863 */
864static unsigned int mei_poll(struct file *file, poll_table *wait)
865{
866 struct mei_cl *cl = file->private_data;
867 struct mei_device *dev;
868 unsigned int mask = 0;
869
870 if (WARN_ON(!cl || !cl->dev))
871 return mask;
872
873 dev = cl->dev;
874
875 mutex_lock(&dev->device_lock);
876
877 if (dev->mei_state != MEI_ENABLED)
878 goto out;
879
880
881 if (cl == &dev->iamthif_cl) {
882 mutex_unlock(&dev->device_lock);
883 poll_wait(file, &dev->iamthif_cl.wait, wait);
884 mutex_lock(&dev->device_lock);
885 if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE &&
886 dev->iamthif_file_object == file) {
887 mask |= (POLLIN | POLLRDNORM);
888 dev_dbg(&dev->pdev->dev, "run next amthi cb\n");
889 mei_run_next_iamthif_cmd(dev);
890 }
891 goto out;
892 }
893
894 mutex_unlock(&dev->device_lock);
895 poll_wait(file, &cl->tx_wait, wait);
896 mutex_lock(&dev->device_lock);
897 if (MEI_WRITE_COMPLETE == cl->writing_state)
898 mask |= (POLLIN | POLLRDNORM);
899
900out:
901 mutex_unlock(&dev->device_lock);
902 return mask;
903}
904
905/*
906 * file operations structure will be used for mei char device.
907 */
908static const struct file_operations mei_fops = {
909 .owner = THIS_MODULE,
910 .read = mei_read,
911 .unlocked_ioctl = mei_ioctl,
912#ifdef CONFIG_COMPAT
913 .compat_ioctl = mei_compat_ioctl,
914#endif
915 .open = mei_open,
916 .release = mei_release,
917 .write = mei_write,
918 .poll = mei_poll,
919 .llseek = no_llseek
920};
921
922
923/*
924 * Misc Device Struct
925 */
926static struct miscdevice mei_misc_device = {
927 .name = "mei",
928 .fops = &mei_fops,
929 .minor = MISC_DYNAMIC_MINOR,
930};
931
932/**
933 * mei_probe - Device Initialization Routine
934 *
935 * @pdev: PCI device structure
936 * @ent: entry in kcs_pci_tbl
937 *
938 * returns 0 on success, <0 on failure.
939 */
940static int __devinit mei_probe(struct pci_dev *pdev,
941 const struct pci_device_id *ent)
942{
943 struct mei_device *dev;
944 int err;
945
946 mutex_lock(&mei_mutex);
947 if (mei_device) {
948 err = -EEXIST;
949 goto end;
950 }
951 /* enable pci dev */
952 err = pci_enable_device(pdev);
953 if (err) {
954 dev_err(&pdev->dev, "failed to enable pci device.\n");
955 goto end;
956 }
957 /* set PCI host mastering */
958 pci_set_master(pdev);
959 /* pci request regions for mei driver */
960 err = pci_request_regions(pdev, mei_driver_name);
961 if (err) {
962 dev_err(&pdev->dev, "failed to get pci regions.\n");
963 goto disable_device;
964 }
965 /* allocates and initializes the mei dev structure */
966 dev = mei_device_init(pdev);
967 if (!dev) {
968 err = -ENOMEM;
969 goto release_regions;
970 }
971 /* mapping IO device memory */
972 dev->mem_addr = pci_iomap(pdev, 0, 0);
973 if (!dev->mem_addr) {
974 dev_err(&pdev->dev, "mapping I/O device memory failure.\n");
975 err = -ENOMEM;
976 goto free_device;
977 }
978 pci_enable_msi(pdev);
979
980 /* request and enable interrupt */
981 if (pci_dev_msi_enabled(pdev))
982 err = request_threaded_irq(pdev->irq,
983 NULL,
984 mei_interrupt_thread_handler,
985 0, mei_driver_name, dev);
986 else
987 err = request_threaded_irq(pdev->irq,
988 mei_interrupt_quick_handler,
989 mei_interrupt_thread_handler,
990 IRQF_SHARED, mei_driver_name, dev);
991
992 if (err) {
993 dev_err(&pdev->dev, "request_threaded_irq failure. irq = %d\n",
994 pdev->irq);
995 goto unmap_memory;
996 }
997 INIT_DELAYED_WORK(&dev->timer_work, mei_timer);
998 if (mei_hw_init(dev)) {
999 dev_err(&pdev->dev, "init hw failure.\n");
1000 err = -ENODEV;
1001 goto release_irq;
1002 }
1003
1004 err = misc_register(&mei_misc_device);
1005 if (err)
1006 goto release_irq;
1007
1008 mei_device = pdev;
1009 pci_set_drvdata(pdev, dev);
1010
1011
1012 schedule_delayed_work(&dev->timer_work, HZ);
1013
1014 mutex_unlock(&mei_mutex);
1015
1016 pr_debug("initialization successful.\n");
1017
1018 return 0;
1019
1020release_irq:
1021 /* disable interrupts */
1022 dev->host_hw_state = mei_hcsr_read(dev);
1023 mei_disable_interrupts(dev);
1024 flush_scheduled_work();
1025 free_irq(pdev->irq, dev);
1026 pci_disable_msi(pdev);
1027unmap_memory:
1028 pci_iounmap(pdev, dev->mem_addr);
1029free_device:
1030 kfree(dev);
1031release_regions:
1032 pci_release_regions(pdev);
1033disable_device:
1034 pci_disable_device(pdev);
1035end:
1036 mutex_unlock(&mei_mutex);
1037 dev_err(&pdev->dev, "initialization failed.\n");
1038 return err;
1039}
1040
1041/**
1042 * mei_remove - Device Removal Routine
1043 *
1044 * @pdev: PCI device structure
1045 *
1046 * mei_remove is called by the PCI subsystem to alert the driver
1047 * that it should release a PCI device.
1048 */
1049static void __devexit mei_remove(struct pci_dev *pdev)
1050{
1051 struct mei_device *dev;
1052
1053 if (mei_device != pdev)
1054 return;
1055
1056 dev = pci_get_drvdata(pdev);
1057 if (!dev)
1058 return;
1059
1060 mutex_lock(&dev->device_lock);
1061
1062 mei_wd_stop(dev, false);
1063
1064 mei_device = NULL;
1065
1066 if (dev->iamthif_cl.state == MEI_FILE_CONNECTED) {
1067 dev->iamthif_cl.state = MEI_FILE_DISCONNECTING;
1068 mei_disconnect_host_client(dev, &dev->iamthif_cl);
1069 }
1070 if (dev->wd_cl.state == MEI_FILE_CONNECTED) {
1071 dev->wd_cl.state = MEI_FILE_DISCONNECTING;
1072 mei_disconnect_host_client(dev, &dev->wd_cl);
1073 }
1074
1075 /* Unregistering watchdog device */
1076 mei_watchdog_unregister(dev);
1077
1078 /* remove entry if already in list */
1079 dev_dbg(&pdev->dev, "list del iamthif and wd file list.\n");
1080 mei_remove_client_from_file_list(dev, dev->wd_cl.host_client_id);
1081 mei_remove_client_from_file_list(dev, dev->iamthif_cl.host_client_id);
1082
1083 dev->iamthif_current_cb = NULL;
1084 dev->me_clients_num = 0;
1085
1086 mutex_unlock(&dev->device_lock);
1087
1088 flush_scheduled_work();
1089
1090 /* disable interrupts */
1091 mei_disable_interrupts(dev);
1092
1093 free_irq(pdev->irq, dev);
1094 pci_disable_msi(pdev);
1095 pci_set_drvdata(pdev, NULL);
1096
1097 if (dev->mem_addr)
1098 pci_iounmap(pdev, dev->mem_addr);
1099
1100 kfree(dev);
1101
1102 pci_release_regions(pdev);
1103 pci_disable_device(pdev);
1104}
1105#ifdef CONFIG_PM
1106static int mei_pci_suspend(struct device *device)
1107{
1108 struct pci_dev *pdev = to_pci_dev(device);
1109 struct mei_device *dev = pci_get_drvdata(pdev);
1110 int err;
1111
1112 if (!dev)
1113 return -ENODEV;
1114 mutex_lock(&dev->device_lock);
1115 /* Stop watchdog if exists */
1116 err = mei_wd_stop(dev, true);
1117 /* Set new mei state */
1118 if (dev->mei_state == MEI_ENABLED ||
1119 dev->mei_state == MEI_RECOVERING_FROM_RESET) {
1120 dev->mei_state = MEI_POWER_DOWN;
1121 mei_reset(dev, 0);
1122 }
1123 mutex_unlock(&dev->device_lock);
1124
1125 free_irq(pdev->irq, dev);
1126 pci_disable_msi(pdev);
1127
1128 return err;
1129}
1130
1131static int mei_pci_resume(struct device *device)
1132{
1133 struct pci_dev *pdev = to_pci_dev(device);
1134 struct mei_device *dev;
1135 int err;
1136
1137 dev = pci_get_drvdata(pdev);
1138 if (!dev)
1139 return -ENODEV;
1140
1141 pci_enable_msi(pdev);
1142
1143 /* request and enable interrupt */
1144 if (pci_dev_msi_enabled(pdev))
1145 err = request_threaded_irq(pdev->irq,
1146 NULL,
1147 mei_interrupt_thread_handler,
1148 0, mei_driver_name, dev);
1149 else
1150 err = request_threaded_irq(pdev->irq,
1151 mei_interrupt_quick_handler,
1152 mei_interrupt_thread_handler,
1153 IRQF_SHARED, mei_driver_name, dev);
1154
1155 if (err) {
1156 dev_err(&pdev->dev, "request_threaded_irq failed: irq = %d.\n",
1157 pdev->irq);
1158 return err;
1159 }
1160
1161 mutex_lock(&dev->device_lock);
1162 dev->mei_state = MEI_POWER_UP;
1163 mei_reset(dev, 1);
1164 mutex_unlock(&dev->device_lock);
1165
1166 /* Start timer if stopped in suspend */
1167 schedule_delayed_work(&dev->timer_work, HZ);
1168
1169 return err;
1170}
1171static SIMPLE_DEV_PM_OPS(mei_pm_ops, mei_pci_suspend, mei_pci_resume);
1172#define MEI_PM_OPS (&mei_pm_ops)
1173#else
1174#define MEI_PM_OPS NULL
1175#endif /* CONFIG_PM */
1176/*
1177 * PCI driver structure
1178 */
1179static struct pci_driver mei_driver = {
1180 .name = mei_driver_name,
1181 .id_table = mei_pci_tbl,
1182 .probe = mei_probe,
1183 .remove = __devexit_p(mei_remove),
1184 .shutdown = __devexit_p(mei_remove),
1185 .driver.pm = MEI_PM_OPS,
1186};
1187
1188/**
1189 * mei_init_module - Driver Registration Routine
1190 *
1191 * mei_init_module is the first routine called when the driver is
1192 * loaded. All it does is to register with the PCI subsystem.
1193 *
1194 * returns 0 on success, <0 on failure.
1195 */
1196static int __init mei_init_module(void)
1197{
1198 int ret;
1199
1200 pr_debug("loading.\n");
1201 /* init pci module */
1202 ret = pci_register_driver(&mei_driver);
1203 if (ret < 0)
1204 pr_err("error registering driver.\n");
1205
1206 return ret;
1207}
1208
1209module_init(mei_init_module);
1210
1211/**
1212 * mei_exit_module - Driver Exit Cleanup Routine
1213 *
1214 * mei_exit_module is called just before the driver is removed
1215 * from memory.
1216 */
1217static void __exit mei_exit_module(void)
1218{
1219 misc_deregister(&mei_misc_device);
1220 pci_unregister_driver(&mei_driver);
1221
1222 pr_debug("unloaded successfully.\n");
1223}
1224
1225module_exit(mei_exit_module);
1226
1227
1228MODULE_AUTHOR("Intel Corporation");
1229MODULE_DESCRIPTION("Intel(R) Management Engine Interface");
1230MODULE_LICENSE("GPL v2");
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h
new file mode 100644
index 00000000000..63d7ee97c5f
--- /dev/null
+++ b/drivers/misc/mei/mei_dev.h
@@ -0,0 +1,428 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16
17#ifndef _MEI_DEV_H_
18#define _MEI_DEV_H_
19
20#include <linux/types.h>
21#include <linux/watchdog.h>
22#include <linux/mei.h>
23#include "hw.h"
24
25/*
26 * watch dog definition
27 */
28#define MEI_WATCHDOG_DATA_SIZE 16
29#define MEI_START_WD_DATA_SIZE 20
30#define MEI_WD_PARAMS_SIZE 4
31#define MEI_WD_STATE_INDEPENDENCE_MSG_SENT (1 << 0)
32
33#define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32))
34
35/*
36 * MEI PCI Device object
37 */
38extern struct pci_dev *mei_device;
39
40
41/*
42 * AMTHI Client UUID
43 */
44extern const uuid_le mei_amthi_guid;
45
46/*
47 * Watchdog Client UUID
48 */
49extern const uuid_le mei_wd_guid;
50
51/*
52 * Watchdog independence state message
53 */
54extern const u8 mei_wd_state_independence_msg[3][4];
55
56/*
57 * Number of File descriptors/handles
58 * that can be opened to the driver.
59 *
60 * Limit to 253: 255 Total Clients
61 * minus internal client for AMTHI
62 * minus internal client for Watchdog
63 */
64#define MEI_MAX_OPEN_HANDLE_COUNT 253
65
66/*
67 * Number of Maximum MEI Clients
68 */
69#define MEI_CLIENTS_MAX 255
70
71/* File state */
72enum file_state {
73 MEI_FILE_INITIALIZING = 0,
74 MEI_FILE_CONNECTING,
75 MEI_FILE_CONNECTED,
76 MEI_FILE_DISCONNECTING,
77 MEI_FILE_DISCONNECTED
78};
79
80/* MEI device states */
81enum mei_states {
82 MEI_INITIALIZING = 0,
83 MEI_INIT_CLIENTS,
84 MEI_ENABLED,
85 MEI_RESETING,
86 MEI_DISABLED,
87 MEI_RECOVERING_FROM_RESET,
88 MEI_POWER_DOWN,
89 MEI_POWER_UP
90};
91
92/* init clients states*/
93enum mei_init_clients_states {
94 MEI_START_MESSAGE = 0,
95 MEI_ENUM_CLIENTS_MESSAGE,
96 MEI_CLIENT_PROPERTIES_MESSAGE
97};
98
99enum iamthif_states {
100 MEI_IAMTHIF_IDLE,
101 MEI_IAMTHIF_WRITING,
102 MEI_IAMTHIF_FLOW_CONTROL,
103 MEI_IAMTHIF_READING,
104 MEI_IAMTHIF_READ_COMPLETE
105};
106
107enum mei_file_transaction_states {
108 MEI_IDLE,
109 MEI_WRITING,
110 MEI_WRITE_COMPLETE,
111 MEI_FLOW_CONTROL,
112 MEI_READING,
113 MEI_READ_COMPLETE
114};
115
116/* MEI CB */
117enum mei_cb_major_types {
118 MEI_READ = 0,
119 MEI_WRITE,
120 MEI_IOCTL,
121 MEI_OPEN,
122 MEI_CLOSE
123};
124
125/*
126 * Intel MEI message data struct
127 */
128struct mei_message_data {
129 u32 size;
130 unsigned char *data;
131} __packed;
132
133
134struct mei_cl_cb {
135 struct list_head cb_list;
136 enum mei_cb_major_types major_file_operations;
137 void *file_private;
138 struct mei_message_data request_buffer;
139 struct mei_message_data response_buffer;
140 unsigned long information;
141 unsigned long read_time;
142 struct file *file_object;
143};
144
145/* MEI client instance carried as file->pirvate_data*/
146struct mei_cl {
147 struct list_head link;
148 struct mei_device *dev;
149 enum file_state state;
150 wait_queue_head_t tx_wait;
151 wait_queue_head_t rx_wait;
152 wait_queue_head_t wait;
153 int read_pending;
154 int status;
155 /* ID of client connected */
156 u8 host_client_id;
157 u8 me_client_id;
158 u8 mei_flow_ctrl_creds;
159 u8 timer_count;
160 enum mei_file_transaction_states reading_state;
161 enum mei_file_transaction_states writing_state;
162 int sm_state;
163 struct mei_cl_cb *read_cb;
164};
165
166struct mei_io_list {
167 struct mei_cl_cb mei_cb;
168};
169
170/* MEI private device struct */
171struct mei_device {
172 struct pci_dev *pdev; /* pointer to pci device struct */
173 /*
174 * lists of queues
175 */
176 /* array of pointers to aio lists */
177 struct mei_io_list read_list; /* driver read queue */
178 struct mei_io_list write_list; /* driver write queue */
179 struct mei_io_list write_waiting_list; /* write waiting queue */
180 struct mei_io_list ctrl_wr_list; /* managed write IOCTL list */
181 struct mei_io_list ctrl_rd_list; /* managed read IOCTL list */
182 struct mei_io_list amthi_cmd_list; /* amthi list for cmd waiting */
183
184 /* driver managed amthi list for reading completed amthi cmd data */
185 struct mei_io_list amthi_read_complete_list;
186 /*
187 * list of files
188 */
189 struct list_head file_list;
190 long open_handle_count;
191 /*
192 * memory of device
193 */
194 unsigned int mem_base;
195 unsigned int mem_length;
196 void __iomem *mem_addr;
197 /*
198 * lock for the device
199 */
200 struct mutex device_lock; /* device lock */
201 struct delayed_work timer_work; /* MEI timer delayed work (timeouts) */
202 bool recvd_msg;
203 /*
204 * hw states of host and fw(ME)
205 */
206 u32 host_hw_state;
207 u32 me_hw_state;
208 /*
209 * waiting queue for receive message from FW
210 */
211 wait_queue_head_t wait_recvd_msg;
212 wait_queue_head_t wait_stop_wd;
213
214 /*
215 * mei device states
216 */
217 enum mei_states mei_state;
218 enum mei_init_clients_states init_clients_state;
219 u16 init_clients_timer;
220 bool stop;
221 bool need_reset;
222
223 u32 extra_write_index;
224 unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; /* control messages */
225 u32 wr_msg_buf[128]; /* used for control messages */
226 u32 ext_msg_buf[8]; /* for control responses */
227 u32 rd_msg_hdr;
228
229 struct hbm_version version;
230
231 struct mei_me_client *me_clients; /* Note: memory has to be allocated */
232 DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX);
233 DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX);
234 u8 me_clients_num;
235 u8 me_client_presentation_num;
236 u8 me_client_index;
237 bool mei_host_buffer_is_empty;
238
239 struct mei_cl wd_cl;
240 bool wd_pending;
241 bool wd_stopped;
242 bool wd_bypass; /* if false, don't refresh watchdog ME client */
243 u16 wd_timeout; /* seconds ((wd_data[1] << 8) + wd_data[0]) */
244 u16 wd_due_counter;
245 unsigned char wd_data[MEI_START_WD_DATA_SIZE];
246
247
248
249 struct file *iamthif_file_object;
250 struct mei_cl iamthif_cl;
251 struct mei_cl_cb *iamthif_current_cb;
252 int iamthif_mtu;
253 unsigned long iamthif_timer;
254 u32 iamthif_stall_timer;
255 unsigned char *iamthif_msg_buf; /* Note: memory has to be allocated */
256 u32 iamthif_msg_buf_size;
257 u32 iamthif_msg_buf_index;
258 enum iamthif_states iamthif_state;
259 bool iamthif_flow_control_pending;
260 bool iamthif_ioctl;
261 bool iamthif_canceled;
262
263 bool wd_interface_reg;
264};
265
266
267/*
268 * mei init function prototypes
269 */
270struct mei_device *mei_device_init(struct pci_dev *pdev);
271void mei_reset(struct mei_device *dev, int interrupts);
272int mei_hw_init(struct mei_device *dev);
273int mei_task_initialize_clients(void *data);
274int mei_initialize_clients(struct mei_device *dev);
275int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl);
276void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id);
277void mei_host_init_iamthif(struct mei_device *dev);
278void mei_allocate_me_clients_storage(struct mei_device *dev);
279
280
281u8 mei_find_me_client_update_filext(struct mei_device *dev,
282 struct mei_cl *priv,
283 const uuid_le *cguid, u8 client_id);
284
285/*
286 * MEI IO List Functions
287 */
288void mei_io_list_init(struct mei_io_list *list);
289void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl);
290
291/*
292 * MEI ME Client Functions
293 */
294
295struct mei_cl *mei_cl_allocate(struct mei_device *dev);
296void mei_cl_init(struct mei_cl *cl, struct mei_device *dev);
297int mei_cl_flush_queues(struct mei_cl *cl);
298/**
299 * mei_cl_cmp_id - tells if file private data have same id
300 *
301 * @fe1: private data of 1. file object
302 * @fe2: private data of 2. file object
303 *
304 * returns true - if ids are the same and not NULL
305 */
306static inline bool mei_cl_cmp_id(const struct mei_cl *cl1,
307 const struct mei_cl *cl2)
308{
309 return cl1 && cl2 &&
310 (cl1->host_client_id == cl2->host_client_id) &&
311 (cl1->me_client_id == cl2->me_client_id);
312}
313
314
315
316/*
317 * MEI Host Client Functions
318 */
319void mei_host_start_message(struct mei_device *dev);
320void mei_host_enum_clients_message(struct mei_device *dev);
321int mei_host_client_properties(struct mei_device *dev);
322
323/*
324 * MEI interrupt functions prototype
325 */
326irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id);
327irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id);
328void mei_timer(struct work_struct *work);
329
330/*
331 * MEI input output function prototype
332 */
333int mei_ioctl_connect_client(struct file *file,
334 struct mei_connect_client_data *data);
335
336int mei_start_read(struct mei_device *dev, struct mei_cl *cl);
337
338int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb);
339
340int amthi_read(struct mei_device *dev, struct file *file,
341 char __user *ubuf, size_t length, loff_t *offset);
342
343struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev,
344 struct file *file);
345
346void mei_run_next_iamthif_cmd(struct mei_device *dev);
347
348void mei_free_cb_private(struct mei_cl_cb *priv_cb);
349
350int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid);
351
352/*
353 * Register Access Function
354 */
355
356/**
357 * mei_reg_read - Reads 32bit data from the mei device
358 *
359 * @dev: the device structure
360 * @offset: offset from which to read the data
361 *
362 * returns register value (u32)
363 */
364static inline u32 mei_reg_read(struct mei_device *dev, unsigned long offset)
365{
366 return ioread32(dev->mem_addr + offset);
367}
368
369/**
370 * mei_reg_write - Writes 32bit data to the mei device
371 *
372 * @dev: the device structure
373 * @offset: offset from which to write the data
374 * @value: register value to write (u32)
375 */
376static inline void mei_reg_write(struct mei_device *dev,
377 unsigned long offset, u32 value)
378{
379 iowrite32(value, dev->mem_addr + offset);
380}
381
382/**
383 * mei_hcsr_read - Reads 32bit data from the host CSR
384 *
385 * @dev: the device structure
386 *
387 * returns the byte read.
388 */
389static inline u32 mei_hcsr_read(struct mei_device *dev)
390{
391 return mei_reg_read(dev, H_CSR);
392}
393
394/**
395 * mei_mecsr_read - Reads 32bit data from the ME CSR
396 *
397 * @dev: the device structure
398 *
399 * returns ME_CSR_HA register value (u32)
400 */
401static inline u32 mei_mecsr_read(struct mei_device *dev)
402{
403 return mei_reg_read(dev, ME_CSR_HA);
404}
405
406/**
407 * get_me_cb_rw - Reads 32bit data from the mei ME_CB_RW register
408 *
409 * @dev: the device structure
410 *
411 * returns ME_CB_RW register value (u32)
412 */
413static inline u32 mei_mecbrw_read(struct mei_device *dev)
414{
415 return mei_reg_read(dev, ME_CB_RW);
416}
417
418
419/*
420 * mei interface function prototypes
421 */
422void mei_hcsr_set(struct mei_device *dev);
423void mei_csr_clear_his(struct mei_device *dev);
424
425void mei_enable_interrupts(struct mei_device *dev);
426void mei_disable_interrupts(struct mei_device *dev);
427
428#endif
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c
new file mode 100644
index 00000000000..6be5605707b
--- /dev/null
+++ b/drivers/misc/mei/wd.c
@@ -0,0 +1,379 @@
1/*
2 *
3 * Intel Management Engine Interface (Intel MEI) Linux driver
4 * Copyright (c) 2003-2012, Intel Corporation.
5 *
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,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 */
16#include <linux/kernel.h>
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/device.h>
20#include <linux/pci.h>
21#include <linux/sched.h>
22#include <linux/watchdog.h>
23
24#include "mei_dev.h"
25#include "hw.h"
26#include "interface.h"
27#include <linux/mei.h>
28
29static const u8 mei_start_wd_params[] = { 0x02, 0x12, 0x13, 0x10 };
30static const u8 mei_stop_wd_params[] = { 0x02, 0x02, 0x14, 0x10 };
31
32const u8 mei_wd_state_independence_msg[3][4] = {
33 {0x05, 0x02, 0x51, 0x10},
34 {0x05, 0x02, 0x52, 0x10},
35 {0x07, 0x02, 0x01, 0x10}
36};
37
38/*
39 * AMT Watchdog Device
40 */
41#define INTEL_AMT_WATCHDOG_ID "INTCAMT"
42
43/* UUIDs for AMT F/W clients */
44const uuid_le mei_wd_guid = UUID_LE(0x05B79A6F, 0x4628, 0x4D7F, 0x89,
45 0x9D, 0xA9, 0x15, 0x14, 0xCB,
46 0x32, 0xAB);
47
48static void mei_wd_set_start_timeout(struct mei_device *dev, u16 timeout)
49{
50 dev_dbg(&dev->pdev->dev, "wd: set timeout=%d.\n", timeout);
51 memcpy(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE);
52 memcpy(dev->wd_data + MEI_WD_PARAMS_SIZE, &timeout, sizeof(u16));
53}
54
55/**
56 * host_init_wd - mei initialization wd.
57 *
58 * @dev: the device structure
59 * returns -ENENT if wd client cannot be found
60 * -EIO if write has failed
61 */
62int mei_wd_host_init(struct mei_device *dev)
63{
64 mei_cl_init(&dev->wd_cl, dev);
65
66 /* look for WD client and connect to it */
67 dev->wd_cl.state = MEI_FILE_DISCONNECTED;
68 dev->wd_timeout = AMT_WD_DEFAULT_TIMEOUT;
69
70 /* find ME WD client */
71 mei_find_me_client_update_filext(dev, &dev->wd_cl,
72 &mei_wd_guid, MEI_WD_HOST_CLIENT_ID);
73
74 dev_dbg(&dev->pdev->dev, "wd: check client\n");
75 if (MEI_FILE_CONNECTING != dev->wd_cl.state) {
76 dev_info(&dev->pdev->dev, "wd: failed to find the client\n");
77 return -ENOENT;
78 }
79
80 if (mei_connect(dev, &dev->wd_cl)) {
81 dev_err(&dev->pdev->dev, "wd: failed to connect to the client\n");
82 dev->wd_cl.state = MEI_FILE_DISCONNECTED;
83 dev->wd_cl.host_client_id = 0;
84 return -EIO;
85 }
86 dev->wd_cl.timer_count = CONNECT_TIMEOUT;
87
88 return 0;
89}
90
91/**
92 * mei_wd_send - sends watch dog message to fw.
93 *
94 * @dev: the device structure
95 *
96 * returns 0 if success,
97 * -EIO when message send fails
98 * -EINVAL when invalid message is to be sent
99 */
100int mei_wd_send(struct mei_device *dev)
101{
102 struct mei_msg_hdr *mei_hdr;
103
104 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0];
105 mei_hdr->host_addr = dev->wd_cl.host_client_id;
106 mei_hdr->me_addr = dev->wd_cl.me_client_id;
107 mei_hdr->msg_complete = 1;
108 mei_hdr->reserved = 0;
109
110 if (!memcmp(dev->wd_data, mei_start_wd_params, MEI_WD_PARAMS_SIZE))
111 mei_hdr->length = MEI_START_WD_DATA_SIZE;
112 else if (!memcmp(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE))
113 mei_hdr->length = MEI_WD_PARAMS_SIZE;
114 else
115 return -EINVAL;
116
117 return mei_write_message(dev, mei_hdr, dev->wd_data, mei_hdr->length);
118}
119
120/**
121 * mei_wd_stop - sends watchdog stop message to fw.
122 *
123 * @dev: the device structure
124 * @preserve: indicate if to keep the timeout value
125 *
126 * returns 0 if success,
127 * -EIO when message send fails
128 * -EINVAL when invalid message is to be sent
129 */
130int mei_wd_stop(struct mei_device *dev, bool preserve)
131{
132 int ret;
133 u16 wd_timeout = dev->wd_timeout;
134
135 cancel_delayed_work(&dev->timer_work);
136 if (dev->wd_cl.state != MEI_FILE_CONNECTED || !dev->wd_timeout)
137 return 0;
138
139 dev->wd_timeout = 0;
140 dev->wd_due_counter = 0;
141 memcpy(dev->wd_data, mei_stop_wd_params, MEI_WD_PARAMS_SIZE);
142 dev->stop = true;
143
144 ret = mei_flow_ctrl_creds(dev, &dev->wd_cl);
145 if (ret < 0)
146 goto out;
147
148 if (ret && dev->mei_host_buffer_is_empty) {
149 ret = 0;
150 dev->mei_host_buffer_is_empty = false;
151
152 if (!mei_wd_send(dev)) {
153 ret = mei_flow_ctrl_reduce(dev, &dev->wd_cl);
154 if (ret)
155 goto out;
156 } else {
157 dev_err(&dev->pdev->dev, "wd: send stop failed\n");
158 }
159
160 dev->wd_pending = false;
161 } else {
162 dev->wd_pending = true;
163 }
164 dev->wd_stopped = false;
165 mutex_unlock(&dev->device_lock);
166
167 ret = wait_event_interruptible_timeout(dev->wait_stop_wd,
168 dev->wd_stopped, 10 * HZ);
169 mutex_lock(&dev->device_lock);
170 if (dev->wd_stopped) {
171 dev_dbg(&dev->pdev->dev, "wd: stop completed ret=%d.\n", ret);
172 ret = 0;
173 } else {
174 if (!ret)
175 ret = -ETIMEDOUT;
176 dev_warn(&dev->pdev->dev,
177 "wd: stop failed to complete ret=%d.\n", ret);
178 }
179
180 if (preserve)
181 dev->wd_timeout = wd_timeout;
182
183out:
184 return ret;
185}
186
187/*
188 * mei_wd_ops_start - wd start command from the watchdog core.
189 *
190 * @wd_dev - watchdog device struct
191 *
192 * returns 0 if success, negative errno code for failure
193 */
194static int mei_wd_ops_start(struct watchdog_device *wd_dev)
195{
196 int err = -ENODEV;
197 struct mei_device *dev;
198
199 dev = pci_get_drvdata(mei_device);
200 if (!dev)
201 return -ENODEV;
202
203 mutex_lock(&dev->device_lock);
204
205 if (dev->mei_state != MEI_ENABLED) {
206 dev_dbg(&dev->pdev->dev,
207 "wd: mei_state != MEI_ENABLED mei_state = %d\n",
208 dev->mei_state);
209 goto end_unlock;
210 }
211
212 if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
213 dev_dbg(&dev->pdev->dev,
214 "MEI Driver is not connected to Watchdog Client\n");
215 goto end_unlock;
216 }
217
218 mei_wd_set_start_timeout(dev, dev->wd_timeout);
219
220 err = 0;
221end_unlock:
222 mutex_unlock(&dev->device_lock);
223 return err;
224}
225
226/*
227 * mei_wd_ops_stop - wd stop command from the watchdog core.
228 *
229 * @wd_dev - watchdog device struct
230 *
231 * returns 0 if success, negative errno code for failure
232 */
233static int mei_wd_ops_stop(struct watchdog_device *wd_dev)
234{
235 struct mei_device *dev;
236 dev = pci_get_drvdata(mei_device);
237
238 if (!dev)
239 return -ENODEV;
240
241 mutex_lock(&dev->device_lock);
242 mei_wd_stop(dev, false);
243 mutex_unlock(&dev->device_lock);
244
245 return 0;
246}
247
248/*
249 * mei_wd_ops_ping - wd ping command from the watchdog core.
250 *
251 * @wd_dev - watchdog device struct
252 *
253 * returns 0 if success, negative errno code for failure
254 */
255static int mei_wd_ops_ping(struct watchdog_device *wd_dev)
256{
257 int ret = 0;
258 struct mei_device *dev;
259 dev = pci_get_drvdata(mei_device);
260
261 if (!dev)
262 return -ENODEV;
263
264 mutex_lock(&dev->device_lock);
265
266 if (dev->wd_cl.state != MEI_FILE_CONNECTED) {
267 dev_err(&dev->pdev->dev, "wd: not connected.\n");
268 ret = -ENODEV;
269 goto end;
270 }
271
272 /* Check if we can send the ping to HW*/
273 if (dev->mei_host_buffer_is_empty &&
274 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
275
276 dev->mei_host_buffer_is_empty = false;
277 dev_dbg(&dev->pdev->dev, "wd: sending ping\n");
278
279 if (mei_wd_send(dev)) {
280 dev_err(&dev->pdev->dev, "wd: send failed.\n");
281 ret = -EIO;
282 goto end;
283 }
284
285 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) {
286 dev_err(&dev->pdev->dev,
287 "wd: mei_flow_ctrl_reduce() failed.\n");
288 ret = -EIO;
289 goto end;
290 }
291
292 } else {
293 dev->wd_pending = true;
294 }
295
296end:
297 mutex_unlock(&dev->device_lock);
298 return ret;
299}
300
301/*
302 * mei_wd_ops_set_timeout - wd set timeout command from the watchdog core.
303 *
304 * @wd_dev - watchdog device struct
305 * @timeout - timeout value to set
306 *
307 * returns 0 if success, negative errno code for failure
308 */
309static int mei_wd_ops_set_timeout(struct watchdog_device *wd_dev, unsigned int timeout)
310{
311 struct mei_device *dev;
312 dev = pci_get_drvdata(mei_device);
313
314 if (!dev)
315 return -ENODEV;
316
317 /* Check Timeout value */
318 if (timeout < AMT_WD_MIN_TIMEOUT || timeout > AMT_WD_MAX_TIMEOUT)
319 return -EINVAL;
320
321 mutex_lock(&dev->device_lock);
322
323 dev->wd_timeout = timeout;
324 wd_dev->timeout = timeout;
325 mei_wd_set_start_timeout(dev, dev->wd_timeout);
326
327 mutex_unlock(&dev->device_lock);
328
329 return 0;
330}
331
332/*
333 * Watchdog Device structs
334 */
335static const struct watchdog_ops wd_ops = {
336 .owner = THIS_MODULE,
337 .start = mei_wd_ops_start,
338 .stop = mei_wd_ops_stop,
339 .ping = mei_wd_ops_ping,
340 .set_timeout = mei_wd_ops_set_timeout,
341};
342static const struct watchdog_info wd_info = {
343 .identity = INTEL_AMT_WATCHDOG_ID,
344 .options = WDIOF_KEEPALIVEPING,
345};
346
347static struct watchdog_device amt_wd_dev = {
348 .info = &wd_info,
349 .ops = &wd_ops,
350 .timeout = AMT_WD_DEFAULT_TIMEOUT,
351 .min_timeout = AMT_WD_MIN_TIMEOUT,
352 .max_timeout = AMT_WD_MAX_TIMEOUT,
353};
354
355
356void mei_watchdog_register(struct mei_device *dev)
357{
358 dev_dbg(&dev->pdev->dev, "dev->wd_timeout =%d.\n", dev->wd_timeout);
359
360 dev->wd_due_counter = !!dev->wd_timeout;
361
362 if (watchdog_register_device(&amt_wd_dev)) {
363 dev_err(&dev->pdev->dev,
364 "wd: unable to register watchdog device.\n");
365 dev->wd_interface_reg = false;
366 } else {
367 dev_dbg(&dev->pdev->dev,
368 "wd: successfully register watchdog interface.\n");
369 dev->wd_interface_reg = true;
370 }
371}
372
373void mei_watchdog_unregister(struct mei_device *dev)
374{
375 if (dev->wd_interface_reg)
376 watchdog_unregister_device(&amt_wd_dev);
377 dev->wd_interface_reg = false;
378}
379