diff options
Diffstat (limited to 'drivers/misc/mei')
-rw-r--r-- | drivers/misc/mei/hbm.c | 64 | ||||
-rw-r--r-- | drivers/misc/mei/hbm.h | 1 | ||||
-rw-r--r-- | drivers/misc/mei/hw-me.c | 3 | ||||
-rw-r--r-- | drivers/misc/mei/init.c | 1 | ||||
-rw-r--r-- | drivers/misc/mei/interrupt.c | 47 | ||||
-rw-r--r-- | drivers/misc/mei/mei_dev.h | 8 |
6 files changed, 88 insertions, 36 deletions
diff --git a/drivers/misc/mei/hbm.c b/drivers/misc/mei/hbm.c index 0c770255bf89..d3fcb23bb081 100644 --- a/drivers/misc/mei/hbm.c +++ b/drivers/misc/mei/hbm.c | |||
@@ -283,17 +283,18 @@ static int mei_hbm_prop_req(struct mei_device *dev) | |||
283 | } | 283 | } |
284 | 284 | ||
285 | /** | 285 | /** |
286 | * mei_hbm_stop_req_prepare - prepare stop request message | 286 | * mei_hbm_stop_req - send stop request message |
287 | * | 287 | * |
288 | * @dev - mei device | 288 | * @dev - mei device |
289 | * @mei_hdr - mei message header | 289 | * @cl: client info |
290 | * @data - hbm message body buffer | 290 | * |
291 | * This function returns -EIO on write failure | ||
291 | */ | 292 | */ |
292 | static void mei_hbm_stop_req_prepare(struct mei_device *dev, | 293 | static int mei_hbm_stop_req(struct mei_device *dev) |
293 | struct mei_msg_hdr *mei_hdr, unsigned char *data) | ||
294 | { | 294 | { |
295 | struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; | ||
295 | struct hbm_host_stop_request *req = | 296 | struct hbm_host_stop_request *req = |
296 | (struct hbm_host_stop_request *)data; | 297 | (struct hbm_host_stop_request *)dev->wr_msg.data; |
297 | const size_t len = sizeof(struct hbm_host_stop_request); | 298 | const size_t len = sizeof(struct hbm_host_stop_request); |
298 | 299 | ||
299 | mei_hbm_hdr(mei_hdr, len); | 300 | mei_hbm_hdr(mei_hdr, len); |
@@ -301,6 +302,8 @@ static void mei_hbm_stop_req_prepare(struct mei_device *dev, | |||
301 | memset(req, 0, len); | 302 | memset(req, 0, len); |
302 | req->hbm_cmd = HOST_STOP_REQ_CMD; | 303 | req->hbm_cmd = HOST_STOP_REQ_CMD; |
303 | req->reason = DRIVER_STOP_REQUEST; | 304 | req->reason = DRIVER_STOP_REQUEST; |
305 | |||
306 | return mei_write_message(dev, mei_hdr, dev->wr_msg.data); | ||
304 | } | 307 | } |
305 | 308 | ||
306 | /** | 309 | /** |
@@ -405,6 +408,25 @@ int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl) | |||
405 | } | 408 | } |
406 | 409 | ||
407 | /** | 410 | /** |
411 | * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW | ||
412 | * | ||
413 | * @dev: the device structure | ||
414 | * @cl: a client to disconnect from | ||
415 | * | ||
416 | * This function returns -EIO on write failure | ||
417 | */ | ||
418 | int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl) | ||
419 | { | ||
420 | struct mei_msg_hdr *mei_hdr = &dev->wr_msg.hdr; | ||
421 | const size_t len = sizeof(struct hbm_client_connect_response); | ||
422 | |||
423 | mei_hbm_hdr(mei_hdr, len); | ||
424 | mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, dev->wr_msg.data, len); | ||
425 | |||
426 | return mei_write_message(dev, mei_hdr, dev->wr_msg.data); | ||
427 | } | ||
428 | |||
429 | /** | ||
408 | * mei_hbm_cl_disconnect_res - disconnect response from ME | 430 | * mei_hbm_cl_disconnect_res - disconnect response from ME |
409 | * | 431 | * |
410 | * @dev: the device structure | 432 | * @dev: the device structure |
@@ -525,12 +547,14 @@ static void mei_hbm_cl_connect_res(struct mei_device *dev, | |||
525 | * | 547 | * |
526 | * @dev: the device structure. | 548 | * @dev: the device structure. |
527 | * @disconnect_req: disconnect request bus message from the me | 549 | * @disconnect_req: disconnect request bus message from the me |
550 | * | ||
551 | * returns -ENOMEM on allocation failure | ||
528 | */ | 552 | */ |
529 | static void mei_hbm_fw_disconnect_req(struct mei_device *dev, | 553 | static int mei_hbm_fw_disconnect_req(struct mei_device *dev, |
530 | struct hbm_client_connect_request *disconnect_req) | 554 | struct hbm_client_connect_request *disconnect_req) |
531 | { | 555 | { |
532 | struct mei_cl *cl, *next; | 556 | struct mei_cl *cl, *next; |
533 | const size_t len = sizeof(struct hbm_client_connect_response); | 557 | struct mei_cl_cb *cb; |
534 | 558 | ||
535 | list_for_each_entry_safe(cl, next, &dev->file_list, link) { | 559 | list_for_each_entry_safe(cl, next, &dev->file_list, link) { |
536 | if (mei_hbm_cl_addr_equal(cl, disconnect_req)) { | 560 | if (mei_hbm_cl_addr_equal(cl, disconnect_req)) { |
@@ -544,13 +568,17 @@ static void mei_hbm_fw_disconnect_req(struct mei_device *dev, | |||
544 | else if (cl == &dev->iamthif_cl) | 568 | else if (cl == &dev->iamthif_cl) |
545 | dev->iamthif_timer = 0; | 569 | dev->iamthif_timer = 0; |
546 | 570 | ||
547 | /* prepare disconnect response */ | 571 | cb = mei_io_cb_init(cl, NULL); |
548 | mei_hbm_hdr(&dev->wr_ext_msg.hdr, len); | 572 | if (!cb) |
549 | mei_hbm_cl_hdr(cl, CLIENT_DISCONNECT_RES_CMD, | 573 | return -ENOMEM; |
550 | dev->wr_ext_msg.data, len); | 574 | cb->fop_type = MEI_FOP_DISCONNECT_RSP; |
575 | cl_dbg(dev, cl, "add disconnect response as first\n"); | ||
576 | list_add(&cb->list, &dev->ctrl_wr_list.list); | ||
577 | |||
551 | break; | 578 | break; |
552 | } | 579 | } |
553 | } | 580 | } |
581 | return 0; | ||
554 | } | 582 | } |
555 | 583 | ||
556 | 584 | ||
@@ -629,10 +657,7 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
629 | dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n"); | 657 | dev_warn(&dev->pdev->dev, "hbm: start: version mismatch - stopping the driver.\n"); |
630 | 658 | ||
631 | dev->hbm_state = MEI_HBM_STOPPED; | 659 | dev->hbm_state = MEI_HBM_STOPPED; |
632 | mei_hbm_stop_req_prepare(dev, &dev->wr_msg.hdr, | 660 | if (mei_hbm_stop_req(dev)) { |
633 | dev->wr_msg.data); | ||
634 | if (mei_write_message(dev, &dev->wr_msg.hdr, | ||
635 | dev->wr_msg.data)) { | ||
636 | dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n"); | 661 | dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n"); |
637 | return -EIO; | 662 | return -EIO; |
638 | } | 663 | } |
@@ -778,10 +803,11 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) | |||
778 | 803 | ||
779 | case ME_STOP_REQ_CMD: | 804 | case ME_STOP_REQ_CMD: |
780 | dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n"); | 805 | dev_dbg(&dev->pdev->dev, "hbm: stop request: message received\n"); |
781 | |||
782 | dev->hbm_state = MEI_HBM_STOPPED; | 806 | dev->hbm_state = MEI_HBM_STOPPED; |
783 | mei_hbm_stop_req_prepare(dev, &dev->wr_ext_msg.hdr, | 807 | if (mei_hbm_stop_req(dev)) { |
784 | dev->wr_ext_msg.data); | 808 | dev_err(&dev->pdev->dev, "hbm: start: failed to send stop request\n"); |
809 | return -EIO; | ||
810 | } | ||
785 | break; | 811 | break; |
786 | default: | 812 | default: |
787 | BUG(); | 813 | BUG(); |
diff --git a/drivers/misc/mei/hbm.h b/drivers/misc/mei/hbm.h index 5f92188a5cd7..20e8782711c0 100644 --- a/drivers/misc/mei/hbm.h +++ b/drivers/misc/mei/hbm.h | |||
@@ -54,6 +54,7 @@ int mei_hbm_start_req(struct mei_device *dev); | |||
54 | int mei_hbm_start_wait(struct mei_device *dev); | 54 | int mei_hbm_start_wait(struct mei_device *dev); |
55 | int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); | 55 | int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl); |
56 | int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); | 56 | int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl); |
57 | int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl); | ||
57 | int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); | 58 | int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl); |
58 | bool mei_hbm_version_is_supported(struct mei_device *dev); | 59 | bool mei_hbm_version_is_supported(struct mei_device *dev); |
59 | 60 | ||
diff --git a/drivers/misc/mei/hw-me.c b/drivers/misc/mei/hw-me.c index 54286f304939..847c9e5746cb 100644 --- a/drivers/misc/mei/hw-me.c +++ b/drivers/misc/mei/hw-me.c | |||
@@ -505,9 +505,6 @@ irqreturn_t mei_me_irq_thread_handler(int irq, void *dev_id) | |||
505 | /* check slots available for reading */ | 505 | /* check slots available for reading */ |
506 | slots = mei_count_full_read_slots(dev); | 506 | slots = mei_count_full_read_slots(dev); |
507 | while (slots > 0) { | 507 | while (slots > 0) { |
508 | /* we have urgent data to send so break the read */ | ||
509 | if (dev->wr_ext_msg.hdr.length) | ||
510 | break; | ||
511 | dev_dbg(&dev->pdev->dev, "slots to read = %08x\n", slots); | 508 | dev_dbg(&dev->pdev->dev, "slots to read = %08x\n", slots); |
512 | rets = mei_irq_read_handler(dev, &complete_list, &slots); | 509 | rets = mei_irq_read_handler(dev, &complete_list, &slots); |
513 | if (rets && dev->dev_state != MEI_DEV_RESETTING) { | 510 | if (rets && dev->dev_state != MEI_DEV_RESETTING) { |
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 95a7180c75ea..214dcef9750a 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -116,7 +116,6 @@ int mei_reset(struct mei_device *dev) | |||
116 | mei_cl_unlink(&dev->wd_cl); | 116 | mei_cl_unlink(&dev->wd_cl); |
117 | mei_cl_unlink(&dev->iamthif_cl); | 117 | mei_cl_unlink(&dev->iamthif_cl); |
118 | mei_amthif_reset_params(dev); | 118 | mei_amthif_reset_params(dev); |
119 | memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); | ||
120 | } | 119 | } |
121 | 120 | ||
122 | 121 | ||
diff --git a/drivers/misc/mei/interrupt.c b/drivers/misc/mei/interrupt.c index 3f0b0b9ce951..75ff4092953e 100644 --- a/drivers/misc/mei/interrupt.c +++ b/drivers/misc/mei/interrupt.c | |||
@@ -161,6 +161,41 @@ static int mei_cl_irq_read_msg(struct mei_device *dev, | |||
161 | } | 161 | } |
162 | 162 | ||
163 | /** | 163 | /** |
164 | * mei_cl_irq_disconnect_rsp - send disconnection response message | ||
165 | * | ||
166 | * @cl: client | ||
167 | * @cb: callback block. | ||
168 | * @slots: free slots. | ||
169 | * @cmpl_list: complete list. | ||
170 | * | ||
171 | * returns 0, OK; otherwise, error. | ||
172 | */ | ||
173 | static int mei_cl_irq_disconnect_rsp(struct mei_cl *cl, struct mei_cl_cb *cb, | ||
174 | s32 *slots, struct mei_cl_cb *cmpl_list) | ||
175 | { | ||
176 | struct mei_device *dev = cl->dev; | ||
177 | int ret; | ||
178 | |||
179 | u32 msg_slots = | ||
180 | mei_data2slots(sizeof(struct hbm_client_connect_response)); | ||
181 | |||
182 | if (*slots < msg_slots) | ||
183 | return -EMSGSIZE; | ||
184 | |||
185 | *slots -= msg_slots; | ||
186 | |||
187 | ret = mei_hbm_cl_disconnect_rsp(dev, cl); | ||
188 | |||
189 | cl->state = MEI_FILE_DISCONNECTED; | ||
190 | cl->status = 0; | ||
191 | mei_io_cb_free(cb); | ||
192 | |||
193 | return ret; | ||
194 | } | ||
195 | |||
196 | |||
197 | |||
198 | /** | ||
164 | * mei_cl_irq_close - processes close related operation from | 199 | * mei_cl_irq_close - processes close related operation from |
165 | * interrupt thread context - send disconnect request | 200 | * interrupt thread context - send disconnect request |
166 | * | 201 | * |
@@ -452,12 +487,6 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
452 | wake_up_interruptible(&dev->wait_stop_wd); | 487 | wake_up_interruptible(&dev->wait_stop_wd); |
453 | } | 488 | } |
454 | 489 | ||
455 | if (dev->wr_ext_msg.hdr.length) { | ||
456 | mei_write_message(dev, &dev->wr_ext_msg.hdr, | ||
457 | dev->wr_ext_msg.data); | ||
458 | slots -= mei_data2slots(dev->wr_ext_msg.hdr.length); | ||
459 | dev->wr_ext_msg.hdr.length = 0; | ||
460 | } | ||
461 | if (dev->dev_state == MEI_DEV_ENABLED) { | 490 | if (dev->dev_state == MEI_DEV_ENABLED) { |
462 | if (dev->wd_pending && | 491 | if (dev->wd_pending && |
463 | mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { | 492 | mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { |
@@ -505,7 +534,11 @@ int mei_irq_write_handler(struct mei_device *dev, struct mei_cl_cb *cmpl_list) | |||
505 | return ret; | 534 | return ret; |
506 | 535 | ||
507 | break; | 536 | break; |
508 | 537 | case MEI_FOP_DISCONNECT_RSP: | |
538 | /* send disconnect resp */ | ||
539 | ret = mei_cl_irq_disconnect_rsp(cl, cb, &slots, cmpl_list); | ||
540 | if (ret) | ||
541 | return ret; | ||
509 | default: | 542 | default: |
510 | BUG(); | 543 | BUG(); |
511 | } | 544 | } |
diff --git a/drivers/misc/mei/mei_dev.h b/drivers/misc/mei/mei_dev.h index f2c949ef3f28..21e52496bc6e 100644 --- a/drivers/misc/mei/mei_dev.h +++ b/drivers/misc/mei/mei_dev.h | |||
@@ -133,6 +133,7 @@ enum mei_wd_states { | |||
133 | * @MEI_FOP_READ - read | 133 | * @MEI_FOP_READ - read |
134 | * @MEI_FOP_WRITE - write | 134 | * @MEI_FOP_WRITE - write |
135 | * @MEI_FOP_CONNECT - connect | 135 | * @MEI_FOP_CONNECT - connect |
136 | * @MEI_FOP_DISCONNECT_RSP - disconnect response | ||
136 | * @MEI_FOP_OPEN - open | 137 | * @MEI_FOP_OPEN - open |
137 | * @MEI_FOP_CLOSE - close | 138 | * @MEI_FOP_CLOSE - close |
138 | */ | 139 | */ |
@@ -140,6 +141,7 @@ enum mei_cb_file_ops { | |||
140 | MEI_FOP_READ = 0, | 141 | MEI_FOP_READ = 0, |
141 | MEI_FOP_WRITE, | 142 | MEI_FOP_WRITE, |
142 | MEI_FOP_CONNECT, | 143 | MEI_FOP_CONNECT, |
144 | MEI_FOP_DISCONNECT_RSP, | ||
143 | MEI_FOP_OPEN, | 145 | MEI_FOP_OPEN, |
144 | MEI_FOP_CLOSE | 146 | MEI_FOP_CLOSE |
145 | }; | 147 | }; |
@@ -339,7 +341,6 @@ struct mei_cl_device { | |||
339 | * @hbuf_depth - depth of hardware host/write buffer is slots | 341 | * @hbuf_depth - depth of hardware host/write buffer is slots |
340 | * @hbuf_is_ready - query if the host host/write buffer is ready | 342 | * @hbuf_is_ready - query if the host host/write buffer is ready |
341 | * @wr_msg - the buffer for hbm control messages | 343 | * @wr_msg - the buffer for hbm control messages |
342 | * @wr_ext_msg - the buffer for hbm control responses (set in read cycle) | ||
343 | */ | 344 | */ |
344 | struct mei_device { | 345 | struct mei_device { |
345 | struct pci_dev *pdev; /* pointer to pci device struct */ | 346 | struct pci_dev *pdev; /* pointer to pci device struct */ |
@@ -394,11 +395,6 @@ struct mei_device { | |||
394 | unsigned char data[128]; | 395 | unsigned char data[128]; |
395 | } wr_msg; | 396 | } wr_msg; |
396 | 397 | ||
397 | struct { | ||
398 | struct mei_msg_hdr hdr; | ||
399 | unsigned char data[4]; /* All HBM messages are 4 bytes */ | ||
400 | } wr_ext_msg; /* for control responses */ | ||
401 | |||
402 | struct hbm_version version; | 398 | struct hbm_version version; |
403 | 399 | ||
404 | struct mei_me_client *me_clients; /* Note: memory has to be allocated */ | 400 | struct mei_me_client *me_clients; /* Note: memory has to be allocated */ |