diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2015-02-10 03:39:39 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2015-03-01 22:37:00 -0500 |
commit | c54bf3ab7536e062b507b625bfd2befb9b2cb841 (patch) | |
tree | 19b872b4941389b2c1b159dcc8b87394822f1383 /drivers/misc | |
parent | 4e097bc5d5c948ff8a60ac38a5826f5b6699603d (diff) |
mei: iamthif: send flow control as a regular client
Reuse common client mechanism for sending flow control
hbm message. Add new function mei_amthif_read_start
similar to mei_cl_read_start that puts control flow request
onto the control write queue and drop mei_amthif_irq_read function
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc')
-rw-r--r-- | drivers/misc/mei/amthif.c | 134 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 25 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 2 |
3 files changed, 77 insertions, 84 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 788b00e23353..e6f7180fd8f2 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -255,6 +255,47 @@ out: | |||
255 | } | 255 | } |
256 | 256 | ||
257 | /** | 257 | /** |
258 | * mei_amthif_read_start - queue message for sending read credential | ||
259 | * | ||
260 | * @cl: host client | ||
261 | * @file: file pointer of message recipient | ||
262 | * | ||
263 | * Return: 0 on success, <0 on failure. | ||
264 | */ | ||
265 | static int mei_amthif_read_start(struct mei_cl *cl, struct file *file) | ||
266 | { | ||
267 | struct mei_device *dev = cl->dev; | ||
268 | struct mei_cl_cb *cb; | ||
269 | size_t length = dev->iamthif_mtu; | ||
270 | int rets; | ||
271 | |||
272 | cb = mei_io_cb_init(cl, file); | ||
273 | if (!cb) { | ||
274 | rets = -ENOMEM; | ||
275 | goto err; | ||
276 | } | ||
277 | |||
278 | rets = mei_io_cb_alloc_resp_buf(cb, length); | ||
279 | if (rets) | ||
280 | goto err; | ||
281 | |||
282 | cb->fop_type = MEI_FOP_READ; | ||
283 | list_add_tail(&cb->list, &dev->ctrl_wr_list.list); | ||
284 | |||
285 | dev->iamthif_msg_buf_index = 0; | ||
286 | dev->iamthif_msg_buf_size = 0; | ||
287 | |||
288 | dev->iamthif_state = MEI_IAMTHIF_READING; | ||
289 | dev->iamthif_file_object = cb->file_object; | ||
290 | dev->iamthif_current_cb = cb; | ||
291 | |||
292 | return 0; | ||
293 | err: | ||
294 | mei_io_cb_free(cb); | ||
295 | return rets; | ||
296 | } | ||
297 | |||
298 | /** | ||
258 | * mei_amthif_send_cmd - send amthif command to the ME | 299 | * mei_amthif_send_cmd - send amthif command to the ME |
259 | * | 300 | * |
260 | * @dev: the device structure | 301 | * @dev: the device structure |
@@ -287,6 +328,7 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | |||
287 | if (ret < 0) | 328 | if (ret < 0) |
288 | return ret; | 329 | return ret; |
289 | 330 | ||
331 | cb->fop_type = MEI_FOP_WRITE; | ||
290 | if (ret && mei_hbuf_acquire(dev)) { | 332 | if (ret && mei_hbuf_acquire(dev)) { |
291 | ret = 0; | 333 | ret = 0; |
292 | if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { | 334 | if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { |
@@ -309,19 +351,17 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | |||
309 | if (mei_hdr.msg_complete) { | 351 | if (mei_hdr.msg_complete) { |
310 | if (mei_cl_flow_ctrl_reduce(cl)) | 352 | if (mei_cl_flow_ctrl_reduce(cl)) |
311 | return -EIO; | 353 | return -EIO; |
312 | dev->iamthif_flow_control_pending = true; | 354 | cb->status = mei_amthif_read_start(cl, cb->file_object); |
313 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | ||
314 | dev_dbg(dev->dev, "add amthif cb to write waiting list\n"); | ||
315 | dev->iamthif_current_cb = cb; | ||
316 | dev->iamthif_file_object = cb->file_object; | ||
317 | list_add_tail(&cb->list, &dev->write_waiting_list.list); | 355 | list_add_tail(&cb->list, &dev->write_waiting_list.list); |
318 | } else { | 356 | } else { |
319 | dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n"); | 357 | dev_dbg(dev->dev, "message does not complete, so add amthif cb to write list.\n"); |
320 | list_add_tail(&cb->list, &dev->write_list.list); | 358 | list_add_tail(&cb->list, &dev->write_list.list); |
321 | } | 359 | } |
322 | } else { | 360 | } else { |
361 | |||
323 | list_add_tail(&cb->list, &dev->write_list.list); | 362 | list_add_tail(&cb->list, &dev->write_list.list); |
324 | } | 363 | } |
364 | |||
325 | return 0; | 365 | return 0; |
326 | } | 366 | } |
327 | 367 | ||
@@ -336,17 +376,10 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | |||
336 | */ | 376 | */ |
337 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) | 377 | int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) |
338 | { | 378 | { |
339 | int ret; | ||
340 | |||
341 | if (!dev || !cb) | 379 | if (!dev || !cb) |
342 | return -ENODEV; | 380 | return -ENODEV; |
343 | 381 | ||
344 | ret = mei_io_cb_alloc_resp_buf(cb, dev->iamthif_mtu); | ||
345 | if (ret) | ||
346 | return ret; | ||
347 | |||
348 | cb->fop_type = MEI_FOP_WRITE; | 382 | cb->fop_type = MEI_FOP_WRITE; |
349 | |||
350 | if (!list_empty(&dev->amthif_cmd_list.list) || | 383 | if (!list_empty(&dev->amthif_cmd_list.list) || |
351 | dev->iamthif_state != MEI_IAMTHIF_IDLE) { | 384 | dev->iamthif_state != MEI_IAMTHIF_IDLE) { |
352 | dev_dbg(dev->dev, | 385 | dev_dbg(dev->dev, |
@@ -383,7 +416,7 @@ void mei_amthif_run_next_cmd(struct mei_device *dev) | |||
383 | typeof(*cb), list); | 416 | typeof(*cb), list); |
384 | if (!cb) | 417 | if (!cb) |
385 | return; | 418 | return; |
386 | list_del(&cb->list); | 419 | list_del_init(&cb->list); |
387 | ret = mei_amthif_send_cmd(dev, cb); | 420 | ret = mei_amthif_send_cmd(dev, cb); |
388 | if (ret) | 421 | if (ret) |
389 | dev_warn(dev->dev, "amthif write failed status = %d\n", ret); | 422 | dev_warn(dev->dev, "amthif write failed status = %d\n", ret); |
@@ -483,13 +516,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, | |||
483 | cl->status = 0; | 516 | cl->status = 0; |
484 | 517 | ||
485 | if (mei_hdr.msg_complete) { | 518 | if (mei_hdr.msg_complete) { |
486 | dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; | 519 | cb->status = mei_amthif_read_start(cl, cb->file_object); |
487 | dev->iamthif_flow_control_pending = true; | ||
488 | |||
489 | /* save iamthif cb sent to amthif client */ | ||
490 | cb->buf_idx = dev->iamthif_msg_buf_index; | ||
491 | dev->iamthif_current_cb = cb; | ||
492 | |||
493 | list_move_tail(&cb->list, &dev->write_waiting_list.list); | 520 | list_move_tail(&cb->list, &dev->write_waiting_list.list); |
494 | } | 521 | } |
495 | 522 | ||
@@ -505,7 +532,7 @@ int mei_amthif_irq_write(struct mei_cl *cl, struct mei_cl_cb *cb, | |||
505 | * @mei_hdr: header of amthif message | 532 | * @mei_hdr: header of amthif message |
506 | * @complete_list: completed callbacks list | 533 | * @complete_list: completed callbacks list |
507 | * | 534 | * |
508 | * Return: -ENODEV if cb is NULL 0 otherwise; error message is in cb->status | 535 | * Return: Always 0; error message is in cb->status |
509 | */ | 536 | */ |
510 | int mei_amthif_irq_read_msg(struct mei_cl *cl, | 537 | int mei_amthif_irq_read_msg(struct mei_cl *cl, |
511 | struct mei_msg_hdr *mei_hdr, | 538 | struct mei_msg_hdr *mei_hdr, |
@@ -514,7 +541,6 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, | |||
514 | struct mei_device *dev; | 541 | struct mei_device *dev; |
515 | struct mei_cl_cb *cb; | 542 | struct mei_cl_cb *cb; |
516 | unsigned char *buffer; | 543 | unsigned char *buffer; |
517 | int ret = 0; | ||
518 | 544 | ||
519 | dev = cl->dev; | 545 | dev = cl->dev; |
520 | 546 | ||
@@ -524,10 +550,13 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, | |||
524 | if (dev->iamthif_state != MEI_IAMTHIF_READING) | 550 | if (dev->iamthif_state != MEI_IAMTHIF_READING) |
525 | goto err; | 551 | goto err; |
526 | 552 | ||
527 | cb = dev->iamthif_current_cb; | 553 | list_for_each_entry(cb, &dev->read_list.list, list) { |
554 | if (cl == cb->cl) | ||
555 | break; | ||
556 | } | ||
528 | 557 | ||
529 | if (!cb) { | 558 | if (&cb->list == &dev->read_list.list) { |
530 | ret = -ENODEV; | 559 | dev_err(dev->dev, "no reader found\n"); |
531 | goto err; | 560 | goto err; |
532 | } | 561 | } |
533 | 562 | ||
@@ -553,7 +582,7 @@ int mei_amthif_irq_read_msg(struct mei_cl *cl, | |||
553 | cb->read_time = jiffies; | 582 | cb->read_time = jiffies; |
554 | 583 | ||
555 | dev_dbg(dev->dev, "complete the amthif read cb.\n "); | 584 | dev_dbg(dev->dev, "complete the amthif read cb.\n "); |
556 | list_add_tail(&cb->list, &complete_list->list); | 585 | list_move_tail(&cb->list, &complete_list->list); |
557 | 586 | ||
558 | return 0; | 587 | return 0; |
559 | 588 | ||
@@ -561,38 +590,6 @@ err: | |||
561 | mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); | 590 | mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); |
562 | dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n", | 591 | dev_dbg(dev->dev, "discarding message " MEI_HDR_FMT "\n", |
563 | MEI_HDR_PRM(mei_hdr)); | 592 | MEI_HDR_PRM(mei_hdr)); |
564 | return ret; | ||
565 | } | ||
566 | |||
567 | /** | ||
568 | * mei_amthif_irq_read - prepares to read amthif data. | ||
569 | * | ||
570 | * @dev: the device structure. | ||
571 | * @slots: free slots. | ||
572 | * | ||
573 | * Return: 0, OK; otherwise, error. | ||
574 | */ | ||
575 | int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) | ||
576 | { | ||
577 | u32 msg_slots = mei_data2slots(sizeof(struct hbm_flow_control)); | ||
578 | |||
579 | if (*slots < msg_slots) | ||
580 | return -EMSGSIZE; | ||
581 | |||
582 | *slots -= msg_slots; | ||
583 | |||
584 | if (mei_hbm_cl_flow_control_req(dev, &dev->iamthif_cl)) { | ||
585 | dev_dbg(dev->dev, "iamthif flow control failed\n"); | ||
586 | return -EIO; | ||
587 | } | ||
588 | |||
589 | dev_dbg(dev->dev, "iamthif flow control success\n"); | ||
590 | dev->iamthif_state = MEI_IAMTHIF_READING; | ||
591 | dev->iamthif_flow_control_pending = false; | ||
592 | dev->iamthif_msg_buf_index = 0; | ||
593 | dev->iamthif_msg_buf_size = 0; | ||
594 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; | ||
595 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); | ||
596 | return 0; | 593 | return 0; |
597 | } | 594 | } |
598 | 595 | ||
@@ -604,17 +601,32 @@ int mei_amthif_irq_read(struct mei_device *dev, s32 *slots) | |||
604 | */ | 601 | */ |
605 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) | 602 | void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) |
606 | { | 603 | { |
604 | |||
605 | if (cb->fop_type == MEI_FOP_WRITE) { | ||
606 | if (!cb->status) { | ||
607 | dev->iamthif_stall_timer = MEI_IAMTHIF_STALL_TIMER; | ||
608 | mei_io_cb_free(cb); | ||
609 | return; | ||
610 | } | ||
611 | /* | ||
612 | * in case of error enqueue the write cb to complete read list | ||
613 | * so it can be propagated to the reader | ||
614 | */ | ||
615 | list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); | ||
616 | wake_up_interruptible(&dev->iamthif_cl.wait); | ||
617 | return; | ||
618 | } | ||
619 | |||
607 | if (dev->iamthif_canceled != 1) { | 620 | if (dev->iamthif_canceled != 1) { |
608 | dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; | 621 | dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; |
609 | dev->iamthif_stall_timer = 0; | 622 | dev->iamthif_stall_timer = 0; |
610 | memcpy(cb->response_buffer.data, | 623 | memcpy(cb->response_buffer.data, |
611 | dev->iamthif_msg_buf, | 624 | dev->iamthif_msg_buf, dev->iamthif_msg_buf_index); |
612 | dev->iamthif_msg_buf_index); | ||
613 | list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); | 625 | list_add_tail(&cb->list, &dev->amthif_rd_complete_list.list); |
614 | dev_dbg(dev->dev, "amthif read completed\n"); | 626 | dev_dbg(dev->dev, "amthif read completed\n"); |
615 | dev->iamthif_timer = jiffies; | 627 | dev->iamthif_timer = jiffies; |
616 | dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", | 628 | dev_dbg(dev->dev, "dev->iamthif_timer = %ld\n", |
617 | dev->iamthif_timer); | 629 | dev->iamthif_timer); |
618 | } else { | 630 | } else { |
619 | mei_amthif_run_next_cmd(dev); | 631 | mei_amthif_run_next_cmd(dev); |
620 | } | 632 | } |
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 4cb602fba593..89f2fbce160f 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -43,7 +43,7 @@ void mei_irq_compl_handler(struct mei_device *dev, struct mei_cl_cb *compl_list) | |||
43 | 43 | ||
44 | list_for_each_entry_safe(cb, next, &compl_list->list, list) { | 44 | list_for_each_entry_safe(cb, next, &compl_list->list, list) { |
45 | cl = cb->cl; | 45 | cl = cb->cl; |
46 | list_del(&cb->list); | 46 | list_del_init(&cb->list); |
47 | 47 | ||
48 | dev_dbg(dev->dev, "completing call back.\n"); | 48 | dev_dbg(dev->dev, "completing call back.\n"); |
49 | if (cl == &dev->iamthif_cl) | 49 | if (cl == &dev->iamthif_cl) |
@@ -386,11 +386,6 @@ int mei_irq_read_handler(struct mei_device *dev, | |||
386 | 386 | ||
387 | if (cl == &dev->iamthif_cl) { | 387 | if (cl == &dev->iamthif_cl) { |
388 | ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list); | 388 | ret = mei_amthif_irq_read_msg(cl, mei_hdr, cmpl_list); |
389 | if (ret) { | ||
390 | dev_err(dev->dev, "mei_amthif_irq_read_msg failed = %d\n", | ||
391 | ret); | ||
392 | goto end; | ||
393 | } | ||
394 | } else { | 389 | } else { |
395 | ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list); | 390 | ret = mei_cl_irq_read_msg(cl, mei_hdr, cmpl_list); |
396 | } | 391 | } |
@@ -448,21 +443,9 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
448 | cl = cb->cl; | 443 | cl = cb->cl; |
449 | 444 | ||
450 | cl->status = 0; | 445 | cl->status = 0; |
451 | list_del(&cb->list); | 446 | cl_dbg(dev, cl, "MEI WRITE COMPLETE\n"); |
452 | if (cb->fop_type == MEI_FOP_WRITE && | 447 | cl->writing_state = MEI_WRITE_COMPLETE; |
453 | cl != &dev->iamthif_cl) { | 448 | list_move_tail(&cb->list, &cmpl_list->list); |
454 | cl_dbg(dev, cl, "MEI WRITE COMPLETE\n"); | ||
455 | cl->writing_state = MEI_WRITE_COMPLETE; | ||
456 | list_add_tail(&cb->list, &cmpl_list->list); | ||
457 | } | ||
458 | if (cl == &dev->iamthif_cl) { | ||
459 | cl_dbg(dev, cl, "check iamthif flow control.\n"); | ||
460 | if (dev->iamthif_flow_control_pending) { | ||
461 | ret = mei_amthif_irq_read(dev, &slots); | ||
462 | if (ret) | ||
463 | return ret; | ||
464 | } | ||
465 | } | ||
466 | } | 449 | } |
467 | 450 | ||
468 | if (dev->wd_state == MEI_WD_STOPPING) { | 451 | if (dev->wd_state == MEI_WD_STOPPING) { |
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 6cc68de580ba..fc460af131d4 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -487,7 +487,6 @@ const char *mei_pg_state_str(enum mei_pg_state state); | |||
487 | * @iamthif_msg_buf_size : size of current amthif message request buffer | 487 | * @iamthif_msg_buf_size : size of current amthif message request buffer |
488 | * @iamthif_msg_buf_index : current index in amthif message request buffer | 488 | * @iamthif_msg_buf_index : current index in amthif message request buffer |
489 | * @iamthif_state : amthif processor state | 489 | * @iamthif_state : amthif processor state |
490 | * @iamthif_flow_control_pending: amthif waits for flow control | ||
491 | * @iamthif_canceled : current amthif command is canceled | 490 | * @iamthif_canceled : current amthif command is canceled |
492 | * | 491 | * |
493 | * @init_work : work item for the device init | 492 | * @init_work : work item for the device init |
@@ -586,7 +585,6 @@ struct mei_device { | |||
586 | u32 iamthif_msg_buf_size; | 585 | u32 iamthif_msg_buf_size; |
587 | u32 iamthif_msg_buf_index; | 586 | u32 iamthif_msg_buf_index; |
588 | enum iamthif_states iamthif_state; | 587 | enum iamthif_states iamthif_state; |
589 | bool iamthif_flow_control_pending; | ||
590 | bool iamthif_canceled; | 588 | bool iamthif_canceled; |
591 | 589 | ||
592 | struct work_struct init_work; | 590 | struct work_struct init_work; |