aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/misc
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2015-02-10 03:39:39 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-03-01 22:37:00 -0500
commitc54bf3ab7536e062b507b625bfd2befb9b2cb841 (patch)
tree19b872b4941389b2c1b159dcc8b87394822f1383 /drivers/misc
parent4e097bc5d5c948ff8a60ac38a5826f5b6699603d (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.c134
-rw-r--r--drivers/misc/mei/interrupt.c25
-rw-r--r--drivers/misc/mei/mei_dev.h2
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 */
265static 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;
293err:
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 */
337int mei_amthif_write(struct mei_device *dev, struct mei_cl_cb *cb) 377int 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 */
510int mei_amthif_irq_read_msg(struct mei_cl *cl, 537int 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 */
575int 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 */
605void mei_amthif_complete(struct mei_device *dev, struct mei_cl_cb *cb) 602void 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;