Commit | Line | Data |
---|---|---|
ab841160 OW |
1 | /* |
2 | * | |
3 | * Intel Management Engine Interface (Intel MEI) Linux driver | |
733ba91c | 4 | * Copyright (c) 2003-2012, Intel Corporation. |
ab841160 OW |
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> | |
fdd9b865 | 21 | #include <linux/cdev.h> |
744f0f2f | 22 | #include <linux/poll.h> |
4f3afe1d | 23 | #include <linux/mei.h> |
e5354107 | 24 | #include <linux/mei_cl_bus.h> |
66ef5ea9 | 25 | |
ab841160 | 26 | #include "hw.h" |
9b0d5efc | 27 | #include "hbm.h" |
ab841160 | 28 | |
9ce178e5 | 29 | |
ab841160 OW |
30 | /* |
31 | * AMTHI Client UUID | |
32 | */ | |
1a1aca42 | 33 | extern const uuid_le mei_amthif_guid; |
ab841160 | 34 | |
fdd9b865 | 35 | #define MEI_RD_MSG_BUF_SIZE (128 * sizeof(u32)) |
ab841160 | 36 | |
1e2776c3 TW |
37 | /* |
38 | * Number of Maximum MEI Clients | |
39 | */ | |
40 | #define MEI_CLIENTS_MAX 256 | |
41 | ||
6adb8efb TW |
42 | /* |
43 | * maximum number of consecutive resets | |
44 | */ | |
45 | #define MEI_MAX_CONSEC_RESET 3 | |
46 | ||
ab841160 OW |
47 | /* |
48 | * Number of File descriptors/handles | |
49 | * that can be opened to the driver. | |
50 | * | |
781d0d89 | 51 | * Limit to 255: 256 Total Clients |
83ce0741 | 52 | * minus internal client for MEI Bus Messages |
ab841160 | 53 | */ |
781d0d89 | 54 | #define MEI_MAX_OPEN_HANDLE_COUNT (MEI_CLIENTS_MAX - 1) |
ab841160 | 55 | |
ab841160 OW |
56 | /* File state */ |
57 | enum file_state { | |
58 | MEI_FILE_INITIALIZING = 0, | |
59 | MEI_FILE_CONNECTING, | |
60 | MEI_FILE_CONNECTED, | |
61 | MEI_FILE_DISCONNECTING, | |
3c666182 | 62 | MEI_FILE_DISCONNECT_REPLY, |
18901357 | 63 | MEI_FILE_DISCONNECT_REQUIRED, |
3c666182 | 64 | MEI_FILE_DISCONNECTED, |
ab841160 OW |
65 | }; |
66 | ||
67 | /* MEI device states */ | |
b210d750 TW |
68 | enum mei_dev_state { |
69 | MEI_DEV_INITIALIZING = 0, | |
70 | MEI_DEV_INIT_CLIENTS, | |
71 | MEI_DEV_ENABLED, | |
0cfee51c | 72 | MEI_DEV_RESETTING, |
b210d750 | 73 | MEI_DEV_DISABLED, |
b210d750 TW |
74 | MEI_DEV_POWER_DOWN, |
75 | MEI_DEV_POWER_UP | |
ab841160 OW |
76 | }; |
77 | ||
b210d750 TW |
78 | const char *mei_dev_state_str(int state); |
79 | ||
ab841160 OW |
80 | enum iamthif_states { |
81 | MEI_IAMTHIF_IDLE, | |
82 | MEI_IAMTHIF_WRITING, | |
83 | MEI_IAMTHIF_FLOW_CONTROL, | |
84 | MEI_IAMTHIF_READING, | |
85 | MEI_IAMTHIF_READ_COMPLETE | |
86 | }; | |
87 | ||
88 | enum mei_file_transaction_states { | |
89 | MEI_IDLE, | |
90 | MEI_WRITING, | |
91 | MEI_WRITE_COMPLETE, | |
92 | MEI_FLOW_CONTROL, | |
93 | MEI_READING, | |
94 | MEI_READ_COMPLETE | |
95 | }; | |
96 | ||
4b8960b4 TW |
97 | /** |
98 | * enum mei_cb_file_ops - file operation associated with the callback | |
ce23139c AU |
99 | * @MEI_FOP_READ: read |
100 | * @MEI_FOP_WRITE: write | |
101 | * @MEI_FOP_CONNECT: connect | |
102 | * @MEI_FOP_DISCONNECT: disconnect | |
103 | * @MEI_FOP_DISCONNECT_RSP: disconnect response | |
965ae37a TW |
104 | * @MEI_FOP_NOTIFY_START: start notification |
105 | * @MEI_FOP_NOTIFY_STOP: stop notification | |
4b8960b4 TW |
106 | */ |
107 | enum mei_cb_file_ops { | |
108 | MEI_FOP_READ = 0, | |
109 | MEI_FOP_WRITE, | |
02a7eecc | 110 | MEI_FOP_CONNECT, |
5a8373fb | 111 | MEI_FOP_DISCONNECT, |
6bb948c9 | 112 | MEI_FOP_DISCONNECT_RSP, |
965ae37a TW |
113 | MEI_FOP_NOTIFY_START, |
114 | MEI_FOP_NOTIFY_STOP, | |
ab841160 OW |
115 | }; |
116 | ||
117 | /* | |
118 | * Intel MEI message data struct | |
119 | */ | |
4234a6de | 120 | struct mei_msg_data { |
f862b6b2 | 121 | size_t size; |
edf1eed4 | 122 | unsigned char *data; |
f060939d | 123 | }; |
ab841160 | 124 | |
04dd3661 | 125 | /* Maximum number of processed FW status registers */ |
edca5ea3 AU |
126 | #define MEI_FW_STATUS_MAX 6 |
127 | /* Minimal buffer for FW status string (8 bytes in dw + space or '\0') */ | |
128 | #define MEI_FW_STATUS_STR_SZ (MEI_FW_STATUS_MAX * (8 + 1)) | |
129 | ||
04dd3661 AU |
130 | |
131 | /* | |
132 | * struct mei_fw_status - storage of FW status data | |
133 | * | |
a8605ea2 AU |
134 | * @count: number of actually available elements in array |
135 | * @status: FW status registers | |
04dd3661 AU |
136 | */ |
137 | struct mei_fw_status { | |
138 | int count; | |
139 | u32 status[MEI_FW_STATUS_MAX]; | |
140 | }; | |
141 | ||
db7da79d TW |
142 | /** |
143 | * struct mei_me_client - representation of me (fw) client | |
144 | * | |
a8605ea2 | 145 | * @list: link in me client list |
79563db9 | 146 | * @refcnt: struct reference count |
a8605ea2 AU |
147 | * @props: client properties |
148 | * @client_id: me client id | |
149 | * @mei_flow_ctrl_creds: flow control credits | |
a03d77f6 | 150 | * @connect_count: number connections to this client |
0ff0a8d8 | 151 | * @bus_added: added to bus |
db7da79d TW |
152 | */ |
153 | struct mei_me_client { | |
5ca2d388 | 154 | struct list_head list; |
79563db9 | 155 | struct kref refcnt; |
db7da79d TW |
156 | struct mei_client_properties props; |
157 | u8 client_id; | |
158 | u8 mei_flow_ctrl_creds; | |
a03d77f6 | 159 | u8 connect_count; |
0ff0a8d8 | 160 | u8 bus_added; |
db7da79d TW |
161 | }; |
162 | ||
ab841160 | 163 | |
db3ed431 TW |
164 | struct mei_cl; |
165 | ||
4b8960b4 | 166 | /** |
db3ed431 TW |
167 | * struct mei_cl_cb - file operation callback structure |
168 | * | |
a8605ea2 AU |
169 | * @list: link in callback queue |
170 | * @cl: file client who is running this operation | |
171 | * @fop_type: file operation type | |
5db7514d | 172 | * @buf: buffer for data associated with the callback |
ce23139c | 173 | * @buf_idx: last read index |
62e8e6ad | 174 | * @fp: pointer to file structure |
3d33ff24 | 175 | * @status: io status of the cb |
ce23139c | 176 | * @internal: communication between driver and FW flag |
8660172e | 177 | * @completed: the transfer or reception has completed |
db3ed431 | 178 | */ |
ab841160 | 179 | struct mei_cl_cb { |
fb601adb | 180 | struct list_head list; |
db3ed431 | 181 | struct mei_cl *cl; |
4b8960b4 | 182 | enum mei_cb_file_ops fop_type; |
5db7514d | 183 | struct mei_msg_data buf; |
f862b6b2 | 184 | size_t buf_idx; |
62e8e6ad | 185 | const struct file *fp; |
3d33ff24 | 186 | int status; |
479327fc | 187 | u32 internal:1; |
8660172e | 188 | u32 completed:1; |
ab841160 OW |
189 | }; |
190 | ||
ce23139c AU |
191 | /** |
192 | * struct mei_cl - me client host representation | |
193 | * carried in file->private_data | |
194 | * | |
195 | * @link: link in the clients list | |
196 | * @dev: mei parent device | |
197 | * @state: file operation state | |
198 | * @tx_wait: wait queue for tx completion | |
199 | * @rx_wait: wait queue for rx completion | |
200 | * @wait: wait queue for management operation | |
b38a362f | 201 | * @ev_wait: notification wait queue |
237092bf | 202 | * @ev_async: event async notification |
ce23139c | 203 | * @status: connection status |
d49ed64a | 204 | * @me_cl: fw client connected |
ce23139c | 205 | * @host_client_id: host id |
ce23139c AU |
206 | * @mei_flow_ctrl_creds: transmit flow credentials |
207 | * @timer_count: watchdog timer for operation completion | |
d49ed64a | 208 | * @reserved: reserved for alignment |
965ae37a TW |
209 | * @notify_en: notification - enabled/disabled |
210 | * @notify_ev: pending notification event | |
ce23139c | 211 | * @writing_state: state of the tx |
a9bed610 TW |
212 | * @rd_pending: pending read credits |
213 | * @rd_completed: completed read | |
ce23139c | 214 | * |
b37719c3 | 215 | * @cldev: device on the mei client bus |
ce23139c | 216 | */ |
ab841160 OW |
217 | struct mei_cl { |
218 | struct list_head link; | |
219 | struct mei_device *dev; | |
220 | enum file_state state; | |
221 | wait_queue_head_t tx_wait; | |
222 | wait_queue_head_t rx_wait; | |
223 | wait_queue_head_t wait; | |
b38a362f | 224 | wait_queue_head_t ev_wait; |
237092bf | 225 | struct fasync_struct *ev_async; |
ab841160 | 226 | int status; |
d49ed64a | 227 | struct mei_me_client *me_cl; |
ab841160 | 228 | u8 host_client_id; |
ab841160 OW |
229 | u8 mei_flow_ctrl_creds; |
230 | u8 timer_count; | |
d49ed64a | 231 | u8 reserved; |
965ae37a TW |
232 | u8 notify_en; |
233 | u8 notify_ev; | |
ab841160 | 234 | enum mei_file_transaction_states writing_state; |
a9bed610 TW |
235 | struct list_head rd_pending; |
236 | struct list_head rd_completed; | |
a7b71bc0 | 237 | |
b37719c3 | 238 | struct mei_cl_device *cldev; |
ab841160 OW |
239 | }; |
240 | ||
99c2658f AU |
241 | /** |
242 | * struct mei_hw_ops - hw specific ops | |
827eef51 | 243 | * |
a8605ea2 | 244 | * @host_is_ready : query for host readiness |
99c2658f | 245 | * |
a8605ea2 AU |
246 | * @hw_is_ready : query if hw is ready |
247 | * @hw_reset : reset hw | |
248 | * @hw_start : start hw after reset | |
249 | * @hw_config : configure hw | |
99c2658f | 250 | * |
a8605ea2 AU |
251 | * @fw_status : get fw status registers |
252 | * @pg_state : power gating state of the device | |
3dc196ea | 253 | * @pg_in_transition : is device now in pg transition |
a8605ea2 | 254 | * @pg_is_enabled : is power gating enabled |
99c2658f | 255 | * |
a8605ea2 AU |
256 | * @intr_clear : clear pending interrupts |
257 | * @intr_enable : enable interrupts | |
258 | * @intr_disable : disable interrupts | |
99c2658f | 259 | * |
a8605ea2 AU |
260 | * @hbuf_free_slots : query for write buffer empty slots |
261 | * @hbuf_is_ready : query if write buffer is empty | |
262 | * @hbuf_max_len : query for write buffer max len | |
99c2658f | 263 | * |
a8605ea2 | 264 | * @write : write a message to FW |
99c2658f | 265 | * |
a8605ea2 | 266 | * @rdbuf_full_slots : query how many slots are filled |
99c2658f | 267 | * |
a8605ea2 AU |
268 | * @read_hdr : get first 4 bytes (header) |
269 | * @read : read a buffer from the FW | |
827eef51 TW |
270 | */ |
271 | struct mei_hw_ops { | |
272 | ||
d63b3095 | 273 | bool (*host_is_ready)(struct mei_device *dev); |
827eef51 | 274 | |
d63b3095 TW |
275 | bool (*hw_is_ready)(struct mei_device *dev); |
276 | int (*hw_reset)(struct mei_device *dev, bool enable); | |
277 | int (*hw_start)(struct mei_device *dev); | |
278 | void (*hw_config)(struct mei_device *dev); | |
827eef51 | 279 | |
1bd30b6a TW |
280 | |
281 | int (*fw_status)(struct mei_device *dev, struct mei_fw_status *fw_sts); | |
964a2331 | 282 | enum mei_pg_state (*pg_state)(struct mei_device *dev); |
3dc196ea | 283 | bool (*pg_in_transition)(struct mei_device *dev); |
ee7e5afd TW |
284 | bool (*pg_is_enabled)(struct mei_device *dev); |
285 | ||
d63b3095 TW |
286 | void (*intr_clear)(struct mei_device *dev); |
287 | void (*intr_enable)(struct mei_device *dev); | |
288 | void (*intr_disable)(struct mei_device *dev); | |
827eef51 | 289 | |
d63b3095 TW |
290 | int (*hbuf_free_slots)(struct mei_device *dev); |
291 | bool (*hbuf_is_ready)(struct mei_device *dev); | |
292 | size_t (*hbuf_max_len)(const struct mei_device *dev); | |
827eef51 TW |
293 | |
294 | int (*write)(struct mei_device *dev, | |
295 | struct mei_msg_hdr *hdr, | |
296 | unsigned char *buf); | |
297 | ||
298 | int (*rdbuf_full_slots)(struct mei_device *dev); | |
299 | ||
300 | u32 (*read_hdr)(const struct mei_device *dev); | |
d63b3095 | 301 | int (*read)(struct mei_device *dev, |
827eef51 TW |
302 | unsigned char *buf, unsigned long len); |
303 | }; | |
304 | ||
e5354107 | 305 | /* MEI bus API*/ |
6009595a | 306 | void mei_cl_bus_rescan(struct mei_device *bus); |
a816a00e | 307 | void mei_cl_bus_rescan_work(struct work_struct *work); |
ae48d74d | 308 | void mei_cl_bus_dev_fixup(struct mei_cl_device *dev); |
be9b720a TW |
309 | ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length, |
310 | bool blocking); | |
39db74ce | 311 | ssize_t __mei_cl_recv(struct mei_cl *cl, u8 *buf, size_t length); |
a1f9ae2b | 312 | bool mei_cl_bus_rx_event(struct mei_cl *cl); |
850f8940 | 313 | bool mei_cl_bus_notify_event(struct mei_cl *cl); |
b37719c3 | 314 | void mei_cl_bus_remove_devices(struct mei_device *bus); |
cf3baefb SO |
315 | int mei_cl_bus_init(void); |
316 | void mei_cl_bus_exit(void); | |
317 | ||
ce23139c | 318 | /** |
964a2331 TW |
319 | * enum mei_pg_event - power gating transition events |
320 | * | |
321 | * @MEI_PG_EVENT_IDLE: the driver is not in power gating transition | |
322 | * @MEI_PG_EVENT_WAIT: the driver is waiting for a pg event to complete | |
323 | * @MEI_PG_EVENT_RECEIVED: the driver received pg event | |
3dc196ea AU |
324 | * @MEI_PG_EVENT_INTR_WAIT: the driver is waiting for a pg event interrupt |
325 | * @MEI_PG_EVENT_INTR_RECEIVED: the driver received pg event interrupt | |
964a2331 TW |
326 | */ |
327 | enum mei_pg_event { | |
328 | MEI_PG_EVENT_IDLE, | |
329 | MEI_PG_EVENT_WAIT, | |
330 | MEI_PG_EVENT_RECEIVED, | |
3dc196ea AU |
331 | MEI_PG_EVENT_INTR_WAIT, |
332 | MEI_PG_EVENT_INTR_RECEIVED, | |
964a2331 TW |
333 | }; |
334 | ||
335 | /** | |
336 | * enum mei_pg_state - device internal power gating state | |
337 | * | |
338 | * @MEI_PG_OFF: device is not power gated - it is active | |
339 | * @MEI_PG_ON: device is power gated - it is in lower power state | |
340 | */ | |
341 | enum mei_pg_state { | |
342 | MEI_PG_OFF = 0, | |
343 | MEI_PG_ON = 1, | |
344 | }; | |
345 | ||
1beeb4b9 AU |
346 | const char *mei_pg_state_str(enum mei_pg_state state); |
347 | ||
24aadc80 | 348 | /** |
5fb54fb4 | 349 | * struct mei_device - MEI private device struct |
ce23139c | 350 | * |
a8605ea2 AU |
351 | * @dev : device on a bus |
352 | * @cdev : character device | |
353 | * @minor : minor number allocated for device | |
f3d8e878 | 354 | * |
ce23139c AU |
355 | * @write_list : write pending list |
356 | * @write_waiting_list : write completion list | |
357 | * @ctrl_wr_list : pending control write list | |
358 | * @ctrl_rd_list : pending control read list | |
bae1cc7d | 359 | * |
ce23139c AU |
360 | * @file_list : list of opened handles |
361 | * @open_handle_count: number of opened handles | |
362 | * | |
363 | * @device_lock : big device lock | |
364 | * @timer_work : MEI timer delayed work (timeouts) | |
365 | * | |
366 | * @recvd_hw_ready : hw ready message received flag | |
367 | * | |
368 | * @wait_hw_ready : wait queue for receive HW ready message form FW | |
369 | * @wait_pg : wait queue for receive PG message from FW | |
370 | * @wait_hbm_start : wait queue for receive HBM start message from FW | |
ce23139c AU |
371 | * |
372 | * @reset_count : number of consecutive resets | |
373 | * @dev_state : device state | |
374 | * @hbm_state : state of host bus message protocol | |
375 | * @init_clients_timer : HBM init handshake timeout | |
bae1cc7d | 376 | * |
a8605ea2 | 377 | * @pg_event : power gating event |
ce23139c AU |
378 | * @pg_domain : runtime PM domain |
379 | * | |
380 | * @rd_msg_buf : control messages buffer | |
381 | * @rd_msg_hdr : read message header storage | |
382 | * | |
a8605ea2 AU |
383 | * @hbuf_depth : depth of hardware host/write buffer is slots |
384 | * @hbuf_is_ready : query if the host host/write buffer is ready | |
385 | * @wr_msg : the buffer for hbm control messages | |
ce23139c AU |
386 | * |
387 | * @version : HBM protocol version in use | |
18901357 AU |
388 | * @hbm_f_pg_supported : hbm feature pgi protocol |
389 | * @hbm_f_dc_supported : hbm feature dynamic clients | |
390 | * @hbm_f_dot_supported : hbm feature disconnect on timeout | |
4d99877d | 391 | * @hbm_f_ev_supported : hbm feature event notification |
f4e06246 | 392 | * @hbm_f_fa_supported : hbm feature fixed address client |
ce23139c | 393 | * |
b7d88514 | 394 | * @me_clients_rwsem: rw lock over me_clients list |
ce23139c AU |
395 | * @me_clients : list of FW clients |
396 | * @me_clients_map : FW clients bit map | |
397 | * @host_clients_map : host clients id pool | |
398 | * @me_client_index : last FW client index in enumeration | |
399 | * | |
eeabfcf5 | 400 | * @allow_fixed_address: allow user space to connect a fixed client |
f4e06246 | 401 | * @override_fixed_address: force allow fixed address behavior |
eeabfcf5 | 402 | * |
ce23139c | 403 | * @amthif_cmd_list : amthif list for cmd waiting |
62e8e6ad | 404 | * @iamthif_fp : file for current amthif operation |
ce23139c AU |
405 | * @iamthif_cl : amthif host client |
406 | * @iamthif_current_cb : amthif current operation callback | |
407 | * @iamthif_open_count : number of opened amthif connections | |
ce23139c | 408 | * @iamthif_stall_timer : timer to detect amthif hang |
ce23139c | 409 | * @iamthif_state : amthif processor state |
ce23139c AU |
410 | * @iamthif_canceled : current amthif command is canceled |
411 | * | |
412 | * @init_work : work item for the device init | |
413 | * @reset_work : work item for the device reset | |
a816a00e | 414 | * @bus_rescan_work : work item for the bus rescan |
ce23139c AU |
415 | * |
416 | * @device_list : mei client bus list | |
0ff0a8d8 | 417 | * @cl_bus_lock : client bus list lock |
ce23139c AU |
418 | * |
419 | * @dbgfs_dir : debugfs mei root directory | |
420 | * | |
421 | * @ops: : hw specific operations | |
422 | * @hw : hw specific data | |
24aadc80 | 423 | */ |
ab841160 | 424 | struct mei_device { |
3a7e9b6c | 425 | struct device *dev; |
f3d8e878 AU |
426 | struct cdev cdev; |
427 | int minor; | |
428 | ||
ce23139c AU |
429 | struct mei_cl_cb write_list; |
430 | struct mei_cl_cb write_waiting_list; | |
431 | struct mei_cl_cb ctrl_wr_list; | |
432 | struct mei_cl_cb ctrl_rd_list; | |
ab841160 | 433 | |
ab841160 | 434 | struct list_head file_list; |
eb9af0ac | 435 | long open_handle_count; |
fecb0d58 | 436 | |
ce23139c AU |
437 | struct mutex device_lock; |
438 | struct delayed_work timer_work; | |
aafae7ec TW |
439 | |
440 | bool recvd_hw_ready; | |
ab841160 OW |
441 | /* |
442 | * waiting queue for receive message from FW | |
443 | */ | |
aafae7ec | 444 | wait_queue_head_t wait_hw_ready; |
4fcbc99b | 445 | wait_queue_head_t wait_pg; |
cb02efc3 | 446 | wait_queue_head_t wait_hbm_start; |
ab841160 OW |
447 | |
448 | /* | |
449 | * mei device states | |
450 | */ | |
6adb8efb | 451 | unsigned long reset_count; |
b210d750 | 452 | enum mei_dev_state dev_state; |
9b0d5efc | 453 | enum mei_hbm_state hbm_state; |
ab841160 | 454 | u16 init_clients_timer; |
ab841160 | 455 | |
964a2331 TW |
456 | /* |
457 | * Power Gating support | |
458 | */ | |
459 | enum mei_pg_event pg_event; | |
bbd6d050 | 460 | #ifdef CONFIG_PM |
e13fa90c | 461 | struct dev_pm_domain pg_domain; |
bbd6d050 | 462 | #endif /* CONFIG_PM */ |
964a2331 | 463 | |
ce23139c | 464 | unsigned char rd_msg_buf[MEI_RD_MSG_BUF_SIZE]; |
ab841160 | 465 | u32 rd_msg_hdr; |
e46f1874 | 466 | |
330dd7da TW |
467 | /* write buffer */ |
468 | u8 hbuf_depth; | |
469 | bool hbuf_is_ready; | |
470 | ||
e46f1874 TW |
471 | /* used for control messages */ |
472 | struct { | |
473 | struct mei_msg_hdr hdr; | |
474 | unsigned char data[128]; | |
475 | } wr_msg; | |
476 | ||
ab841160 | 477 | struct hbm_version version; |
bae1cc7d | 478 | unsigned int hbm_f_pg_supported:1; |
70ef835c | 479 | unsigned int hbm_f_dc_supported:1; |
18901357 | 480 | unsigned int hbm_f_dot_supported:1; |
4d99877d | 481 | unsigned int hbm_f_ev_supported:1; |
f4e06246 | 482 | unsigned int hbm_f_fa_supported:1; |
ab841160 | 483 | |
b7d88514 | 484 | struct rw_semaphore me_clients_rwsem; |
5ca2d388 | 485 | struct list_head me_clients; |
ab841160 OW |
486 | DECLARE_BITMAP(me_clients_map, MEI_CLIENTS_MAX); |
487 | DECLARE_BITMAP(host_clients_map, MEI_CLIENTS_MAX); | |
1aee351a | 488 | unsigned long me_client_index; |
ab841160 | 489 | |
621a5f7a | 490 | bool allow_fixed_address; |
f4e06246 | 491 | bool override_fixed_address; |
eeabfcf5 | 492 | |
e773efc4 TW |
493 | /* amthif list for cmd waiting */ |
494 | struct mei_cl_cb amthif_cmd_list; | |
495 | /* driver managed amthif list for reading completed amthif cmd data */ | |
62e8e6ad | 496 | const struct file *iamthif_fp; |
ab841160 | 497 | struct mei_cl iamthif_cl; |
eb9af0ac | 498 | struct mei_cl_cb *iamthif_current_cb; |
22f96a0e | 499 | long iamthif_open_count; |
ab841160 | 500 | u32 iamthif_stall_timer; |
ab841160 | 501 | enum iamthif_states iamthif_state; |
eb9af0ac | 502 | bool iamthif_canceled; |
c1174c0e SO |
503 | |
504 | struct work_struct init_work; | |
544f9460 | 505 | struct work_struct reset_work; |
a816a00e | 506 | struct work_struct bus_rescan_work; |
827eef51 | 507 | |
a7b71bc0 SO |
508 | /* List of bus devices */ |
509 | struct list_head device_list; | |
0ff0a8d8 | 510 | struct mutex cl_bus_lock; |
a7b71bc0 | 511 | |
30e53bb8 TW |
512 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
513 | struct dentry *dbgfs_dir; | |
514 | #endif /* CONFIG_DEBUG_FS */ | |
515 | ||
516 | ||
827eef51 | 517 | const struct mei_hw_ops *ops; |
52c34561 | 518 | char hw[0] __aligned(sizeof(void *)); |
ab841160 OW |
519 | }; |
520 | ||
3870c320 TW |
521 | static inline unsigned long mei_secs_to_jiffies(unsigned long sec) |
522 | { | |
523 | return msecs_to_jiffies(sec * MSEC_PER_SEC); | |
524 | } | |
525 | ||
c8c8d080 TW |
526 | /** |
527 | * mei_data2slots - get slots - number of (dwords) from a message length | |
528 | * + size of the mei header | |
ce23139c | 529 | * |
a8605ea2 AU |
530 | * @length: size of the messages in bytes |
531 | * | |
532 | * Return: number of slots | |
c8c8d080 TW |
533 | */ |
534 | static inline u32 mei_data2slots(size_t length) | |
535 | { | |
536 | return DIV_ROUND_UP(sizeof(struct mei_msg_hdr) + length, 4); | |
537 | } | |
538 | ||
10ee9074 | 539 | /** |
ce23139c AU |
540 | * mei_slots2data - get data in slots - bytes from slots |
541 | * | |
a8605ea2 | 542 | * @slots: number of available slots |
ce23139c | 543 | * |
a8605ea2 | 544 | * Return: number of bytes in slots |
10ee9074 TW |
545 | */ |
546 | static inline u32 mei_slots2data(int slots) | |
547 | { | |
548 | return slots * 4; | |
549 | } | |
550 | ||
ab841160 OW |
551 | /* |
552 | * mei init function prototypes | |
553 | */ | |
3a7e9b6c TW |
554 | void mei_device_init(struct mei_device *dev, |
555 | struct device *device, | |
556 | const struct mei_hw_ops *hw_ops); | |
33ec0826 | 557 | int mei_reset(struct mei_device *dev); |
c4d589be | 558 | int mei_start(struct mei_device *dev); |
33ec0826 | 559 | int mei_restart(struct mei_device *dev); |
7cb035d9 | 560 | void mei_stop(struct mei_device *dev); |
dc844b0d | 561 | void mei_cancel_work(struct mei_device *dev); |
c95efb74 | 562 | |
c95efb74 TW |
563 | /* |
564 | * MEI interrupt functions prototype | |
ab841160 | 565 | */ |
06ecd645 | 566 | |
a61c6530 | 567 | void mei_timer(struct work_struct *work); |
06ecd645 TW |
568 | int mei_irq_read_handler(struct mei_device *dev, |
569 | struct mei_cl_cb *cmpl_list, s32 *slots); | |
570 | ||
571 | int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); | |
4c6e22b8 | 572 | void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list); |
ab841160 | 573 | |
19838fb8 TW |
574 | /* |
575 | * AMTHIF - AMT Host Interface Functions | |
576 | */ | |
577 | void mei_amthif_reset_params(struct mei_device *dev); | |
578 | ||
d49ed64a | 579 | int mei_amthif_host_init(struct mei_device *dev, struct mei_me_client *me_cl); |
19838fb8 | 580 | |
19838fb8 | 581 | int mei_amthif_read(struct mei_device *dev, struct file *file, |
744f0f2f TW |
582 | char __user *ubuf, size_t length, loff_t *offset); |
583 | ||
584 | unsigned int mei_amthif_poll(struct mei_device *dev, | |
585 | struct file *file, poll_table *wait); | |
ab841160 | 586 | |
a562d5c2 TW |
587 | int mei_amthif_release(struct mei_device *dev, struct file *file); |
588 | ||
8660172e TW |
589 | int mei_amthif_write(struct mei_cl *cl, struct mei_cl_cb *cb); |
590 | int mei_amthif_run_next_cmd(struct mei_device *dev); | |
9d098192 TW |
591 | int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, |
592 | struct mei_cl_cb *cmpl_list); | |
5ceb46e2 | 593 | |
9abd8b31 | 594 | void mei_amthif_complete(struct mei_cl *cl, struct mei_cl_cb *cb); |
db4756fd | 595 | int mei_amthif_irq_read_msg(struct mei_cl *cl, |
5ceb46e2 TW |
596 | struct mei_msg_hdr *mei_hdr, |
597 | struct mei_cl_cb *complete_list); | |
598 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); | |
599 | ||
ab841160 OW |
600 | /* |
601 | * Register Access Function | |
602 | */ | |
603 | ||
8d929d48 | 604 | |
827eef51 TW |
605 | static inline void mei_hw_config(struct mei_device *dev) |
606 | { | |
607 | dev->ops->hw_config(dev); | |
608 | } | |
ee7e5afd | 609 | |
964a2331 TW |
610 | static inline enum mei_pg_state mei_pg_state(struct mei_device *dev) |
611 | { | |
612 | return dev->ops->pg_state(dev); | |
613 | } | |
614 | ||
3dc196ea AU |
615 | static inline bool mei_pg_in_transition(struct mei_device *dev) |
616 | { | |
617 | return dev->ops->pg_in_transition(dev); | |
618 | } | |
619 | ||
ee7e5afd TW |
620 | static inline bool mei_pg_is_enabled(struct mei_device *dev) |
621 | { | |
622 | return dev->ops->pg_is_enabled(dev); | |
623 | } | |
624 | ||
c20c68d5 | 625 | static inline int mei_hw_reset(struct mei_device *dev, bool enable) |
827eef51 | 626 | { |
c20c68d5 | 627 | return dev->ops->hw_reset(dev, enable); |
827eef51 TW |
628 | } |
629 | ||
9049f793 | 630 | static inline int mei_hw_start(struct mei_device *dev) |
aafae7ec | 631 | { |
9049f793 | 632 | return dev->ops->hw_start(dev); |
aafae7ec TW |
633 | } |
634 | ||
827eef51 TW |
635 | static inline void mei_clear_interrupts(struct mei_device *dev) |
636 | { | |
637 | dev->ops->intr_clear(dev); | |
638 | } | |
639 | ||
640 | static inline void mei_enable_interrupts(struct mei_device *dev) | |
641 | { | |
642 | dev->ops->intr_enable(dev); | |
643 | } | |
ab841160 | 644 | |
827eef51 TW |
645 | static inline void mei_disable_interrupts(struct mei_device *dev) |
646 | { | |
647 | dev->ops->intr_disable(dev); | |
648 | } | |
ab841160 | 649 | |
827eef51 TW |
650 | static inline bool mei_host_is_ready(struct mei_device *dev) |
651 | { | |
652 | return dev->ops->host_is_ready(dev); | |
653 | } | |
654 | static inline bool mei_hw_is_ready(struct mei_device *dev) | |
655 | { | |
656 | return dev->ops->hw_is_ready(dev); | |
657 | } | |
e7e0c231 | 658 | |
827eef51 TW |
659 | static inline bool mei_hbuf_is_ready(struct mei_device *dev) |
660 | { | |
661 | return dev->ops->hbuf_is_ready(dev); | |
662 | } | |
ab841160 | 663 | |
827eef51 TW |
664 | static inline int mei_hbuf_empty_slots(struct mei_device *dev) |
665 | { | |
666 | return dev->ops->hbuf_free_slots(dev); | |
667 | } | |
115ba28c | 668 | |
827eef51 TW |
669 | static inline size_t mei_hbuf_max_len(const struct mei_device *dev) |
670 | { | |
671 | return dev->ops->hbuf_max_len(dev); | |
672 | } | |
3a65dd4e | 673 | |
827eef51 TW |
674 | static inline int mei_write_message(struct mei_device *dev, |
675 | struct mei_msg_hdr *hdr, | |
676 | unsigned char *buf) | |
677 | { | |
678 | return dev->ops->write(dev, hdr, buf); | |
679 | } | |
680 | ||
681 | static inline u32 mei_read_hdr(const struct mei_device *dev) | |
682 | { | |
683 | return dev->ops->read_hdr(dev); | |
684 | } | |
685 | ||
686 | static inline void mei_read_slots(struct mei_device *dev, | |
687 | unsigned char *buf, unsigned long len) | |
688 | { | |
689 | dev->ops->read(dev, buf, len); | |
690 | } | |
691 | ||
692 | static inline int mei_count_full_read_slots(struct mei_device *dev) | |
693 | { | |
694 | return dev->ops->rdbuf_full_slots(dev); | |
695 | } | |
5bd64714 | 696 | |
1bd30b6a TW |
697 | static inline int mei_fw_status(struct mei_device *dev, |
698 | struct mei_fw_status *fw_status) | |
699 | { | |
700 | return dev->ops->fw_status(dev, fw_status); | |
701 | } | |
04dd3661 | 702 | |
6aae48ff TW |
703 | bool mei_hbuf_acquire(struct mei_device *dev); |
704 | ||
a532bbed TW |
705 | bool mei_write_is_idle(struct mei_device *dev); |
706 | ||
30e53bb8 TW |
707 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
708 | int mei_dbgfs_register(struct mei_device *dev, const char *name); | |
709 | void mei_dbgfs_deregister(struct mei_device *dev); | |
710 | #else | |
711 | static inline int mei_dbgfs_register(struct mei_device *dev, const char *name) | |
712 | { | |
713 | return 0; | |
714 | } | |
715 | static inline void mei_dbgfs_deregister(struct mei_device *dev) {} | |
716 | #endif /* CONFIG_DEBUG_FS */ | |
717 | ||
f3d8e878 | 718 | int mei_register(struct mei_device *dev, struct device *parent); |
30e53bb8 | 719 | void mei_deregister(struct mei_device *dev); |
2703d4b2 | 720 | |
479327fc | 721 | #define MEI_HDR_FMT "hdr:host=%02d me=%02d len=%d internal=%1d comp=%1d" |
15d4acc5 TW |
722 | #define MEI_HDR_PRM(hdr) \ |
723 | (hdr)->host_addr, (hdr)->me_addr, \ | |
479327fc | 724 | (hdr)->length, (hdr)->internal, (hdr)->msg_complete |
15d4acc5 | 725 | |
edca5ea3 AU |
726 | ssize_t mei_fw_status2str(struct mei_fw_status *fw_sts, char *buf, size_t len); |
727 | /** | |
728 | * mei_fw_status_str - fetch and convert fw status registers to printable string | |
729 | * | |
730 | * @dev: the device structure | |
731 | * @buf: string buffer at minimal size MEI_FW_STATUS_STR_SZ | |
732 | * @len: buffer len must be >= MEI_FW_STATUS_STR_SZ | |
733 | * | |
734 | * Return: number of bytes written or < 0 on failure | |
735 | */ | |
736 | static inline ssize_t mei_fw_status_str(struct mei_device *dev, | |
737 | char *buf, size_t len) | |
738 | { | |
739 | struct mei_fw_status fw_status; | |
740 | int ret; | |
741 | ||
742 | buf[0] = '\0'; | |
743 | ||
744 | ret = mei_fw_status(dev, &fw_status); | |
745 | if (ret) | |
746 | return ret; | |
747 | ||
748 | ret = mei_fw_status2str(&fw_status, buf, MEI_FW_STATUS_STR_SZ); | |
749 | ||
750 | return ret; | |
751 | } | |
752 | ||
753 | ||
ab841160 | 754 | #endif |