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