diff options
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/mei/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/mei/amthif.c | 572 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 73 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 218 | ||||
-rw-r--r-- | drivers/misc/mei/iorw.c | 266 | ||||
-rw-r--r-- | drivers/misc/mei/main.c | 10 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 29 |
7 files changed, 613 insertions, 556 deletions
diff --git a/drivers/misc/mei/Makefile b/drivers/misc/mei/Makefile index 57168db6c7e5..0017842e166c 100644 --- a/drivers/misc/mei/Makefile +++ b/drivers/misc/mei/Makefile | |||
@@ -8,4 +8,5 @@ mei-objs += interrupt.o | |||
8 | mei-objs += interface.o | 8 | mei-objs += interface.o |
9 | mei-objs += iorw.o | 9 | mei-objs += iorw.o |
10 | mei-objs += main.o | 10 | mei-objs += main.o |
11 | mei-objs += amthif.o | ||
11 | mei-objs += wd.o | 12 | mei-objs += wd.o |
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c new file mode 100644 index 000000000000..392203d8d254 --- /dev/null +++ b/drivers/misc/mei/amthif.c | |||
@@ -0,0 +1,572 @@ | |||
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/kernel.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/types.h> | ||
21 | #include <linux/fcntl.h> | ||
22 | #include <linux/aio.h> | ||
23 | #include <linux/pci.h> | ||
24 | #include <linux/init.h> | ||
25 | #include <linux/ioctl.h> | ||
26 | #include <linux/cdev.h> | ||
27 | #include <linux/list.h> | ||
28 | #include <linux/delay.h> | ||
29 | #include <linux/sched.h> | ||
30 | #include <linux/uuid.h> | ||
31 | #include <linux/jiffies.h> | ||
32 | #include <linux/uaccess.h> | ||
33 | |||
34 | |||
35 | #include "mei_dev.h" | ||
36 | #include "hw.h" | ||
37 | #include <linux/mei.h> | ||
38 | #include "interface.h" | ||
39 | |||
40 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, | ||
41 | 0xa8, 0x46, 0xe0, 0xff, 0x65, | ||
42 | 0x81, 0x4c); | ||
43 | |||
44 | /** | ||
45 | * mei_amthif_reset_params - initializes mei device iamthif | ||
46 | * | ||
47 | * @dev: the device structure | ||
48 | */ | ||
49 | void mei_amthif_reset_params(struct mei_device *dev) | ||
50 | { | ||
51 | /* reset iamthif parameters. */ | ||
52 | dev->iamthif_current_cb = NULL; | ||
53 | dev->iamthif_msg_buf_size = 0; | ||
54 | dev->iamthif_msg_buf_index = 0; | ||
55 | dev->iamthif_canceled = false; | ||
56 | dev->iamthif_ioctl = false; | ||
57 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
58 | dev->iamthif_timer = 0; | ||
59 | } | ||
60 | |||
61 | /** | ||
62 | * mei_amthif_host_init_ - mei initialization amthif client. | ||
63 | * | ||
64 | * @dev: the device structure | ||
65 | * | ||
66 | */ | ||
67 | void mei_amthif_host_init(struct mei_device *dev) | ||
68 | { | ||
69 | int i; | ||
70 | unsigned char *msg_buf; | ||
71 | |||
72 | mei_cl_init(&dev->iamthif_cl, dev); | ||
73 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
74 | |||
75 | /* find ME amthi client */ | ||
76 | i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, | ||
77 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | ||
78 | if (i < 0) { | ||
79 | dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | /* Assign iamthif_mtu to the value received from ME */ | ||
84 | |||
85 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; | ||
86 | dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n", | ||
87 | dev->me_clients[i].props.max_msg_length); | ||
88 | |||
89 | kfree(dev->iamthif_msg_buf); | ||
90 | dev->iamthif_msg_buf = NULL; | ||
91 | |||
92 | /* allocate storage for ME message buffer */ | ||
93 | msg_buf = kcalloc(dev->iamthif_mtu, | ||
94 | sizeof(unsigned char), GFP_KERNEL); | ||
95 | if (!msg_buf) { | ||
96 | dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | dev->iamthif_msg_buf = msg_buf; | ||
101 | |||
102 | if (mei_connect(dev, &dev->iamthif_cl)) { | ||
103 | dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); | ||
104 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
105 | dev->iamthif_cl.host_client_id = 0; | ||
106 | } else { | ||
107 | dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT; | ||
108 | } | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * mei_amthif_find_read_list_entry - finds a amthilist entry for current file | ||
113 | * | ||
114 | * @dev: the device structure | ||
115 | * @file: pointer to file object | ||
116 | * | ||
117 | * returns returned a list entry on success, NULL on failure. | ||
118 | */ | ||
119 | struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, | ||
120 | struct file *file) | ||
121 | { | ||
122 | struct mei_cl *cl_temp; | ||
123 | struct mei_cl_cb *pos = NULL; | ||
124 | struct mei_cl_cb *next = NULL; | ||
125 | |||
126 | list_for_each_entry_safe(pos, next, | ||
127 | &dev->amthi_read_complete_list.list, list) { | ||
128 | cl_temp = (struct mei_cl *)pos->file_private; | ||
129 | if (cl_temp && cl_temp == &dev->iamthif_cl && | ||
130 | pos->file_object == file) | ||
131 | return pos; | ||
132 | } | ||
133 | return NULL; | ||
134 | } | ||
135 | |||
136 | |||
137 | /** | ||
138 | * mei_amthif_read - read data from AMTHIF client | ||
139 | * | ||
140 | * @dev: the device structure | ||
141 | * @if_num: minor number | ||
142 | * @file: pointer to file object | ||
143 | * @*ubuf: pointer to user data in user space | ||
144 | * @length: data length to read | ||
145 | * @offset: data read offset | ||
146 | * | ||
147 | * Locking: called under "dev->device_lock" lock | ||
148 | * | ||
149 | * returns | ||
150 | * returned data length on success, | ||
151 | * zero if no data to read, | ||
152 | * negative on failure. | ||
153 | */ | ||
154 | int mei_amthif_read(struct mei_device *dev, struct file *file, | ||
155 | char __user *ubuf, size_t length, loff_t *offset) | ||
156 | { | ||
157 | int rets; | ||
158 | int wait_ret; | ||
159 | struct mei_cl_cb *cb = NULL; | ||
160 | struct mei_cl *cl = file->private_data; | ||
161 | unsigned long timeout; | ||
162 | int i; | ||
163 | |||
164 | /* Only Posible if we are in timeout */ | ||
165 | if (!cl || cl != &dev->iamthif_cl) { | ||
166 | dev_dbg(&dev->pdev->dev, "bad file ext.\n"); | ||
167 | return -ETIMEDOUT; | ||
168 | } | ||
169 | |||
170 | i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); | ||
171 | |||
172 | if (i < 0) { | ||
173 | dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); | ||
174 | return -ENODEV; | ||
175 | } | ||
176 | dev_dbg(&dev->pdev->dev, "checking amthi data\n"); | ||
177 | cb = mei_amthif_find_read_list_entry(dev, file); | ||
178 | |||
179 | /* Check for if we can block or not*/ | ||
180 | if (cb == NULL && file->f_flags & O_NONBLOCK) | ||
181 | return -EAGAIN; | ||
182 | |||
183 | |||
184 | dev_dbg(&dev->pdev->dev, "waiting for amthi data\n"); | ||
185 | while (cb == NULL) { | ||
186 | /* unlock the Mutex */ | ||
187 | mutex_unlock(&dev->device_lock); | ||
188 | |||
189 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, | ||
190 | (cb = mei_amthif_find_read_list_entry(dev, file))); | ||
191 | |||
192 | if (wait_ret) | ||
193 | return -ERESTARTSYS; | ||
194 | |||
195 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | ||
196 | |||
197 | /* Locking again the Mutex */ | ||
198 | mutex_lock(&dev->device_lock); | ||
199 | } | ||
200 | |||
201 | |||
202 | dev_dbg(&dev->pdev->dev, "Got amthi data\n"); | ||
203 | dev->iamthif_timer = 0; | ||
204 | |||
205 | if (cb) { | ||
206 | timeout = cb->read_time + | ||
207 | mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); | ||
208 | dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", | ||
209 | timeout); | ||
210 | |||
211 | if (time_after(jiffies, timeout)) { | ||
212 | dev_dbg(&dev->pdev->dev, "amthi Time out\n"); | ||
213 | /* 15 sec for the message has expired */ | ||
214 | list_del(&cb->list); | ||
215 | rets = -ETIMEDOUT; | ||
216 | goto free; | ||
217 | } | ||
218 | } | ||
219 | /* if the whole message will fit remove it from the list */ | ||
220 | if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) | ||
221 | list_del(&cb->list); | ||
222 | else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { | ||
223 | /* end of the message has been reached */ | ||
224 | list_del(&cb->list); | ||
225 | rets = 0; | ||
226 | goto free; | ||
227 | } | ||
228 | /* else means that not full buffer will be read and do not | ||
229 | * remove message from deletion list | ||
230 | */ | ||
231 | |||
232 | dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n", | ||
233 | cb->response_buffer.size); | ||
234 | dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx); | ||
235 | |||
236 | /* length is being turncated to PAGE_SIZE, however, | ||
237 | * the buf_idx may point beyond */ | ||
238 | length = min_t(size_t, length, (cb->buf_idx - *offset)); | ||
239 | |||
240 | if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) | ||
241 | rets = -EFAULT; | ||
242 | else { | ||
243 | rets = length; | ||
244 | if ((*offset + length) < cb->buf_idx) { | ||
245 | *offset += length; | ||
246 | goto out; | ||
247 | } | ||
248 | } | ||
249 | free: | ||
250 | dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n"); | ||
251 | *offset = 0; | ||
252 | mei_io_cb_free(cb); | ||
253 | out: | ||
254 | return rets; | ||
255 | } | ||
256 | |||
257 | /** | ||
258 | * mei_amthif_write - write amthif data to amthif client | ||
259 | * | ||
260 | * @dev: the device structure | ||
261 | * @cb: mei call back struct | ||
262 | * | ||
263 | * returns 0 on success, <0 on failure. | ||
264 | */ | ||
265 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) | ||
266 | { | ||
267 | struct mei_msg_hdr mei_hdr; | ||
268 | int ret; | ||
269 | |||
270 | if (!dev || !cb) | ||
271 | return -ENODEV; | ||
272 | |||
273 | dev_dbg(&dev->pdev->dev, "write data to amthi client.\n"); | ||
274 | |||
275 | dev->iamthif_state = MEI_IAMTHIF_WRITING; | ||
276 | dev->iamthif_current_cb = cb; | ||
277 | dev->iamthif_file_object = cb->file_object; | ||
278 | dev->iamthif_canceled = false; | ||
279 | dev->iamthif_ioctl = true; | ||
280 | dev->iamthif_msg_buf_size = cb->request_buffer.size; | ||
281 | memcpy(dev->iamthif_msg_buf, cb->request_buffer.data, | ||
282 | cb->request_buffer.size); | ||
283 | |||
284 | ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl); | ||
285 | if (ret < 0) | ||
286 | return ret; | ||
287 | |||
288 | if (ret && dev->mei_host_buffer_is_empty) { | ||
289 | ret = 0; | ||
290 | dev->mei_host_buffer_is_empty = false; | ||
291 | if (cb->request_buffer.size > mei_hbuf_max_data(dev)) { | ||
292 | mei_hdr.length = mei_hbuf_max_data(dev); | ||
293 | mei_hdr.msg_complete = 0; | ||
294 | } else { | ||
295 | mei_hdr.length = cb->request_buffer.size; | ||
296 | mei_hdr.msg_complete = 1; | ||
297 | } | ||
298 | |||
299 | mei_hdr.host_addr = dev->iamthif_cl.host_client_id; | ||
300 | mei_hdr.me_addr = dev->iamthif_cl.me_client_id; | ||
301 | mei_hdr.reserved = 0; | ||
302 | dev->iamthif_msg_buf_index += mei_hdr.length; | ||
303 | if (mei_write_message(dev, &mei_hdr, | ||
304 | (unsigned char *)(dev->iamthif_msg_buf), | ||
305 | mei_hdr.length)) | ||
306 | return -ENODEV; | ||
307 | |||
308 | if (mei_hdr.msg_complete) { | ||
309 | if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl)) | ||
310 | return -ENODEV; | ||
311 | dev->iamthif_flow_control_pending = true; | ||
312 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
313 | dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n"); | ||
314 | dev->iamthif_current_cb = cb; | ||
315 | dev->iamthif_file_object = cb->file_object; | ||
316 | list_add_tail(&cb->list, &dev->write_waiting_list.list); | ||
317 | } else { | ||
318 | dev_dbg(&dev->pdev->dev, "message does not complete, so add amthi cb to write list.\n"); | ||
319 | list_add_tail(&cb->list, &dev->write_list.list); | ||
320 | } | ||
321 | } else { | ||
322 | if (!(dev->mei_host_buffer_is_empty)) | ||
323 | dev_dbg(&dev->pdev->dev, "host buffer is not empty"); | ||
324 | |||
325 | dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n"); | ||
326 | list_add_tail(&cb->list, &dev->write_list.list); | ||
327 | } | ||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | /** | ||
332 | * mei_amthif_run_next_cmd | ||
333 | * | ||
334 | * @dev: the device structure | ||
335 | * | ||
336 | * returns 0 on success, <0 on failure. | ||
337 | */ | ||
338 | void mei_amthif_run_next_cmd(struct mei_device *dev) | ||
339 | { | ||
340 | struct mei_cl *cl_tmp; | ||
341 | struct mei_cl_cb *pos = NULL; | ||
342 | struct mei_cl_cb *next = NULL; | ||
343 | int status; | ||
344 | |||
345 | if (!dev) | ||
346 | return; | ||
347 | |||
348 | dev->iamthif_msg_buf_size = 0; | ||
349 | dev->iamthif_msg_buf_index = 0; | ||
350 | dev->iamthif_canceled = false; | ||
351 | dev->iamthif_ioctl = true; | ||
352 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
353 | dev->iamthif_timer = 0; | ||
354 | dev->iamthif_file_object = NULL; | ||
355 | |||
356 | dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n"); | ||
357 | |||
358 | list_for_each_entry_safe(pos, next, &dev->amthi_cmd_list.list, list) { | ||
359 | list_del(&pos->list); | ||
360 | cl_tmp = (struct mei_cl *)pos->file_private; | ||
361 | |||
362 | if (cl_tmp && cl_tmp == &dev->iamthif_cl) { | ||
363 | status = mei_amthif_write(dev, pos); | ||
364 | if (status) { | ||
365 | dev_dbg(&dev->pdev->dev, | ||
366 | "amthi write failed status = %d\n", | ||
367 | status); | ||
368 | return; | ||
369 | } | ||
370 | break; | ||
371 | } | ||
372 | } | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * mei_amthif_irq_process_completed - processes completed iamthif operation. | ||
377 | * | ||
378 | * @dev: the device structure. | ||
379 | * @slots: free slots. | ||
380 | * @cb_pos: callback block. | ||
381 | * @cl: private data of the file object. | ||
382 | * @cmpl_list: complete list. | ||
383 | * | ||
384 | * returns 0, OK; otherwise, error. | ||
385 | */ | ||
386 | int mei_amthif_irq_process_completed(struct mei_device *dev, s32 *slots, | ||
387 | struct mei_cl_cb *cb_pos, | ||
388 | struct mei_cl *cl, | ||
389 | struct mei_cl_cb *cmpl_list) | ||
390 | { | ||
391 | struct mei_msg_hdr *mei_hdr; | ||
392 | |||
393 | if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + | ||
394 | dev->iamthif_msg_buf_size - | ||
395 | dev->iamthif_msg_buf_index)) { | ||
396 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
397 | mei_hdr->host_addr = cl->host_client_id; | ||
398 | mei_hdr->me_addr = cl->me_client_id; | ||
399 | mei_hdr->length = dev->iamthif_msg_buf_size - | ||
400 | dev->iamthif_msg_buf_index; | ||
401 | mei_hdr->msg_complete = 1; | ||
402 | mei_hdr->reserved = 0; | ||
403 | |||
404 | *slots -= mei_data2slots(mei_hdr->length); | ||
405 | |||
406 | if (mei_write_message(dev, mei_hdr, | ||
407 | (dev->iamthif_msg_buf + | ||
408 | dev->iamthif_msg_buf_index), | ||
409 | mei_hdr->length)) { | ||
410 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
411 | cl->status = -ENODEV; | ||
412 | list_del(&cb_pos->list); | ||
413 | return -ENODEV; | ||
414 | } else { | ||
415 | if (mei_flow_ctrl_reduce(dev, cl)) | ||
416 | return -ENODEV; | ||
417 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
418 | cb_pos->buf_idx = dev->iamthif_msg_buf_index; | ||
419 | cl->status = 0; | ||
420 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
421 | dev->iamthif_flow_control_pending = true; | ||
422 | /* save iamthif cb sent to amthi client */ | ||
423 | dev->iamthif_current_cb = cb_pos; | ||
424 | list_move_tail(&cb_pos->list, | ||
425 | &dev->write_waiting_list.list); | ||
426 | |||
427 | } | ||
428 | } else if (*slots == dev->hbuf_depth) { | ||
429 | /* buffer is still empty */ | ||
430 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
431 | mei_hdr->host_addr = cl->host_client_id; | ||
432 | mei_hdr->me_addr = cl->me_client_id; | ||
433 | mei_hdr->length = | ||
434 | (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
435 | mei_hdr->msg_complete = 0; | ||
436 | mei_hdr->reserved = 0; | ||
437 | |||
438 | *slots -= mei_data2slots(mei_hdr->length); | ||
439 | |||
440 | if (mei_write_message(dev, mei_hdr, | ||
441 | (dev->iamthif_msg_buf + | ||
442 | dev->iamthif_msg_buf_index), | ||
443 | mei_hdr->length)) { | ||
444 | cl->status = -ENODEV; | ||
445 | list_del(&cb_pos->list); | ||
446 | } else { | ||
447 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
448 | } | ||
449 | return -EMSGSIZE; | ||
450 | } else { | ||
451 | return -EBADMSG; | ||
452 | } | ||
453 | |||
454 | return 0; | ||
455 | } | ||
456 | |||
457 | /** | ||
458 | * mei_amthif_irq_read_message - read routine after ISR to | ||
459 | * handle the read amthi message | ||
460 | * | ||
461 | * @complete_list: An instance of our list structure | ||
462 | * @dev: the device structure | ||
463 | * @mei_hdr: header of amthi message | ||
464 | * | ||
465 | * returns 0 on success, <0 on failure. | ||
466 | */ | ||
467 | int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list, | ||
468 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr) | ||
469 | { | ||
470 | struct mei_cl *cl; | ||
471 | struct mei_cl_cb *cb; | ||
472 | unsigned char *buffer; | ||
473 | |||
474 | BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); | ||
475 | BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING); | ||
476 | |||
477 | buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; | ||
478 | BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); | ||
479 | |||
480 | mei_read_slots(dev, buffer, mei_hdr->length); | ||
481 | |||
482 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
483 | |||
484 | if (!mei_hdr->msg_complete) | ||
485 | return 0; | ||
486 | |||
487 | dev_dbg(&dev->pdev->dev, | ||
488 | "amthi_message_buffer_index =%d\n", | ||
489 | mei_hdr->length); | ||
490 | |||
491 | dev_dbg(&dev->pdev->dev, "completed amthi read.\n "); | ||
492 | if (!dev->iamthif_current_cb) | ||
493 | return -ENODEV; | ||
494 | |||
495 | cb = dev->iamthif_current_cb; | ||
496 | dev->iamthif_current_cb = NULL; | ||
497 | |||
498 | cl = (struct mei_cl *)cb->file_private; | ||
499 | if (!cl) | ||
500 | return -ENODEV; | ||
501 | |||
502 | dev->iamthif_stall_timer = 0; | ||
503 | cb->buf_idx = dev->iamthif_msg_buf_index; | ||
504 | cb->read_time = jiffies; | ||
505 | if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) { | ||
506 | /* found the iamthif cb */ | ||
507 | dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n "); | ||
508 | dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n "); | ||
509 | list_add_tail(&cb->list, &complete_list->list); | ||
510 | } | ||
511 | return 0; | ||
512 | } | ||
513 | |||
514 | /** | ||
515 | * mei_amthif_irq_read - prepares to read amthif data. | ||
516 | * | ||
517 | * @dev: the device structure. | ||
518 | * @slots: free slots. | ||
519 | * | ||
520 | * returns 0, OK; otherwise, error. | ||
521 | */ | ||
522 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) | ||
523 | { | ||
524 | |||
525 | if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr) | ||
526 | + sizeof(struct hbm_flow_control))) { | ||
527 | return -EMSGSIZE; | ||
528 | } | ||
529 | *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); | ||
530 | if (mei_send_flow_control(dev, &dev->iamthif_cl)) { | ||
531 | dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); | ||
532 | return -EIO; | ||
533 | } | ||
534 | |||
535 | dev_dbg(&dev->pdev->dev, "iamthif flow control success\n"); | ||
536 | dev->iamthif_state = MEI_IAMTHIF_READING; | ||
537 | dev->iamthif_flow_control_pending = false; | ||
538 | dev->iamthif_msg_buf_index = 0; | ||
539 | dev->iamthif_msg_buf_size = 0; | ||
540 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; | ||
541 | dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | ||
542 | return 0; | ||
543 | } | ||
544 | |||
545 | /** | ||
546 | * mei_amthif_complete - complete amthif callback. | ||
547 | * | ||
548 | * @dev: the device structure. | ||
549 | * @cb_pos: callback block. | ||
550 | */ | ||
551 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) | ||
552 | { | ||
553 | if (dev->iamthif_canceled != 1) { | ||
554 | dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; | ||
555 | dev->iamthif_stall_timer = 0; | ||
556 | memcpy(cb->response_buffer.data, | ||
557 | dev->iamthif_msg_buf, | ||
558 | dev->iamthif_msg_buf_index); | ||
559 | list_add_tail(&cb->list, &dev->amthi_read_complete_list.list); | ||
560 | dev_dbg(&dev->pdev->dev, "amthi read completed\n"); | ||
561 | dev->iamthif_timer = jiffies; | ||
562 | dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", | ||
563 | dev->iamthif_timer); | ||
564 | } else { | ||
565 | mei_amthif_run_next_cmd(dev); | ||
566 | } | ||
567 | |||
568 | dev_dbg(&dev->pdev->dev, "completing amthi call back.\n"); | ||
569 | wake_up_interruptible(&dev->iamthif_cl.wait); | ||
570 | } | ||
571 | |||
572 | |||
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index e6951ec4840f..4a8eb920f7fb 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -43,10 +43,6 @@ const char *mei_dev_state_str(int state) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | 45 | ||
46 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, | ||
47 | 0xa8, 0x46, 0xe0, 0xff, 0x65, | ||
48 | 0x81, 0x4c); | ||
49 | |||
50 | /** | 46 | /** |
51 | * mei_io_list_flush - removes list entry belonging to cl. | 47 | * mei_io_list_flush - removes list entry belonging to cl. |
52 | * | 48 | * |
@@ -92,23 +88,6 @@ int mei_cl_flush_queues(struct mei_cl *cl) | |||
92 | 88 | ||
93 | 89 | ||
94 | /** | 90 | /** |
95 | * mei_reset_iamthif_params - initializes mei device iamthif | ||
96 | * | ||
97 | * @dev: the device structure | ||
98 | */ | ||
99 | static void mei_reset_iamthif_params(struct mei_device *dev) | ||
100 | { | ||
101 | /* reset iamthif parameters. */ | ||
102 | dev->iamthif_current_cb = NULL; | ||
103 | dev->iamthif_msg_buf_size = 0; | ||
104 | dev->iamthif_msg_buf_index = 0; | ||
105 | dev->iamthif_canceled = false; | ||
106 | dev->iamthif_ioctl = false; | ||
107 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
108 | dev->iamthif_timer = 0; | ||
109 | } | ||
110 | |||
111 | /** | ||
112 | * init_mei_device - allocates and initializes the mei device structure | 91 | * init_mei_device - allocates and initializes the mei device structure |
113 | * | 92 | * |
114 | * @pdev: The pci device structure | 93 | * @pdev: The pci device structure |
@@ -313,7 +292,7 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
313 | mei_remove_client_from_file_list(dev, | 292 | mei_remove_client_from_file_list(dev, |
314 | dev->iamthif_cl.host_client_id); | 293 | dev->iamthif_cl.host_client_id); |
315 | 294 | ||
316 | mei_reset_iamthif_params(dev); | 295 | mei_amthif_reset_params(dev); |
317 | dev->extra_write_index = 0; | 296 | dev->extra_write_index = 0; |
318 | } | 297 | } |
319 | 298 | ||
@@ -577,56 +556,6 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, | |||
577 | } | 556 | } |
578 | 557 | ||
579 | /** | 558 | /** |
580 | * host_init_iamthif - mei initialization iamthif client. | ||
581 | * | ||
582 | * @dev: the device structure | ||
583 | * | ||
584 | */ | ||
585 | void mei_host_init_iamthif(struct mei_device *dev) | ||
586 | { | ||
587 | int i; | ||
588 | unsigned char *msg_buf; | ||
589 | |||
590 | mei_cl_init(&dev->iamthif_cl, dev); | ||
591 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
592 | |||
593 | /* find ME amthi client */ | ||
594 | i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, | ||
595 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | ||
596 | if (i < 0) { | ||
597 | dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); | ||
598 | return; | ||
599 | } | ||
600 | |||
601 | /* Assign iamthif_mtu to the value received from ME */ | ||
602 | |||
603 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; | ||
604 | dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n", | ||
605 | dev->me_clients[i].props.max_msg_length); | ||
606 | |||
607 | kfree(dev->iamthif_msg_buf); | ||
608 | dev->iamthif_msg_buf = NULL; | ||
609 | |||
610 | /* allocate storage for ME message buffer */ | ||
611 | msg_buf = kcalloc(dev->iamthif_mtu, | ||
612 | sizeof(unsigned char), GFP_KERNEL); | ||
613 | if (!msg_buf) { | ||
614 | dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); | ||
615 | return; | ||
616 | } | ||
617 | |||
618 | dev->iamthif_msg_buf = msg_buf; | ||
619 | |||
620 | if (mei_connect(dev, &dev->iamthif_cl)) { | ||
621 | dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); | ||
622 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
623 | dev->iamthif_cl.host_client_id = 0; | ||
624 | } else { | ||
625 | dev->iamthif_cl.timer_count = MEI_CONNECT_TIMEOUT; | ||
626 | } | ||
627 | } | ||
628 | |||
629 | /** | ||
630 | * mei_alloc_file_private - allocates a private file structure and sets it up. | 559 | * mei_alloc_file_private - allocates a private file structure and sets it up. |
631 | * @file: the file structure | 560 | * @file: the file structure |
632 | * | 561 | * |
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 248f581bde31..62f8b65fd11a 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -74,92 +74,6 @@ static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) | |||
74 | } | 74 | } |
75 | 75 | ||
76 | /** | 76 | /** |
77 | * _mei_cmpl_iamthif - processes completed iamthif operation. | ||
78 | * | ||
79 | * @dev: the device structure. | ||
80 | * @cb_pos: callback block. | ||
81 | */ | ||
82 | static 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->list, &dev->amthi_read_complete_list.list); | ||
91 | dev_dbg(&dev->pdev->dev, "amthi read completed\n"); | ||
92 | dev->iamthif_timer = jiffies; | ||
93 | dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", | ||
94 | dev->iamthif_timer); | ||
95 | } else { | ||
96 | mei_run_next_iamthif_cmd(dev); | ||
97 | } | ||
98 | |||
99 | dev_dbg(&dev->pdev->dev, "completing amthi call back.\n"); | ||
100 | wake_up_interruptible(&dev->iamthif_cl.wait); | ||
101 | } | ||
102 | |||
103 | |||
104 | /** | ||
105 | * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to | ||
106 | * handle the read amthi message data processing. | ||
107 | * | ||
108 | * @complete_list: An instance of our list structure | ||
109 | * @dev: the device structure | ||
110 | * @mei_hdr: header of amthi message | ||
111 | * | ||
112 | * returns 0 on success, <0 on failure. | ||
113 | */ | ||
114 | static int mei_irq_thread_read_amthi_message(struct mei_cl_cb *complete_list, | ||
115 | struct mei_device *dev, | ||
116 | struct mei_msg_hdr *mei_hdr) | ||
117 | { | ||
118 | struct mei_cl *cl; | ||
119 | struct mei_cl_cb *cb; | ||
120 | unsigned char *buffer; | ||
121 | |||
122 | BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); | ||
123 | BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING); | ||
124 | |||
125 | buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; | ||
126 | BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); | ||
127 | |||
128 | mei_read_slots(dev, buffer, mei_hdr->length); | ||
129 | |||
130 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
131 | |||
132 | if (!mei_hdr->msg_complete) | ||
133 | return 0; | ||
134 | |||
135 | dev_dbg(&dev->pdev->dev, | ||
136 | "amthi_message_buffer_index =%d\n", | ||
137 | mei_hdr->length); | ||
138 | |||
139 | dev_dbg(&dev->pdev->dev, "completed amthi read.\n "); | ||
140 | if (!dev->iamthif_current_cb) | ||
141 | return -ENODEV; | ||
142 | |||
143 | cb = dev->iamthif_current_cb; | ||
144 | dev->iamthif_current_cb = NULL; | ||
145 | |||
146 | cl = (struct mei_cl *)cb->file_private; | ||
147 | if (!cl) | ||
148 | return -ENODEV; | ||
149 | |||
150 | dev->iamthif_stall_timer = 0; | ||
151 | cb->buf_idx = dev->iamthif_msg_buf_index; | ||
152 | cb->read_time = jiffies; | ||
153 | if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) { | ||
154 | /* found the iamthif cb */ | ||
155 | dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n "); | ||
156 | dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n "); | ||
157 | list_add_tail(&cb->list, &complete_list->list); | ||
158 | } | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | /** | ||
163 | * _mei_irq_thread_state_ok - checks if mei header matches file private data | 77 | * _mei_irq_thread_state_ok - checks if mei header matches file private data |
164 | * | 78 | * |
165 | * @cl: private data of the file object | 79 | * @cl: private data of the file object |
@@ -244,37 +158,6 @@ quit: | |||
244 | } | 158 | } |
245 | 159 | ||
246 | /** | 160 | /** |
247 | * _mei_irq_thread_iamthif_read - prepares to read iamthif data. | ||
248 | * | ||
249 | * @dev: the device structure. | ||
250 | * @slots: free slots. | ||
251 | * | ||
252 | * returns 0, OK; otherwise, error. | ||
253 | */ | ||
254 | static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots) | ||
255 | { | ||
256 | |||
257 | if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr) | ||
258 | + sizeof(struct hbm_flow_control))) { | ||
259 | return -EMSGSIZE; | ||
260 | } | ||
261 | *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); | ||
262 | if (mei_send_flow_control(dev, &dev->iamthif_cl)) { | ||
263 | dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); | ||
264 | return -EIO; | ||
265 | } | ||
266 | |||
267 | dev_dbg(&dev->pdev->dev, "iamthif flow control success\n"); | ||
268 | dev->iamthif_state = MEI_IAMTHIF_READING; | ||
269 | dev->iamthif_flow_control_pending = false; | ||
270 | dev->iamthif_msg_buf_index = 0; | ||
271 | dev->iamthif_msg_buf_size = 0; | ||
272 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; | ||
273 | dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | ||
274 | return 0; | ||
275 | } | ||
276 | |||
277 | /** | ||
278 | * _mei_irq_thread_close - processes close related operation. | 161 | * _mei_irq_thread_close - processes close related operation. |
279 | * | 162 | * |
280 | * @dev: the device structure. | 163 | * @dev: the device structure. |
@@ -370,7 +253,7 @@ static void mei_client_connect_response(struct mei_device *dev, | |||
370 | mei_watchdog_register(dev); | 253 | mei_watchdog_register(dev); |
371 | 254 | ||
372 | /* next step in the state maching */ | 255 | /* next step in the state maching */ |
373 | mei_host_init_iamthif(dev); | 256 | mei_amthif_host_init(dev); |
374 | return; | 257 | return; |
375 | } | 258 | } |
376 | 259 | ||
@@ -728,7 +611,7 @@ static void mei_irq_thread_read_bus_message(struct mei_device *dev, | |||
728 | * will be received | 611 | * will be received |
729 | */ | 612 | */ |
730 | if (mei_wd_host_init(dev)) | 613 | if (mei_wd_host_init(dev)) |
731 | mei_host_init_iamthif(dev); | 614 | mei_amthif_host_init(dev); |
732 | } | 615 | } |
733 | 616 | ||
734 | } else { | 617 | } else { |
@@ -964,87 +847,6 @@ static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots, | |||
964 | } | 847 | } |
965 | 848 | ||
966 | /** | 849 | /** |
967 | * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation. | ||
968 | * | ||
969 | * @dev: the device structure. | ||
970 | * @slots: free slots. | ||
971 | * @cb_pos: callback block. | ||
972 | * @cl: private data of the file object. | ||
973 | * @cmpl_list: complete list. | ||
974 | * | ||
975 | * returns 0, OK; otherwise, error. | ||
976 | */ | ||
977 | static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, | ||
978 | struct mei_cl_cb *cb_pos, | ||
979 | struct mei_cl *cl, | ||
980 | struct mei_cl_cb *cmpl_list) | ||
981 | { | ||
982 | struct mei_msg_hdr *mei_hdr; | ||
983 | |||
984 | if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + | ||
985 | dev->iamthif_msg_buf_size - | ||
986 | dev->iamthif_msg_buf_index)) { | ||
987 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
988 | mei_hdr->host_addr = cl->host_client_id; | ||
989 | mei_hdr->me_addr = cl->me_client_id; | ||
990 | mei_hdr->length = dev->iamthif_msg_buf_size - | ||
991 | dev->iamthif_msg_buf_index; | ||
992 | mei_hdr->msg_complete = 1; | ||
993 | mei_hdr->reserved = 0; | ||
994 | |||
995 | *slots -= mei_data2slots(mei_hdr->length); | ||
996 | |||
997 | if (mei_write_message(dev, mei_hdr, | ||
998 | (dev->iamthif_msg_buf + | ||
999 | dev->iamthif_msg_buf_index), | ||
1000 | mei_hdr->length)) { | ||
1001 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
1002 | cl->status = -ENODEV; | ||
1003 | list_del(&cb_pos->list); | ||
1004 | return -ENODEV; | ||
1005 | } else { | ||
1006 | if (mei_flow_ctrl_reduce(dev, cl)) | ||
1007 | return -ENODEV; | ||
1008 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
1009 | cb_pos->buf_idx = dev->iamthif_msg_buf_index; | ||
1010 | cl->status = 0; | ||
1011 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
1012 | dev->iamthif_flow_control_pending = true; | ||
1013 | /* save iamthif cb sent to amthi client */ | ||
1014 | dev->iamthif_current_cb = cb_pos; | ||
1015 | list_move_tail(&cb_pos->list, &dev->write_waiting_list.list); | ||
1016 | |||
1017 | } | ||
1018 | } else if (*slots == dev->hbuf_depth) { | ||
1019 | /* buffer is still empty */ | ||
1020 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | ||
1021 | mei_hdr->host_addr = cl->host_client_id; | ||
1022 | mei_hdr->me_addr = cl->me_client_id; | ||
1023 | mei_hdr->length = | ||
1024 | (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | ||
1025 | mei_hdr->msg_complete = 0; | ||
1026 | mei_hdr->reserved = 0; | ||
1027 | |||
1028 | *slots -= mei_data2slots(mei_hdr->length); | ||
1029 | |||
1030 | if (mei_write_message(dev, mei_hdr, | ||
1031 | (dev->iamthif_msg_buf + | ||
1032 | dev->iamthif_msg_buf_index), | ||
1033 | mei_hdr->length)) { | ||
1034 | cl->status = -ENODEV; | ||
1035 | list_del(&cb_pos->list); | ||
1036 | } else { | ||
1037 | dev->iamthif_msg_buf_index += mei_hdr->length; | ||
1038 | } | ||
1039 | return -EMSGSIZE; | ||
1040 | } else { | ||
1041 | return -EBADMSG; | ||
1042 | } | ||
1043 | |||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | /** | ||
1048 | * mei_irq_thread_read_handler - bottom half read routine after ISR to | 850 | * mei_irq_thread_read_handler - bottom half read routine after ISR to |
1049 | * handle the read processing. | 851 | * handle the read processing. |
1050 | * | 852 | * |
@@ -1117,8 +919,8 @@ static int mei_irq_thread_read_handler(struct mei_cl_cb *cmpl_list, | |||
1117 | dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); | 919 | dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); |
1118 | dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", | 920 | dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", |
1119 | mei_hdr->length); | 921 | mei_hdr->length); |
1120 | ret = mei_irq_thread_read_amthi_message(cmpl_list, | 922 | |
1121 | dev, mei_hdr); | 923 | ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr); |
1122 | if (ret) | 924 | if (ret) |
1123 | goto end; | 925 | goto end; |
1124 | 926 | ||
@@ -1195,7 +997,7 @@ static int mei_irq_thread_write_handler(struct mei_cl_cb *cmpl_list, | |||
1195 | if (cl == &dev->iamthif_cl) { | 997 | if (cl == &dev->iamthif_cl) { |
1196 | dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); | 998 | dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); |
1197 | if (dev->iamthif_flow_control_pending) { | 999 | if (dev->iamthif_flow_control_pending) { |
1198 | ret = _mei_irq_thread_iamthif_read(dev, slots); | 1000 | ret = mei_amthif_irq_read(dev, slots); |
1199 | if (ret) | 1001 | if (ret) |
1200 | return ret; | 1002 | return ret; |
1201 | } | 1003 | } |
@@ -1300,8 +1102,8 @@ static int mei_irq_thread_write_handler(struct mei_cl_cb *cmpl_list, | |||
1300 | cl->host_client_id); | 1102 | cl->host_client_id); |
1301 | continue; | 1103 | continue; |
1302 | } | 1104 | } |
1303 | ret = _mei_irq_thread_cmpl_iamthif(dev, slots, pos, | 1105 | ret = mei_amthif_irq_process_completed(dev, slots, pos, |
1304 | cl, cmpl_list); | 1106 | cl, cmpl_list); |
1305 | if (ret) | 1107 | if (ret) |
1306 | return ret; | 1108 | return ret; |
1307 | 1109 | ||
@@ -1372,7 +1174,7 @@ void mei_timer(struct work_struct *work) | |||
1372 | dev->iamthif_current_cb = NULL; | 1174 | dev->iamthif_current_cb = NULL; |
1373 | 1175 | ||
1374 | dev->iamthif_file_object = NULL; | 1176 | dev->iamthif_file_object = NULL; |
1375 | mei_run_next_iamthif_cmd(dev); | 1177 | mei_amthif_run_next_cmd(dev); |
1376 | } | 1178 | } |
1377 | } | 1179 | } |
1378 | 1180 | ||
@@ -1409,7 +1211,7 @@ void mei_timer(struct work_struct *work) | |||
1409 | dev->iamthif_file_object->private_data = NULL; | 1211 | dev->iamthif_file_object->private_data = NULL; |
1410 | dev->iamthif_file_object = NULL; | 1212 | dev->iamthif_file_object = NULL; |
1411 | dev->iamthif_timer = 0; | 1213 | dev->iamthif_timer = 0; |
1412 | mei_run_next_iamthif_cmd(dev); | 1214 | mei_amthif_run_next_cmd(dev); |
1413 | 1215 | ||
1414 | } | 1216 | } |
1415 | } | 1217 | } |
@@ -1524,7 +1326,7 @@ end: | |||
1524 | _mei_cmpl(cl, cb_pos); | 1326 | _mei_cmpl(cl, cb_pos); |
1525 | cb_pos = NULL; | 1327 | cb_pos = NULL; |
1526 | } else if (cl == &dev->iamthif_cl) { | 1328 | } else if (cl == &dev->iamthif_cl) { |
1527 | _mei_cmpl_iamthif(dev, cb_pos); | 1329 | mei_amthif_complete(dev, cb_pos); |
1528 | } | 1330 | } |
1529 | } | 1331 | } |
1530 | } | 1332 | } |
diff --git a/drivers/misc/mei/iorw.c b/drivers/misc/mei/iorw.c index 8026cbf755db..a1d9ba1a06e7 100644 --- a/drivers/misc/mei/iorw.c +++ b/drivers/misc/mei/iorw.c | |||
@@ -320,152 +320,6 @@ end: | |||
320 | } | 320 | } |
321 | 321 | ||
322 | /** | 322 | /** |
323 | * find_amthi_read_list_entry - finds a amthilist entry for current file | ||
324 | * | ||
325 | * @dev: the device structure | ||
326 | * @file: pointer to file object | ||
327 | * | ||
328 | * returns returned a list entry on success, NULL on failure. | ||
329 | */ | ||
330 | struct mei_cl_cb *find_amthi_read_list_entry( | ||
331 | struct mei_device *dev, | ||
332 | struct file *file) | ||
333 | { | ||
334 | struct mei_cl *cl_temp; | ||
335 | struct mei_cl_cb *pos = NULL; | ||
336 | struct mei_cl_cb *next = NULL; | ||
337 | |||
338 | list_for_each_entry_safe(pos, next, | ||
339 | &dev->amthi_read_complete_list.list, list) { | ||
340 | cl_temp = (struct mei_cl *)pos->file_private; | ||
341 | if (cl_temp && cl_temp == &dev->iamthif_cl && | ||
342 | pos->file_object == file) | ||
343 | return pos; | ||
344 | } | ||
345 | return NULL; | ||
346 | } | ||
347 | |||
348 | /** | ||
349 | * amthi_read - read data from AMTHI client | ||
350 | * | ||
351 | * @dev: the device structure | ||
352 | * @if_num: minor number | ||
353 | * @file: pointer to file object | ||
354 | * @*ubuf: pointer to user data in user space | ||
355 | * @length: data length to read | ||
356 | * @offset: data read offset | ||
357 | * | ||
358 | * Locking: called under "dev->device_lock" lock | ||
359 | * | ||
360 | * returns | ||
361 | * returned data length on success, | ||
362 | * zero if no data to read, | ||
363 | * negative on failure. | ||
364 | */ | ||
365 | int amthi_read(struct mei_device *dev, struct file *file, | ||
366 | char __user *ubuf, size_t length, loff_t *offset) | ||
367 | { | ||
368 | int rets; | ||
369 | int wait_ret; | ||
370 | struct mei_cl_cb *cb = NULL; | ||
371 | struct mei_cl *cl = file->private_data; | ||
372 | unsigned long timeout; | ||
373 | int i; | ||
374 | |||
375 | /* Only Posible if we are in timeout */ | ||
376 | if (!cl || cl != &dev->iamthif_cl) { | ||
377 | dev_dbg(&dev->pdev->dev, "bad file ext.\n"); | ||
378 | return -ETIMEDOUT; | ||
379 | } | ||
380 | |||
381 | i = mei_me_cl_by_id(dev, dev->iamthif_cl.me_client_id); | ||
382 | |||
383 | if (i < 0) { | ||
384 | dev_dbg(&dev->pdev->dev, "amthi client not found.\n"); | ||
385 | return -ENODEV; | ||
386 | } | ||
387 | dev_dbg(&dev->pdev->dev, "checking amthi data\n"); | ||
388 | cb = find_amthi_read_list_entry(dev, file); | ||
389 | |||
390 | /* Check for if we can block or not*/ | ||
391 | if (cb == NULL && file->f_flags & O_NONBLOCK) | ||
392 | return -EAGAIN; | ||
393 | |||
394 | |||
395 | dev_dbg(&dev->pdev->dev, "waiting for amthi data\n"); | ||
396 | while (cb == NULL) { | ||
397 | /* unlock the Mutex */ | ||
398 | mutex_unlock(&dev->device_lock); | ||
399 | |||
400 | wait_ret = wait_event_interruptible(dev->iamthif_cl.wait, | ||
401 | (cb = find_amthi_read_list_entry(dev, file))); | ||
402 | |||
403 | if (wait_ret) | ||
404 | return -ERESTARTSYS; | ||
405 | |||
406 | dev_dbg(&dev->pdev->dev, "woke up from sleep\n"); | ||
407 | |||
408 | /* Locking again the Mutex */ | ||
409 | mutex_lock(&dev->device_lock); | ||
410 | } | ||
411 | |||
412 | |||
413 | dev_dbg(&dev->pdev->dev, "Got amthi data\n"); | ||
414 | dev->iamthif_timer = 0; | ||
415 | |||
416 | if (cb) { | ||
417 | timeout = cb->read_time + | ||
418 | mei_secs_to_jiffies(MEI_IAMTHIF_READ_TIMER); | ||
419 | dev_dbg(&dev->pdev->dev, "amthi timeout = %lud\n", | ||
420 | timeout); | ||
421 | |||
422 | if (time_after(jiffies, timeout)) { | ||
423 | dev_dbg(&dev->pdev->dev, "amthi Time out\n"); | ||
424 | /* 15 sec for the message has expired */ | ||
425 | list_del(&cb->list); | ||
426 | rets = -ETIMEDOUT; | ||
427 | goto free; | ||
428 | } | ||
429 | } | ||
430 | /* if the whole message will fit remove it from the list */ | ||
431 | if (cb->buf_idx >= *offset && length >= (cb->buf_idx - *offset)) | ||
432 | list_del(&cb->list); | ||
433 | else if (cb->buf_idx > 0 && cb->buf_idx <= *offset) { | ||
434 | /* end of the message has been reached */ | ||
435 | list_del(&cb->list); | ||
436 | rets = 0; | ||
437 | goto free; | ||
438 | } | ||
439 | /* else means that not full buffer will be read and do not | ||
440 | * remove message from deletion list | ||
441 | */ | ||
442 | |||
443 | dev_dbg(&dev->pdev->dev, "amthi cb->response_buffer size - %d\n", | ||
444 | cb->response_buffer.size); | ||
445 | dev_dbg(&dev->pdev->dev, "amthi cb->buf_idx - %lu\n", cb->buf_idx); | ||
446 | |||
447 | /* length is being turncated to PAGE_SIZE, however, | ||
448 | * the buf_idx may point beyond */ | ||
449 | length = min_t(size_t, length, (cb->buf_idx - *offset)); | ||
450 | |||
451 | if (copy_to_user(ubuf, cb->response_buffer.data + *offset, length)) | ||
452 | rets = -EFAULT; | ||
453 | else { | ||
454 | rets = length; | ||
455 | if ((*offset + length) < cb->buf_idx) { | ||
456 | *offset += length; | ||
457 | goto out; | ||
458 | } | ||
459 | } | ||
460 | free: | ||
461 | dev_dbg(&dev->pdev->dev, "free amthi cb memory.\n"); | ||
462 | *offset = 0; | ||
463 | mei_io_cb_free(cb); | ||
464 | out: | ||
465 | return rets; | ||
466 | } | ||
467 | |||
468 | /** | ||
469 | * mei_start_read - the start read client message function. | 323 | * mei_start_read - the start read client message function. |
470 | * | 324 | * |
471 | * @dev: the device structure | 325 | * @dev: the device structure |
@@ -524,123 +378,3 @@ err: | |||
524 | return rets; | 378 | return rets; |
525 | } | 379 | } |
526 | 380 | ||
527 | /** | ||
528 | * amthi_write - write iamthif data to amthi client | ||
529 | * | ||
530 | * @dev: the device structure | ||
531 | * @cb: mei call back struct | ||
532 | * | ||
533 | * returns 0 on success, <0 on failure. | ||
534 | */ | ||
535 | int amthi_write(struct mei_device *dev, struct mei_cl_cb *cb) | ||
536 | { | ||
537 | struct mei_msg_hdr mei_hdr; | ||
538 | int ret; | ||
539 | |||
540 | if (!dev || !cb) | ||
541 | return -ENODEV; | ||
542 | |||
543 | dev_dbg(&dev->pdev->dev, "write data to amthi client.\n"); | ||
544 | |||
545 | dev->iamthif_state = MEI_IAMTHIF_WRITING; | ||
546 | dev->iamthif_current_cb = cb; | ||
547 | dev->iamthif_file_object = cb->file_object; | ||
548 | dev->iamthif_canceled = false; | ||
549 | dev->iamthif_ioctl = true; | ||
550 | dev->iamthif_msg_buf_size = cb->request_buffer.size; | ||
551 | memcpy(dev->iamthif_msg_buf, cb->request_buffer.data, | ||
552 | cb->request_buffer.size); | ||
553 | |||
554 | ret = mei_flow_ctrl_creds(dev, &dev->iamthif_cl); | ||
555 | if (ret < 0) | ||
556 | return ret; | ||
557 | |||
558 | if (ret && dev->mei_host_buffer_is_empty) { | ||
559 | ret = 0; | ||
560 | dev->mei_host_buffer_is_empty = false; | ||
561 | if (cb->request_buffer.size > mei_hbuf_max_data(dev)) { | ||
562 | mei_hdr.length = mei_hbuf_max_data(dev); | ||
563 | mei_hdr.msg_complete = 0; | ||
564 | } else { | ||
565 | mei_hdr.length = cb->request_buffer.size; | ||
566 | mei_hdr.msg_complete = 1; | ||
567 | } | ||
568 | |||
569 | mei_hdr.host_addr = dev->iamthif_cl.host_client_id; | ||
570 | mei_hdr.me_addr = dev->iamthif_cl.me_client_id; | ||
571 | mei_hdr.reserved = 0; | ||
572 | dev->iamthif_msg_buf_index += mei_hdr.length; | ||
573 | if (mei_write_message(dev, &mei_hdr, | ||
574 | (unsigned char *)(dev->iamthif_msg_buf), | ||
575 | mei_hdr.length)) | ||
576 | return -ENODEV; | ||
577 | |||
578 | if (mei_hdr.msg_complete) { | ||
579 | if (mei_flow_ctrl_reduce(dev, &dev->iamthif_cl)) | ||
580 | return -ENODEV; | ||
581 | dev->iamthif_flow_control_pending = true; | ||
582 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
583 | dev_dbg(&dev->pdev->dev, "add amthi cb to write waiting list\n"); | ||
584 | dev->iamthif_current_cb = cb; | ||
585 | dev->iamthif_file_object = cb->file_object; | ||
586 | list_add_tail(&cb->list, &dev->write_waiting_list.list); | ||
587 | } else { | ||
588 | dev_dbg(&dev->pdev->dev, "message does not complete, " | ||
589 | "so add amthi cb to write list.\n"); | ||
590 | list_add_tail(&cb->list, &dev->write_list.list); | ||
591 | } | ||
592 | } else { | ||
593 | if (!(dev->mei_host_buffer_is_empty)) | ||
594 | dev_dbg(&dev->pdev->dev, "host buffer is not empty"); | ||
595 | |||
596 | dev_dbg(&dev->pdev->dev, "No flow control credentials, " | ||
597 | "so add iamthif cb to write list.\n"); | ||
598 | list_add_tail(&cb->list, &dev->write_list.list); | ||
599 | } | ||
600 | return 0; | ||
601 | } | ||
602 | |||
603 | /** | ||
604 | * iamthif_ioctl_send_msg - send cmd data to amthi client | ||
605 | * | ||
606 | * @dev: the device structure | ||
607 | * | ||
608 | * returns 0 on success, <0 on failure. | ||
609 | */ | ||
610 | void mei_run_next_iamthif_cmd(struct mei_device *dev) | ||
611 | { | ||
612 | struct mei_cl *cl_tmp; | ||
613 | struct mei_cl_cb *pos = NULL; | ||
614 | struct mei_cl_cb *next = NULL; | ||
615 | int status; | ||
616 | |||
617 | if (!dev) | ||
618 | return; | ||
619 | |||
620 | dev->iamthif_msg_buf_size = 0; | ||
621 | dev->iamthif_msg_buf_index = 0; | ||
622 | dev->iamthif_canceled = false; | ||
623 | dev->iamthif_ioctl = true; | ||
624 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
625 | dev->iamthif_timer = 0; | ||
626 | dev->iamthif_file_object = NULL; | ||
627 | |||
628 | dev_dbg(&dev->pdev->dev, "complete amthi cmd_list cb.\n"); | ||
629 | |||
630 | list_for_each_entry_safe(pos, next, &dev->amthi_cmd_list.list, list) { | ||
631 | list_del(&pos->list); | ||
632 | cl_tmp = (struct mei_cl *)pos->file_private; | ||
633 | |||
634 | if (cl_tmp && cl_tmp == &dev->iamthif_cl) { | ||
635 | status = amthi_write(dev, pos); | ||
636 | if (status) { | ||
637 | dev_dbg(&dev->pdev->dev, | ||
638 | "amthi write failed status = %d\n", | ||
639 | status); | ||
640 | return; | ||
641 | } | ||
642 | break; | ||
643 | } | ||
644 | } | ||
645 | } | ||
646 | |||
diff --git a/drivers/misc/mei/main.c b/drivers/misc/mei/main.c index 659727a79012..f69e0856f982 100644 --- a/drivers/misc/mei/main.c +++ b/drivers/misc/mei/main.c | |||
@@ -349,7 +349,7 @@ static int mei_release(struct inode *inode, struct file *file) | |||
349 | dev->iamthif_canceled = true; | 349 | dev->iamthif_canceled = true; |
350 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) { | 350 | if (dev->iamthif_state == MEI_IAMTHIF_READ_COMPLETE) { |
351 | dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n"); | 351 | dev_dbg(&dev->pdev->dev, "run next amthi iamthif cb\n"); |
352 | mei_run_next_iamthif_cmd(dev); | 352 | mei_amthif_run_next_cmd(dev); |
353 | } | 353 | } |
354 | } | 354 | } |
355 | 355 | ||
@@ -410,7 +410,7 @@ static ssize_t mei_read(struct file *file, char __user *ubuf, | |||
410 | } | 410 | } |
411 | 411 | ||
412 | if (cl == &dev->iamthif_cl) { | 412 | if (cl == &dev->iamthif_cl) { |
413 | rets = amthi_read(dev, file, ubuf, length, offset); | 413 | rets = mei_amthif_read(dev, file, ubuf, length, offset); |
414 | goto out; | 414 | goto out; |
415 | } | 415 | } |
416 | 416 | ||
@@ -563,7 +563,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
563 | goto err; | 563 | goto err; |
564 | } | 564 | } |
565 | if (cl == &dev->iamthif_cl) { | 565 | if (cl == &dev->iamthif_cl) { |
566 | write_cb = find_amthi_read_list_entry(dev, file); | 566 | write_cb = mei_amthif_find_read_list_entry(dev, file); |
567 | 567 | ||
568 | if (write_cb) { | 568 | if (write_cb) { |
569 | timeout = write_cb->read_time + | 569 | timeout = write_cb->read_time + |
@@ -636,7 +636,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf, | |||
636 | list_add_tail(&write_cb->list, &dev->amthi_cmd_list.list); | 636 | list_add_tail(&write_cb->list, &dev->amthi_cmd_list.list); |
637 | } else { | 637 | } else { |
638 | dev_dbg(&dev->pdev->dev, "call amthi write\n"); | 638 | dev_dbg(&dev->pdev->dev, "call amthi write\n"); |
639 | rets = amthi_write(dev, write_cb); | 639 | rets = mei_amthif_write(dev, write_cb); |
640 | 640 | ||
641 | if (rets) { | 641 | if (rets) { |
642 | dev_err(&dev->pdev->dev, "amthi write failed with status = %d\n", | 642 | dev_err(&dev->pdev->dev, "amthi write failed with status = %d\n", |
@@ -823,7 +823,7 @@ static unsigned int mei_poll(struct file *file, poll_table *wait) | |||
823 | dev->iamthif_file_object == file) { | 823 | dev->iamthif_file_object == file) { |
824 | mask |= (POLLIN | POLLRDNORM); | 824 | mask |= (POLLIN | POLLRDNORM); |
825 | dev_dbg(&dev->pdev->dev, "run next amthi cb\n"); | 825 | dev_dbg(&dev->pdev->dev, "run next amthi cb\n"); |
826 | mei_run_next_iamthif_cmd(dev); | 826 | mei_amthif_run_next_cmd(dev); |
827 | } | 827 | } |
828 | goto out; | 828 | goto out; |
829 | } | 829 | } |
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 32c951ab1221..57a5a4e4ee4d 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -286,7 +286,6 @@ int mei_task_initialize_clients(void *data); | |||
286 | int mei_initialize_clients(struct mei_device *dev); | 286 | int mei_initialize_clients(struct mei_device *dev); |
287 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl); | 287 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl); |
288 | void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id); | 288 | void mei_remove_client_from_file_list(struct mei_device *dev, u8 host_client_id); |
289 | void mei_host_init_iamthif(struct mei_device *dev); | ||
290 | void mei_allocate_me_clients_storage(struct mei_device *dev); | 289 | void mei_allocate_me_clients_storage(struct mei_device *dev); |
291 | 290 | ||
292 | 291 | ||
@@ -362,17 +361,37 @@ int mei_ioctl_connect_client(struct file *file, | |||
362 | 361 | ||
363 | int mei_start_read(struct mei_device *dev, struct mei_cl *cl); | 362 | int mei_start_read(struct mei_device *dev, struct mei_cl *cl); |
364 | 363 | ||
365 | int amthi_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); | ||
366 | 364 | ||
367 | int amthi_read(struct mei_device *dev, struct file *file, | 365 | /* |
366 | * AMTHIF - AMT Host Interface Functions | ||
367 | */ | ||
368 | void mei_amthif_reset_params(struct mei_device *dev); | ||
369 | |||
370 | void mei_amthif_host_init(struct mei_device *dev); | ||
371 | |||
372 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *priv_cb); | ||
373 | |||
374 | int mei_amthif_read(struct mei_device *dev, struct file *file, | ||
368 | char __user *ubuf, size_t length, loff_t *offset); | 375 | char __user *ubuf, size_t length, loff_t *offset); |
369 | 376 | ||
370 | struct mei_cl_cb *find_amthi_read_list_entry(struct mei_device *dev, | 377 | struct mei_cl_cb *mei_amthif_find_read_list_entry(struct mei_device *dev, |
371 | struct file *file); | 378 | struct file *file); |
372 | 379 | ||
373 | void mei_run_next_iamthif_cmd(struct mei_device *dev); | 380 | void mei_amthif_run_next_cmd(struct mei_device *dev); |
381 | |||
382 | |||
383 | int mei_amthif_read_message(struct mei_cl_cb *complete_list, | ||
384 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr); | ||
374 | 385 | ||
386 | int mei_amthif_irq_process_completed(struct mei_device *dev, s32 *slots, | ||
387 | struct mei_cl_cb *cb_pos, | ||
388 | struct mei_cl *cl, | ||
389 | struct mei_cl_cb *cmpl_list); | ||
375 | 390 | ||
391 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb); | ||
392 | int mei_amthif_irq_read_message(struct mei_cl_cb *complete_list, | ||
393 | struct mei_device *dev, struct mei_msg_hdr *mei_hdr); | ||
394 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots); | ||
376 | 395 | ||
377 | /* | 396 | /* |
378 | * Register Access Function | 397 | * Register Access Function |