interrupt.c (de65d816aa44f9ddd79861ae21d75010cc1fd003) interrupt.c (827eef51f8dd9a4ab62b4ad270c15472f46938f2)
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.

--- 7 unchanged lines hidden (view full) ---

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
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.

--- 7 unchanged lines hidden (view full) ---

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>
24#include <linux/mei.h>
26#include "hw.h"
27#include "interface.h"
28
25
26#include "mei_dev.h"
27#include "hbm.h"
28#include "hw-me.h"
29#include "client.h"
29
30
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
31
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{

--- 85 unchanged lines hidden (view full) ---

145 }
146
147 }
148
149quit:
150 dev_dbg(&dev->pdev->dev, "message read\n");
151 if (!buffer) {
152 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
32/**
33 * _mei_cmpl - processes completed operation.
34 *
35 * @cl: private data of the file object.
36 * @cb_pos: callback block.
37 */
38static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos)
39{

--- 85 unchanged lines hidden (view full) ---

125 }
126
127 }
128
129quit:
130 dev_dbg(&dev->pdev->dev, "message read\n");
131 if (!buffer) {
132 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
153 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n",
154 *(u32 *) dev->rd_msg_buf);
133 dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n",
134 MEI_HDR_PRM(mei_hdr));
155 }
156
157 return 0;
158}
159
160/**
161 * _mei_irq_thread_close - processes close related operation.
162 *

--- 11 unchanged lines hidden (view full) ---

174 struct mei_cl_cb *cmpl_list)
175{
176 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
177 sizeof(struct hbm_client_connect_request)))
178 return -EBADMSG;
179
180 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
181
135 }
136
137 return 0;
138}
139
140/**
141 * _mei_irq_thread_close - processes close related operation.
142 *

--- 11 unchanged lines hidden (view full) ---

154 struct mei_cl_cb *cmpl_list)
155{
156 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
157 sizeof(struct hbm_client_connect_request)))
158 return -EBADMSG;
159
160 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
161
182 if (mei_disconnect(dev, cl)) {
162 if (mei_hbm_cl_disconnect_req(dev, cl)) {
183 cl->status = 0;
184 cb_pos->buf_idx = 0;
185 list_move_tail(&cb_pos->list, &cmpl_list->list);
186 return -EMSGSIZE;
187 } else {
188 cl->state = MEI_FILE_DISCONNECTING;
189 cl->status = 0;
190 cb_pos->buf_idx = 0;
191 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
192 cl->timer_count = MEI_CONNECT_TIMEOUT;
193 }
194
195 return 0;
196}
197
163 cl->status = 0;
164 cb_pos->buf_idx = 0;
165 list_move_tail(&cb_pos->list, &cmpl_list->list);
166 return -EMSGSIZE;
167 } else {
168 cl->state = MEI_FILE_DISCONNECTING;
169 cl->status = 0;
170 cb_pos->buf_idx = 0;
171 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
172 cl->timer_count = MEI_CONNECT_TIMEOUT;
173 }
174
175 return 0;
176}
177
198/**
199 * is_treat_specially_client - checks if the message belongs
200 * to the file private data.
201 *
202 * @cl: private data of the file object
203 * @rs: connect response bus message
204 *
205 */
206static bool is_treat_specially_client(struct mei_cl *cl,
207 struct hbm_client_connect_response *rs)
208{
209
178
210 if (cl->host_client_id == rs->host_addr &&
211 cl->me_client_id == rs->me_addr) {
212 if (!rs->status) {
213 cl->state = MEI_FILE_CONNECTED;
214 cl->status = 0;
215
216 } else {
217 cl->state = MEI_FILE_DISCONNECTED;
218 cl->status = -ENODEV;
219 }
220 cl->timer_count = 0;
221
222 return true;
223 }
224 return false;
225}
226
227/**
179/**
228 * mei_client_connect_response - connects to response irq routine
229 *
230 * @dev: the device structure
231 * @rs: connect response bus message
232 */
233static void mei_client_connect_response(struct mei_device *dev,
234 struct hbm_client_connect_response *rs)
235{
236
237 struct mei_cl *cl;
238 struct mei_cl_cb *pos = NULL, *next = NULL;
239
240 dev_dbg(&dev->pdev->dev,
241 "connect_response:\n"
242 "ME Client = %d\n"
243 "Host Client = %d\n"
244 "Status = %d\n",
245 rs->me_addr,
246 rs->host_addr,
247 rs->status);
248
249 /* if WD or iamthif client treat specially */
250
251 if (is_treat_specially_client(&(dev->wd_cl), rs)) {
252 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n");
253 mei_watchdog_register(dev);
254
255 return;
256 }
257
258 if (is_treat_specially_client(&(dev->iamthif_cl), rs)) {
259 dev->iamthif_state = MEI_IAMTHIF_IDLE;
260 return;
261 }
262 list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
263
264 cl = pos->cl;
265 if (!cl) {
266 list_del(&pos->list);
267 return;
268 }
269 if (pos->fop_type == MEI_FOP_IOCTL) {
270 if (is_treat_specially_client(cl, rs)) {
271 list_del(&pos->list);
272 cl->status = 0;
273 cl->timer_count = 0;
274 break;
275 }
276 }
277 }
278}
279
280/**
281 * mei_client_disconnect_response - disconnects from response irq routine
282 *
283 * @dev: the device structure
284 * @rs: disconnect response bus message
285 */
286static void mei_client_disconnect_response(struct mei_device *dev,
287 struct hbm_client_connect_response *rs)
288{
289 struct mei_cl *cl;
290 struct mei_cl_cb *pos = NULL, *next = NULL;
291
292 dev_dbg(&dev->pdev->dev,
293 "disconnect_response:\n"
294 "ME Client = %d\n"
295 "Host Client = %d\n"
296 "Status = %d\n",
297 rs->me_addr,
298 rs->host_addr,
299 rs->status);
300
301 list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) {
302 cl = pos->cl;
303
304 if (!cl) {
305 list_del(&pos->list);
306 return;
307 }
308
309 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n");
310 if (cl->host_client_id == rs->host_addr &&
311 cl->me_client_id == rs->me_addr) {
312
313 list_del(&pos->list);
314 if (!rs->status)
315 cl->state = MEI_FILE_DISCONNECTED;
316
317 cl->status = 0;
318 cl->timer_count = 0;
319 break;
320 }
321 }
322}
323
324/**
325 * same_flow_addr - tells if they have the same address.
326 *
327 * @file: private data of the file object.
328 * @flow: flow control.
329 *
330 * returns !=0, same; 0,not.
331 */
332static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow)
333{
334 return (cl->host_client_id == flow->host_addr &&
335 cl->me_client_id == flow->me_addr);
336}
337
338/**
339 * add_single_flow_creds - adds single buffer credentials.
340 *
341 * @file: private data ot the file object.
342 * @flow: flow control.
343 */
344static void add_single_flow_creds(struct mei_device *dev,
345 struct hbm_flow_control *flow)
346{
347 struct mei_me_client *client;
348 int i;
349
350 for (i = 0; i < dev->me_clients_num; i++) {
351 client = &dev->me_clients[i];
352 if (client && flow->me_addr == client->client_id) {
353 if (client->props.single_recv_buf) {
354 client->mei_flow_ctrl_creds++;
355 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n",
356 flow->me_addr);
357 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n",
358 client->mei_flow_ctrl_creds);
359 } else {
360 BUG(); /* error in flow control */
361 }
362 }
363 }
364}
365
366/**
367 * mei_client_flow_control_response - flow control response irq routine
368 *
369 * @dev: the device structure
370 * @flow_control: flow control response bus message
371 */
372static void mei_client_flow_control_response(struct mei_device *dev,
373 struct hbm_flow_control *flow_control)
374{
375 struct mei_cl *cl_pos = NULL;
376 struct mei_cl *cl_next = NULL;
377
378 if (!flow_control->host_addr) {
379 /* single receive buffer */
380 add_single_flow_creds(dev, flow_control);
381 } else {
382 /* normal connection */
383 list_for_each_entry_safe(cl_pos, cl_next,
384 &dev->file_list, link) {
385 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n");
386
387 dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n",
388 cl_pos->host_client_id,
389 cl_pos->me_client_id);
390 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n",
391 flow_control->host_addr,
392 flow_control->me_addr);
393 if (same_flow_addr(cl_pos, flow_control)) {
394 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n",
395 flow_control->host_addr,
396 flow_control->me_addr);
397 cl_pos->mei_flow_ctrl_creds++;
398 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n",
399 cl_pos->mei_flow_ctrl_creds);
400 break;
401 }
402 }
403 }
404}
405
406/**
407 * same_disconn_addr - tells if they have the same address
408 *
409 * @file: private data of the file object.
410 * @disconn: disconnection request.
411 *
412 * returns !=0, same; 0,not.
413 */
414static int same_disconn_addr(struct mei_cl *cl,
415 struct hbm_client_connect_request *req)
416{
417 return (cl->host_client_id == req->host_addr &&
418 cl->me_client_id == req->me_addr);
419}
420
421/**
422 * mei_client_disconnect_request - disconnects from request irq routine
423 *
424 * @dev: the device structure.
425 * @disconnect_req: disconnect request bus message.
426 */
427static void mei_client_disconnect_request(struct mei_device *dev,
428 struct hbm_client_connect_request *disconnect_req)
429{
430 struct hbm_client_connect_response *disconnect_res;
431 struct mei_cl *pos, *next;
432 const size_t len = sizeof(struct hbm_client_connect_response);
433
434 list_for_each_entry_safe(pos, next, &dev->file_list, link) {
435 if (same_disconn_addr(pos, disconnect_req)) {
436 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n",
437 disconnect_req->host_addr,
438 disconnect_req->me_addr);
439 pos->state = MEI_FILE_DISCONNECTED;
440 pos->timer_count = 0;
441 if (pos == &dev->wd_cl)
442 dev->wd_pending = false;
443 else if (pos == &dev->iamthif_cl)
444 dev->iamthif_timer = 0;
445
446 /* prepare disconnect response */
447 (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
448 disconnect_res =
449 (struct hbm_client_connect_response *)
450 &dev->wr_ext_msg.data;
451 disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD;
452 disconnect_res->host_addr = pos->host_client_id;
453 disconnect_res->me_addr = pos->me_client_id;
454 disconnect_res->status = 0;
455 break;
456 }
457 }
458}
459
460/**
461 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to
462 * handle the read bus message cmd processing.
463 *
464 * @dev: the device structure
465 * @mei_hdr: header of bus message
466 */
467static void mei_irq_thread_read_bus_message(struct mei_device *dev,
468 struct mei_msg_hdr *mei_hdr)
469{
470 struct mei_bus_message *mei_msg;
471 struct mei_me_client *me_client;
472 struct hbm_host_version_response *version_res;
473 struct hbm_client_connect_response *connect_res;
474 struct hbm_client_connect_response *disconnect_res;
475 struct hbm_client_connect_request *disconnect_req;
476 struct hbm_flow_control *flow_control;
477 struct hbm_props_response *props_res;
478 struct hbm_host_enum_response *enum_res;
479 struct hbm_host_stop_request *stop_req;
480
481 /* read the message to our buffer */
482 BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf));
483 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length);
484 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf;
485
486 switch (mei_msg->hbm_cmd) {
487 case HOST_START_RES_CMD:
488 version_res = (struct hbm_host_version_response *) mei_msg;
489 if (version_res->host_version_supported) {
490 dev->version.major_version = HBM_MAJOR_VERSION;
491 dev->version.minor_version = HBM_MINOR_VERSION;
492 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
493 dev->init_clients_state == MEI_START_MESSAGE) {
494 dev->init_clients_timer = 0;
495 mei_host_enum_clients_message(dev);
496 } else {
497 dev->recvd_msg = false;
498 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n");
499 mei_reset(dev, 1);
500 return;
501 }
502 } else {
503 u32 *buf = dev->wr_msg_buf;
504 const size_t len = sizeof(struct hbm_host_stop_request);
505
506 dev->version = version_res->me_max_version;
507
508 /* send stop message */
509 mei_hdr = mei_hbm_hdr(&buf[0], len);
510 stop_req = (struct hbm_host_stop_request *)&buf[1];
511 memset(stop_req, 0, len);
512 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
513 stop_req->reason = DRIVER_STOP_REQUEST;
514
515 mei_write_message(dev, mei_hdr,
516 (unsigned char *)stop_req, len);
517 dev_dbg(&dev->pdev->dev, "version mismatch.\n");
518 return;
519 }
520
521 dev->recvd_msg = true;
522 dev_dbg(&dev->pdev->dev, "host start response message received.\n");
523 break;
524
525 case CLIENT_CONNECT_RES_CMD:
526 connect_res = (struct hbm_client_connect_response *) mei_msg;
527 mei_client_connect_response(dev, connect_res);
528 dev_dbg(&dev->pdev->dev, "client connect response message received.\n");
529 wake_up(&dev->wait_recvd_msg);
530 break;
531
532 case CLIENT_DISCONNECT_RES_CMD:
533 disconnect_res = (struct hbm_client_connect_response *) mei_msg;
534 mei_client_disconnect_response(dev, disconnect_res);
535 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n");
536 wake_up(&dev->wait_recvd_msg);
537 break;
538
539 case MEI_FLOW_CONTROL_CMD:
540 flow_control = (struct hbm_flow_control *) mei_msg;
541 mei_client_flow_control_response(dev, flow_control);
542 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n");
543 break;
544
545 case HOST_CLIENT_PROPERTIES_RES_CMD:
546 props_res = (struct hbm_props_response *)mei_msg;
547 me_client = &dev->me_clients[dev->me_client_presentation_num];
548
549 if (props_res->status || !dev->me_clients) {
550 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n");
551 mei_reset(dev, 1);
552 return;
553 }
554
555 if (me_client->client_id != props_res->address) {
556 dev_err(&dev->pdev->dev,
557 "Host client properties reply mismatch\n");
558 mei_reset(dev, 1);
559
560 return;
561 }
562
563 if (dev->dev_state != MEI_DEV_INIT_CLIENTS ||
564 dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) {
565 dev_err(&dev->pdev->dev,
566 "Unexpected client properties reply\n");
567 mei_reset(dev, 1);
568
569 return;
570 }
571
572 me_client->props = props_res->client_properties;
573 dev->me_client_index++;
574 dev->me_client_presentation_num++;
575
576 mei_host_client_enumerate(dev);
577
578 break;
579
580 case HOST_ENUM_RES_CMD:
581 enum_res = (struct hbm_host_enum_response *) mei_msg;
582 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32);
583 if (dev->dev_state == MEI_DEV_INIT_CLIENTS &&
584 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) {
585 dev->init_clients_timer = 0;
586 dev->me_client_presentation_num = 0;
587 dev->me_client_index = 0;
588 mei_allocate_me_clients_storage(dev);
589 dev->init_clients_state =
590 MEI_CLIENT_PROPERTIES_MESSAGE;
591
592 mei_host_client_enumerate(dev);
593 } else {
594 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n");
595 mei_reset(dev, 1);
596 return;
597 }
598 break;
599
600 case HOST_STOP_RES_CMD:
601 dev->dev_state = MEI_DEV_DISABLED;
602 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n");
603 mei_reset(dev, 1);
604 break;
605
606 case CLIENT_DISCONNECT_REQ_CMD:
607 /* search for client */
608 disconnect_req = (struct hbm_client_connect_request *)mei_msg;
609 mei_client_disconnect_request(dev, disconnect_req);
610 break;
611
612 case ME_STOP_REQ_CMD:
613 {
614 /* prepare stop request: sent in next interrupt event */
615
616 const size_t len = sizeof(struct hbm_host_stop_request);
617
618 mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len);
619 stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data;
620 memset(stop_req, 0, len);
621 stop_req->hbm_cmd = HOST_STOP_REQ_CMD;
622 stop_req->reason = DRIVER_STOP_REQUEST;
623 break;
624 }
625 default:
626 BUG();
627 break;
628
629 }
630}
631
632
633/**
634 * _mei_hb_read - processes read related operation.
635 *
636 * @dev: the device structure.
637 * @slots: free slots.
638 * @cb_pos: callback block.
639 * @cl: private data of the file object.
640 * @cmpl_list: complete list.
641 *

--- 8 unchanged lines hidden (view full) ---

650 sizeof(struct hbm_flow_control))) {
651 /* return the cancel routine */
652 list_del(&cb_pos->list);
653 return -EBADMSG;
654 }
655
656 *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
657
180 * _mei_hb_read - processes read related operation.
181 *
182 * @dev: the device structure.
183 * @slots: free slots.
184 * @cb_pos: callback block.
185 * @cl: private data of the file object.
186 * @cmpl_list: complete list.
187 *

--- 8 unchanged lines hidden (view full) ---

196 sizeof(struct hbm_flow_control))) {
197 /* return the cancel routine */
198 list_del(&cb_pos->list);
199 return -EBADMSG;
200 }
201
202 *slots -= mei_data2slots(sizeof(struct hbm_flow_control));
203
658 if (mei_send_flow_control(dev, cl)) {
204 if (mei_hbm_cl_flow_control_req(dev, cl)) {
659 cl->status = -ENODEV;
660 cb_pos->buf_idx = 0;
661 list_move_tail(&cb_pos->list, &cmpl_list->list);
662 return -ENODEV;
663 }
664 list_move_tail(&cb_pos->list, &dev->read_list.list);
665
666 return 0;

--- 19 unchanged lines hidden (view full) ---

686 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
687 sizeof(struct hbm_client_connect_request))) {
688 /* return the cancel routine */
689 list_del(&cb_pos->list);
690 return -EBADMSG;
691 }
692
693 cl->state = MEI_FILE_CONNECTING;
205 cl->status = -ENODEV;
206 cb_pos->buf_idx = 0;
207 list_move_tail(&cb_pos->list, &cmpl_list->list);
208 return -ENODEV;
209 }
210 list_move_tail(&cb_pos->list, &dev->read_list.list);
211
212 return 0;

--- 19 unchanged lines hidden (view full) ---

232 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) +
233 sizeof(struct hbm_client_connect_request))) {
234 /* return the cancel routine */
235 list_del(&cb_pos->list);
236 return -EBADMSG;
237 }
238
239 cl->state = MEI_FILE_CONNECTING;
694 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
695 if (mei_connect(dev, cl)) {
240 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request));
241 if (mei_hbm_cl_connect_req(dev, cl)) {
696 cl->status = -ENODEV;
697 cb_pos->buf_idx = 0;
698 list_del(&cb_pos->list);
699 return -ENODEV;
700 } else {
701 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
702 cl->timer_count = MEI_CONNECT_TIMEOUT;
703 }

--- 8 unchanged lines hidden (view full) ---

712 * @cb: callback block.
713 * @cmpl_list: complete list.
714 *
715 * returns 0, OK; otherwise, error.
716 */
717static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
718 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
719{
242 cl->status = -ENODEV;
243 cb_pos->buf_idx = 0;
244 list_del(&cb_pos->list);
245 return -ENODEV;
246 } else {
247 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list);
248 cl->timer_count = MEI_CONNECT_TIMEOUT;
249 }

--- 8 unchanged lines hidden (view full) ---

258 * @cb: callback block.
259 * @cmpl_list: complete list.
260 *
261 * returns 0, OK; otherwise, error.
262 */
263static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots,
264 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list)
265{
720 struct mei_msg_hdr *mei_hdr;
266 struct mei_msg_hdr mei_hdr;
721 struct mei_cl *cl = cb->cl;
722 size_t len = cb->request_buffer.size - cb->buf_idx;
723 size_t msg_slots = mei_data2slots(len);
724
267 struct mei_cl *cl = cb->cl;
268 size_t len = cb->request_buffer.size - cb->buf_idx;
269 size_t msg_slots = mei_data2slots(len);
270
725 mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0];
726 mei_hdr->host_addr = cl->host_client_id;
727 mei_hdr->me_addr = cl->me_client_id;
728 mei_hdr->reserved = 0;
271 mei_hdr.host_addr = cl->host_client_id;
272 mei_hdr.me_addr = cl->me_client_id;
273 mei_hdr.reserved = 0;
729
730 if (*slots >= msg_slots) {
274
275 if (*slots >= msg_slots) {
731 mei_hdr->length = len;
732 mei_hdr->msg_complete = 1;
276 mei_hdr.length = len;
277 mei_hdr.msg_complete = 1;
733 /* Split the message only if we can write the whole host buffer */
734 } else if (*slots == dev->hbuf_depth) {
735 msg_slots = *slots;
736 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
278 /* Split the message only if we can write the whole host buffer */
279 } else if (*slots == dev->hbuf_depth) {
280 msg_slots = *slots;
281 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr);
737 mei_hdr->length = len;
738 mei_hdr->msg_complete = 0;
282 mei_hdr.length = len;
283 mei_hdr.msg_complete = 0;
739 } else {
740 /* wait for next time the host buffer is empty */
741 return 0;
742 }
743
744 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
745 cb->request_buffer.size, cb->buf_idx);
284 } else {
285 /* wait for next time the host buffer is empty */
286 return 0;
287 }
288
289 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n",
290 cb->request_buffer.size, cb->buf_idx);
746 dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n",
747 mei_hdr->length, mei_hdr->msg_complete);
291 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr));
748
749 *slots -= msg_slots;
292
293 *slots -= msg_slots;
750 if (mei_write_message(dev, mei_hdr,
751 cb->request_buffer.data + cb->buf_idx, len)) {
294 if (mei_write_message(dev, &mei_hdr,
295 cb->request_buffer.data + cb->buf_idx)) {
752 cl->status = -ENODEV;
753 list_move_tail(&cb->list, &cmpl_list->list);
754 return -ENODEV;
755 }
756
296 cl->status = -ENODEV;
297 list_move_tail(&cb->list, &cmpl_list->list);
298 return -ENODEV;
299 }
300
757 if (mei_flow_ctrl_reduce(dev, cl))
301 if (mei_cl_flow_ctrl_reduce(cl))
758 return -ENODEV;
759
760 cl->status = 0;
302 return -ENODEV;
303
304 cl->status = 0;
761 cb->buf_idx += mei_hdr->length;
762 if (mei_hdr->msg_complete)
305 cb->buf_idx += mei_hdr.length;
306 if (mei_hdr.msg_complete)
763 list_move_tail(&cb->list, &dev->write_waiting_list.list);
764
765 return 0;
766}
767
768/**
769 * mei_irq_thread_read_handler - bottom half read routine after ISR to
770 * handle the read processing.

--- 9 unchanged lines hidden (view full) ---

780 s32 *slots)
781{
782 struct mei_msg_hdr *mei_hdr;
783 struct mei_cl *cl_pos = NULL;
784 struct mei_cl *cl_next = NULL;
785 int ret = 0;
786
787 if (!dev->rd_msg_hdr) {
307 list_move_tail(&cb->list, &dev->write_waiting_list.list);
308
309 return 0;
310}
311
312/**
313 * mei_irq_thread_read_handler - bottom half read routine after ISR to
314 * handle the read processing.

--- 9 unchanged lines hidden (view full) ---

324 s32 *slots)
325{
326 struct mei_msg_hdr *mei_hdr;
327 struct mei_cl *cl_pos = NULL;
328 struct mei_cl *cl_next = NULL;
329 int ret = 0;
330
331 if (!dev->rd_msg_hdr) {
788 dev->rd_msg_hdr = mei_mecbrw_read(dev);
332 dev->rd_msg_hdr = mei_read_hdr(dev);
789 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
790 (*slots)--;
791 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
792 }
793 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
333 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
334 (*slots)--;
335 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots);
336 }
337 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr;
794 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length);
338 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
795
796 if (mei_hdr->reserved || !dev->rd_msg_hdr) {
797 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
798 ret = -EBADMSG;
799 goto end;
800 }
801
802 if (mei_hdr->host_addr || mei_hdr->me_addr) {

--- 22 unchanged lines hidden (view full) ---

825 /* we can't read the message */
826 ret = -ERANGE;
827 goto end;
828 }
829
830 /* decide where to read the message too */
831 if (!mei_hdr->host_addr) {
832 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
339
340 if (mei_hdr->reserved || !dev->rd_msg_hdr) {
341 dev_dbg(&dev->pdev->dev, "corrupted message header.\n");
342 ret = -EBADMSG;
343 goto end;
344 }
345
346 if (mei_hdr->host_addr || mei_hdr->me_addr) {

--- 22 unchanged lines hidden (view full) ---

369 /* we can't read the message */
370 ret = -ERANGE;
371 goto end;
372 }
373
374 /* decide where to read the message too */
375 if (!mei_hdr->host_addr) {
376 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n");
833 mei_irq_thread_read_bus_message(dev, mei_hdr);
377 mei_hbm_dispatch(dev, mei_hdr);
834 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
835 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
836 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
837 (dev->iamthif_state == MEI_IAMTHIF_READING)) {
838 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
378 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n");
379 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id &&
380 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) &&
381 (dev->iamthif_state == MEI_IAMTHIF_READING)) {
382 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n");
839 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n",
840 mei_hdr->length);
841
383
384 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr));
385
842 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
843 if (ret)
844 goto end;
386 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr);
387 if (ret)
388 goto end;
845
846 } else {
847 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
848 ret = mei_irq_thread_read_client_message(cmpl_list,
849 dev, mei_hdr);
850 if (ret)
851 goto end;
852
853 }

--- 28 unchanged lines hidden (view full) ---

882{
883
884 struct mei_cl *cl;
885 struct mei_cl_cb *pos = NULL, *next = NULL;
886 struct mei_cl_cb *list;
887 s32 slots;
888 int ret;
889
389 } else {
390 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n");
391 ret = mei_irq_thread_read_client_message(cmpl_list,
392 dev, mei_hdr);
393 if (ret)
394 goto end;
395
396 }

--- 28 unchanged lines hidden (view full) ---

425{
426
427 struct mei_cl *cl;
428 struct mei_cl_cb *pos = NULL, *next = NULL;
429 struct mei_cl_cb *list;
430 s32 slots;
431 int ret;
432
890 if (!mei_hbuf_is_empty(dev)) {
433 if (!mei_hbuf_is_ready(dev)) {
891 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
892 return 0;
893 }
894 slots = mei_hbuf_empty_slots(dev);
895 if (slots <= 0)
896 return -EMSGSIZE;
897
898 /* complete all waiting for write CB */

--- 26 unchanged lines hidden (view full) ---

925
926 if (dev->wd_state == MEI_WD_STOPPING) {
927 dev->wd_state = MEI_WD_IDLE;
928 wake_up_interruptible(&dev->wait_stop_wd);
929 }
930
931 if (dev->wr_ext_msg.hdr.length) {
932 mei_write_message(dev, &dev->wr_ext_msg.hdr,
434 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n");
435 return 0;
436 }
437 slots = mei_hbuf_empty_slots(dev);
438 if (slots <= 0)
439 return -EMSGSIZE;
440
441 /* complete all waiting for write CB */

--- 26 unchanged lines hidden (view full) ---

468
469 if (dev->wd_state == MEI_WD_STOPPING) {
470 dev->wd_state = MEI_WD_IDLE;
471 wake_up_interruptible(&dev->wait_stop_wd);
472 }
473
474 if (dev->wr_ext_msg.hdr.length) {
475 mei_write_message(dev, &dev->wr_ext_msg.hdr,
933 dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length);
476 dev->wr_ext_msg.data);
934 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
935 dev->wr_ext_msg.hdr.length = 0;
936 }
937 if (dev->dev_state == MEI_DEV_ENABLED) {
938 if (dev->wd_pending &&
477 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length);
478 dev->wr_ext_msg.hdr.length = 0;
479 }
480 if (dev->dev_state == MEI_DEV_ENABLED) {
481 if (dev->wd_pending &&
939 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) {
482 mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) {
940 if (mei_wd_send(dev))
941 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
483 if (mei_wd_send(dev))
484 dev_dbg(&dev->pdev->dev, "wd send failed.\n");
942 else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl))
485 else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl))
943 return -ENODEV;
944
945 dev->wd_pending = false;
946
947 if (dev->wd_state == MEI_WD_RUNNING)
948 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
949 else
950 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);

--- 22 unchanged lines hidden (view full) ---

973 ret = _mei_irq_thread_read(dev, &slots, pos,
974 cl, cmpl_list);
975 if (ret)
976 return ret;
977
978 break;
979 case MEI_FOP_IOCTL:
980 /* connect message */
486 return -ENODEV;
487
488 dev->wd_pending = false;
489
490 if (dev->wd_state == MEI_WD_RUNNING)
491 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE);
492 else
493 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE);

--- 22 unchanged lines hidden (view full) ---

516 ret = _mei_irq_thread_read(dev, &slots, pos,
517 cl, cmpl_list);
518 if (ret)
519 return ret;
520
521 break;
522 case MEI_FOP_IOCTL:
523 /* connect message */
981 if (mei_other_client_is_connecting(dev, cl))
524 if (mei_cl_is_other_connecting(cl))
982 continue;
983 ret = _mei_irq_thread_ioctl(dev, &slots, pos,
984 cl, cmpl_list);
985 if (ret)
986 return ret;
987
988 break;
989
990 default:
991 BUG();
992 }
993
994 }
995 /* complete write list CB */
996 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
997 list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
998 cl = pos->cl;
999 if (cl == NULL)
1000 continue;
525 continue;
526 ret = _mei_irq_thread_ioctl(dev, &slots, pos,
527 cl, cmpl_list);
528 if (ret)
529 return ret;
530
531 break;
532
533 default:
534 BUG();
535 }
536
537 }
538 /* complete write list CB */
539 dev_dbg(&dev->pdev->dev, "complete write list cb.\n");
540 list_for_each_entry_safe(pos, next, &dev->write_list.list, list) {
541 cl = pos->cl;
542 if (cl == NULL)
543 continue;
1001 if (mei_flow_ctrl_creds(dev, cl) <= 0) {
544 if (mei_cl_flow_ctrl_creds(cl) <= 0) {
1002 dev_dbg(&dev->pdev->dev,
1003 "No flow control credentials for client %d, not sending.\n",
1004 cl->host_client_id);
1005 continue;
1006 }
1007
1008 if (cl == &dev->iamthif_cl)
1009 ret = mei_amthif_irq_write_complete(dev, &slots,

--- 133 unchanged lines hidden (view full) ---

1143 int rets;
1144 bool bus_message_received;
1145
1146
1147 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
1148 /* initialize our complete list */
1149 mutex_lock(&dev->device_lock);
1150 mei_io_list_init(&complete_list);
545 dev_dbg(&dev->pdev->dev,
546 "No flow control credentials for client %d, not sending.\n",
547 cl->host_client_id);
548 continue;
549 }
550
551 if (cl == &dev->iamthif_cl)
552 ret = mei_amthif_irq_write_complete(dev, &slots,

--- 133 unchanged lines hidden (view full) ---

686 int rets;
687 bool bus_message_received;
688
689
690 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n");
691 /* initialize our complete list */
692 mutex_lock(&dev->device_lock);
693 mei_io_list_init(&complete_list);
1151 dev->host_hw_state = mei_hcsr_read(dev);
1152
1153 /* Ack the interrupt here
1154 * In case of MSI we don't go through the quick handler */
1155 if (pci_dev_msi_enabled(dev->pdev))
694
695 /* Ack the interrupt here
696 * In case of MSI we don't go through the quick handler */
697 if (pci_dev_msi_enabled(dev->pdev))
1156 mei_reg_write(dev, H_CSR, dev->host_hw_state);
698 mei_clear_interrupts(dev);
1157
699
1158 dev->me_hw_state = mei_mecsr_read(dev);
1159
1160 /* check if ME wants a reset */
700 /* check if ME wants a reset */
1161 if ((dev->me_hw_state & ME_RDY_HRA) == 0 &&
701 if (!mei_hw_is_ready(dev) &&
1162 dev->dev_state != MEI_DEV_RESETING &&
1163 dev->dev_state != MEI_DEV_INITIALIZING) {
1164 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1165 mei_reset(dev, 1);
1166 mutex_unlock(&dev->device_lock);
1167 return IRQ_HANDLED;
1168 }
1169
1170 /* check if we need to start the dev */
702 dev->dev_state != MEI_DEV_RESETING &&
703 dev->dev_state != MEI_DEV_INITIALIZING) {
704 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
705 mei_reset(dev, 1);
706 mutex_unlock(&dev->device_lock);
707 return IRQ_HANDLED;
708 }
709
710 /* check if we need to start the dev */
1171 if ((dev->host_hw_state & H_RDY) == 0) {
1172 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) {
711 if (!mei_host_is_ready(dev)) {
712 if (mei_hw_is_ready(dev)) {
1173 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
713 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n");
1174 dev->host_hw_state |= (H_IE | H_IG | H_RDY);
1175 mei_hcsr_set(dev);
1176 dev->dev_state = MEI_DEV_INIT_CLIENTS;
714
715 mei_host_set_ready(dev);
716
1177 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
717 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n");
1178 /* link is established
1179 * start sending messages.
1180 */
1181 mei_host_start_message(dev);
718 /* link is established * start sending messages. */
719
720 dev->dev_state = MEI_DEV_INIT_CLIENTS;
721
722 mei_hbm_start_req(dev);
1182 mutex_unlock(&dev->device_lock);
1183 return IRQ_HANDLED;
1184 } else {
1185 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
1186 mutex_unlock(&dev->device_lock);
1187 return IRQ_HANDLED;
1188 }
1189 }

--- 7 unchanged lines hidden (view full) ---

1197 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
1198 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
1199 if (rets)
1200 goto end;
1201 }
1202 rets = mei_irq_thread_write_handler(dev, &complete_list);
1203end:
1204 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
723 mutex_unlock(&dev->device_lock);
724 return IRQ_HANDLED;
725 } else {
726 dev_dbg(&dev->pdev->dev, "FW not ready.\n");
727 mutex_unlock(&dev->device_lock);
728 return IRQ_HANDLED;
729 }
730 }

--- 7 unchanged lines hidden (view full) ---

738 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n");
739 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots);
740 if (rets)
741 goto end;
742 }
743 rets = mei_irq_thread_write_handler(dev, &complete_list);
744end:
745 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n");
1205 dev->host_hw_state = mei_hcsr_read(dev);
1206 dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev);
746 dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev);
1207
1208 bus_message_received = false;
1209 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
1210 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
1211 bus_message_received = true;
1212 }
1213 mutex_unlock(&dev->device_lock);
1214 if (bus_message_received) {

--- 23 unchanged lines hidden ---
747
748 bus_message_received = false;
749 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) {
750 dev_dbg(&dev->pdev->dev, "received waiting bus message\n");
751 bus_message_received = true;
752 }
753 mutex_unlock(&dev->device_lock);
754 if (bus_message_received) {

--- 23 unchanged lines hidden ---