diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2014-02-19 10:35:47 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-02-28 18:15:56 -0500 |
commit | 6aae48ff18f2fcfb533d2b448ecae16d1de006c1 (patch) | |
tree | 1e886fe2f579ed8dea6f594219e591f7c6820d89 /drivers/misc/mei | |
parent | 4a22176aa89b8121a5160064d77244e26fe38790 (diff) |
mei: add mei_hbuf_acquire wrapper
A client has to acquire host buffer
before writing, we add lock like wrapper
to replace the code snippet
if (dev->hbuf_is_ready)
dev->hbuf_is_ready = false;
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/amthif.c | 7 | ||||
-rw-r--r-- | drivers/misc/mei/client.c | 56 | ||||
-rw-r--r-- | drivers/misc/mei/hw-me.c | 2 | ||||
-rw-r--r-- | drivers/misc/mei/hw-txe.c | 17 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 6 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 2 | ||||
-rw-r--r-- | drivers/misc/mei/wd.c | 14 |
7 files changed, 57 insertions, 47 deletions
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c index 61275e6e839c..e7ba8801d2b4 100644 --- a/drivers/misc/mei/amthif.c +++ b/drivers/misc/mei/amthif.c | |||
@@ -296,9 +296,8 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | |||
296 | if (ret < 0) | 296 | if (ret < 0) |
297 | return ret; | 297 | return ret; |
298 | 298 | ||
299 | if (ret && dev->hbuf_is_ready) { | 299 | if (ret && mei_hbuf_acquire(dev)) { |
300 | ret = 0; | 300 | ret = 0; |
301 | dev->hbuf_is_ready = false; | ||
302 | if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { | 301 | if (cb->request_buffer.size > mei_hbuf_max_len(dev)) { |
303 | mei_hdr.length = mei_hbuf_max_len(dev); | 302 | mei_hdr.length = mei_hbuf_max_len(dev); |
304 | mei_hdr.msg_complete = 0; | 303 | mei_hdr.msg_complete = 0; |
@@ -330,10 +329,6 @@ static int mei_amthif_send_cmd(struct mei_device *dev, struct mei_cl_cb *cb) | |||
330 | list_add_tail(&cb->list, &dev->write_list.list); | 329 | list_add_tail(&cb->list, &dev->write_list.list); |
331 | } | 330 | } |
332 | } else { | 331 | } else { |
333 | if (!dev->hbuf_is_ready) | ||
334 | dev_dbg(&dev->pdev->dev, "host buffer is not empty"); | ||
335 | |||
336 | dev_dbg(&dev->pdev->dev, "No flow control credentials, so add iamthif cb to write list.\n"); | ||
337 | list_add_tail(&cb->list, &dev->write_list.list); | 332 | list_add_tail(&cb->list, &dev->write_list.list); |
338 | } | 333 | } |
339 | return 0; | 334 | return 0; |
diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 2df0efab00a2..083179b75297 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c | |||
@@ -371,6 +371,23 @@ void mei_host_client_init(struct work_struct *work) | |||
371 | mutex_unlock(&dev->device_lock); | 371 | mutex_unlock(&dev->device_lock); |
372 | } | 372 | } |
373 | 373 | ||
374 | /** | ||
375 | * mei_hbuf_acquire: try to acquire host buffer | ||
376 | * | ||
377 | * @dev: the device structure | ||
378 | * returns true if host buffer was acquired | ||
379 | */ | ||
380 | bool mei_hbuf_acquire(struct mei_device *dev) | ||
381 | { | ||
382 | if (!dev->hbuf_is_ready) { | ||
383 | dev_dbg(&dev->pdev->dev, "hbuf is not ready\n"); | ||
384 | return false; | ||
385 | } | ||
386 | |||
387 | dev->hbuf_is_ready = false; | ||
388 | |||
389 | return true; | ||
390 | } | ||
374 | 391 | ||
375 | /** | 392 | /** |
376 | * mei_cl_disconnect - disconnect host client from the me one | 393 | * mei_cl_disconnect - disconnect host client from the me one |
@@ -402,8 +419,7 @@ int mei_cl_disconnect(struct mei_cl *cl) | |||
402 | return -ENOMEM; | 419 | return -ENOMEM; |
403 | 420 | ||
404 | cb->fop_type = MEI_FOP_CLOSE; | 421 | cb->fop_type = MEI_FOP_CLOSE; |
405 | if (dev->hbuf_is_ready) { | 422 | if (mei_hbuf_acquire(dev)) { |
406 | dev->hbuf_is_ready = false; | ||
407 | if (mei_hbm_cl_disconnect_req(dev, cl)) { | 423 | if (mei_hbm_cl_disconnect_req(dev, cl)) { |
408 | rets = -ENODEV; | 424 | rets = -ENODEV; |
409 | cl_err(dev, cl, "failed to disconnect.\n"); | 425 | cl_err(dev, cl, "failed to disconnect.\n"); |
@@ -503,9 +519,8 @@ int mei_cl_connect(struct mei_cl *cl, struct file *file) | |||
503 | 519 | ||
504 | cb->fop_type = MEI_FOP_CONNECT; | 520 | cb->fop_type = MEI_FOP_CONNECT; |
505 | 521 | ||
506 | if (dev->hbuf_is_ready && !mei_cl_is_other_connecting(cl)) { | 522 | /* run hbuf acquire last so we don't have to undo */ |
507 | dev->hbuf_is_ready = false; | 523 | if (!mei_cl_is_other_connecting(cl) && mei_hbuf_acquire(dev)) { |
508 | |||
509 | if (mei_hbm_cl_connect_req(dev, cl)) { | 524 | if (mei_hbm_cl_connect_req(dev, cl)) { |
510 | rets = -ENODEV; | 525 | rets = -ENODEV; |
511 | goto out; | 526 | goto out; |
@@ -663,8 +678,7 @@ int mei_cl_read_start(struct mei_cl *cl, size_t length) | |||
663 | goto err; | 678 | goto err; |
664 | 679 | ||
665 | cb->fop_type = MEI_FOP_READ; | 680 | cb->fop_type = MEI_FOP_READ; |
666 | if (dev->hbuf_is_ready) { | 681 | if (mei_hbuf_acquire(dev)) { |
667 | dev->hbuf_is_ready = false; | ||
668 | if (mei_hbm_cl_flow_control_req(dev, cl)) { | 682 | if (mei_hbm_cl_flow_control_req(dev, cl)) { |
669 | cl_err(dev, cl, "flow control send failed\n"); | 683 | cl_err(dev, cl, "flow control send failed\n"); |
670 | rets = -ENODEV; | 684 | rets = -ENODEV; |
@@ -799,21 +813,29 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) | |||
799 | 813 | ||
800 | 814 | ||
801 | cb->fop_type = MEI_FOP_WRITE; | 815 | cb->fop_type = MEI_FOP_WRITE; |
816 | cb->buf_idx = 0; | ||
817 | cl->writing_state = MEI_IDLE; | ||
818 | |||
819 | mei_hdr.host_addr = cl->host_client_id; | ||
820 | mei_hdr.me_addr = cl->me_client_id; | ||
821 | mei_hdr.reserved = 0; | ||
822 | mei_hdr.msg_complete = 0; | ||
823 | mei_hdr.internal = cb->internal; | ||
802 | 824 | ||
803 | rets = mei_cl_flow_ctrl_creds(cl); | 825 | rets = mei_cl_flow_ctrl_creds(cl); |
804 | if (rets < 0) | 826 | if (rets < 0) |
805 | goto err; | 827 | goto err; |
806 | 828 | ||
807 | /* Host buffer is not ready, we queue the request */ | 829 | if (rets == 0) { |
808 | if (rets == 0 || !dev->hbuf_is_ready) { | 830 | cl_dbg(dev, cl, "No flow control credentials: not sending.\n"); |
809 | cb->buf_idx = 0; | 831 | rets = buf->size; |
810 | /* unseting complete will enqueue the cb for write */ | 832 | goto out; |
811 | mei_hdr.msg_complete = 0; | 833 | } |
834 | if (!mei_hbuf_acquire(dev)) { | ||
835 | cl_dbg(dev, cl, "Cannot acquire the host buffer: not sending.\n"); | ||
812 | rets = buf->size; | 836 | rets = buf->size; |
813 | goto out; | 837 | goto out; |
814 | } | 838 | } |
815 | |||
816 | dev->hbuf_is_ready = false; | ||
817 | 839 | ||
818 | /* Check for a maximum length */ | 840 | /* Check for a maximum length */ |
819 | if (buf->size > mei_hbuf_max_len(dev)) { | 841 | if (buf->size > mei_hbuf_max_len(dev)) { |
@@ -824,12 +846,6 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking) | |||
824 | mei_hdr.msg_complete = 1; | 846 | mei_hdr.msg_complete = 1; |
825 | } | 847 | } |
826 | 848 | ||
827 | mei_hdr.host_addr = cl->host_client_id; | ||
828 | mei_hdr.me_addr = cl->me_client_id; | ||
829 | mei_hdr.reserved = 0; | ||
830 | mei_hdr.internal = cb->internal; | ||
831 | |||
832 | |||
833 | rets = mei_write_message(dev, &mei_hdr, buf->data); | 849 | rets = mei_write_message(dev, &mei_hdr, buf->data); |
834 | if (rets) | 850 | if (rets) |
835 | goto err; | 851 | goto err; |
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 847c9e5746cb..b0c42d6182a6 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -513,6 +513,8 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) | |||
513 | } | 513 | } |
514 | } | 514 | } |
515 | 515 | ||
516 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); | ||
517 | |||
516 | rets = mei_irq_write_handler(dev, &complete_list); | 518 | rets = mei_irq_write_handler(dev, &complete_list); |
517 | 519 | ||
518 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); | 520 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); |
diff --git a/drivers/misc/mei/hw-txe.c b/drivers/misc/mei/hw-txe.c index 49a5ed376969..8f5e4be9ebc2 100644 --- a/drivers/misc/mei/hw-txe.c +++ b/drivers/misc/mei/hw-txe.c | |||
@@ -605,7 +605,6 @@ static int mei_txe_write(struct mei_device *dev, | |||
605 | mei_txe_input_payload_write(dev, i + 1, reg); | 605 | mei_txe_input_payload_write(dev, i + 1, reg); |
606 | } | 606 | } |
607 | 607 | ||
608 | dev->hbuf_is_ready = false; | ||
609 | /* Set Input-Doorbell */ | 608 | /* Set Input-Doorbell */ |
610 | mei_txe_input_doorbell_set(hw); | 609 | mei_txe_input_doorbell_set(hw); |
611 | 610 | ||
@@ -983,20 +982,16 @@ irqreturn_t mei_txe_irq_thread_handler(int irq, void *dev_id) | |||
983 | dev->hbuf_is_ready = true; | 982 | dev->hbuf_is_ready = true; |
984 | 983 | ||
985 | if (hw->aliveness && dev->hbuf_is_ready) { | 984 | if (hw->aliveness && dev->hbuf_is_ready) { |
986 | /* if SeC did not complete reading the written data by host */ | ||
987 | if (!mei_txe_is_input_ready(dev)) { | ||
988 | dev_dbg(&dev->pdev->dev, "got Input Ready Int, but SEC_IPC_INPUT_STATUS_RDY is 0.\n"); | ||
989 | goto end; | ||
990 | } | ||
991 | 985 | ||
986 | /* get the real register value */ | ||
987 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); | ||
992 | rets = mei_irq_write_handler(dev, &complete_list); | 988 | rets = mei_irq_write_handler(dev, &complete_list); |
993 | if (rets) | 989 | if (rets && rets != -EMSGSIZE) |
994 | dev_err(&dev->pdev->dev, | 990 | dev_err(&dev->pdev->dev, "mei_irq_write_handler ret = %d.\n", |
995 | "mei_irq_write_handler ret = %d.\n", rets); | 991 | rets); |
992 | dev->hbuf_is_ready = mei_hbuf_is_ready(dev); | ||
996 | } | 993 | } |
997 | 994 | ||
998 | |||
999 | |||
1000 | mei_irq_compl_handler(dev, &complete_list); | 995 | mei_irq_compl_handler(dev, &complete_list); |
1001 | 996 | ||
1002 | end: | 997 | end: |
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 6c4597e9b997..aed03efa72f4 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -446,10 +446,10 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
446 | s32 slots; | 446 | s32 slots; |
447 | int ret; | 447 | int ret; |
448 | 448 | ||
449 | if (!mei_hbuf_is_ready(dev)) { | 449 | |
450 | dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); | 450 | if (!mei_hbuf_acquire(dev)) |
451 | return 0; | 451 | return 0; |
452 | } | 452 | |
453 | slots = mei_hbuf_empty_slots(dev); | 453 | slots = mei_hbuf_empty_slots(dev); |
454 | if (slots <= 0) | 454 | if (slots <= 0) |
455 | return -EMSGSIZE; | 455 | return -EMSGSIZE; |
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index 030b29e1c92e..52499bc5a068 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -630,6 +630,8 @@ static inline int mei_count_full_read_slots(struct mei_device *dev) | |||
630 | return dev->ops->rdbuf_full_slots(dev); | 630 | return dev->ops->rdbuf_full_slots(dev); |
631 | } | 631 | } |
632 | 632 | ||
633 | bool mei_hbuf_acquire(struct mei_device *dev); | ||
634 | |||
633 | #if IS_ENABLED(CONFIG_DEBUG_FS) | 635 | #if IS_ENABLED(CONFIG_DEBUG_FS) |
634 | int mei_dbgfs_register(struct mei_device *dev, const char *name); | 636 | int mei_dbgfs_register(struct mei_device *dev, const char *name); |
635 | void mei_dbgfs_deregister(struct mei_device *dev); | 637 | void mei_dbgfs_deregister(struct mei_device *dev); |
diff --git a/drivers/misc/mei/wd.c b/drivers/misc/mei/wd.c index 8c302829a194..afe976a18586 100644 --- a/drivers/misc/mei/wd.c +++ b/drivers/misc/mei/wd.c | |||
@@ -158,9 +158,8 @@ int mei_wd_stop(struct mei_device *dev) | |||
158 | if (ret < 0) | 158 | if (ret < 0) |
159 | goto out; | 159 | goto out; |
160 | 160 | ||
161 | if (ret && dev->hbuf_is_ready) { | 161 | if (ret && mei_hbuf_acquire(dev)) { |
162 | ret = 0; | 162 | ret = 0; |
163 | dev->hbuf_is_ready = false; | ||
164 | 163 | ||
165 | if (!mei_wd_send(dev)) { | 164 | if (!mei_wd_send(dev)) { |
166 | ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl); | 165 | ret = mei_cl_flow_ctrl_reduce(&dev->wd_cl); |
@@ -265,8 +264,8 @@ static int mei_wd_ops_stop(struct watchdog_device *wd_dev) | |||
265 | */ | 264 | */ |
266 | static int mei_wd_ops_ping(struct watchdog_device *wd_dev) | 265 | static int mei_wd_ops_ping(struct watchdog_device *wd_dev) |
267 | { | 266 | { |
268 | int ret = 0; | ||
269 | struct mei_device *dev; | 267 | struct mei_device *dev; |
268 | int ret; | ||
270 | 269 | ||
271 | dev = watchdog_get_drvdata(wd_dev); | 270 | dev = watchdog_get_drvdata(wd_dev); |
272 | if (!dev) | 271 | if (!dev) |
@@ -282,10 +281,12 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) | |||
282 | 281 | ||
283 | dev->wd_state = MEI_WD_RUNNING; | 282 | dev->wd_state = MEI_WD_RUNNING; |
284 | 283 | ||
284 | ret = mei_cl_flow_ctrl_creds(&dev->wd_cl); | ||
285 | if (ret < 0) | ||
286 | goto end; | ||
285 | /* Check if we can send the ping to HW*/ | 287 | /* Check if we can send the ping to HW*/ |
286 | if (dev->hbuf_is_ready && mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { | 288 | if (ret && mei_hbuf_acquire(dev)) { |
287 | 289 | ||
288 | dev->hbuf_is_ready = false; | ||
289 | dev_dbg(&dev->pdev->dev, "wd: sending ping\n"); | 290 | dev_dbg(&dev->pdev->dev, "wd: sending ping\n"); |
290 | 291 | ||
291 | if (mei_wd_send(dev)) { | 292 | if (mei_wd_send(dev)) { |
@@ -295,8 +296,7 @@ static int mei_wd_ops_ping(struct watchdog_device *wd_dev) | |||
295 | } | 296 | } |
296 | 297 | ||
297 | if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) { | 298 | if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) { |
298 | dev_err(&dev->pdev->dev, | 299 | dev_err(&dev->pdev->dev, "wd: mei_cl_flow_ctrl_reduce() failed.\n"); |
299 | "wd: mei_cl_flow_ctrl_reduce() failed.\n"); | ||
300 | ret = -EIO; | 300 | ret = -EIO; |
301 | goto end; | 301 | goto end; |
302 | } | 302 | } |