diff options
Diffstat (limited to 'drivers/misc/mei/init.c')
-rw-r--r-- | drivers/misc/mei/init.c | 93 |
1 files changed, 56 insertions, 37 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index e77f86e69fb5..98f1430e3e14 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -24,6 +24,25 @@ | |||
24 | #include "interface.h" | 24 | #include "interface.h" |
25 | #include <linux/mei.h> | 25 | #include <linux/mei.h> |
26 | 26 | ||
27 | const char *mei_dev_state_str(int state) | ||
28 | { | ||
29 | #define MEI_DEV_STATE(state) case MEI_DEV_##state: return #state | ||
30 | switch (state) { | ||
31 | MEI_DEV_STATE(INITIALIZING); | ||
32 | MEI_DEV_STATE(INIT_CLIENTS); | ||
33 | MEI_DEV_STATE(ENABLED); | ||
34 | MEI_DEV_STATE(RESETING); | ||
35 | MEI_DEV_STATE(DISABLED); | ||
36 | MEI_DEV_STATE(RECOVERING_FROM_RESET); | ||
37 | MEI_DEV_STATE(POWER_DOWN); | ||
38 | MEI_DEV_STATE(POWER_UP); | ||
39 | default: | ||
40 | return "unkown"; | ||
41 | } | ||
42 | #undef MEI_DEV_STATE | ||
43 | } | ||
44 | |||
45 | |||
27 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, | 46 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, |
28 | 0xa8, 0x46, 0xe0, 0xff, 0x65, | 47 | 0xa8, 0x46, 0xe0, 0xff, 0x65, |
29 | 0x81, 0x4c); | 48 | 0x81, 0x4c); |
@@ -123,7 +142,7 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) | |||
123 | mutex_init(&dev->device_lock); | 142 | mutex_init(&dev->device_lock); |
124 | init_waitqueue_head(&dev->wait_recvd_msg); | 143 | init_waitqueue_head(&dev->wait_recvd_msg); |
125 | init_waitqueue_head(&dev->wait_stop_wd); | 144 | init_waitqueue_head(&dev->wait_stop_wd); |
126 | dev->mei_state = MEI_INITIALIZING; | 145 | dev->dev_state = MEI_DEV_INITIALIZING; |
127 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | 146 | dev->iamthif_state = MEI_IAMTHIF_IDLE; |
128 | dev->wd_interface_reg = false; | 147 | dev->wd_interface_reg = false; |
129 | 148 | ||
@@ -182,7 +201,7 @@ int mei_hw_init(struct mei_device *dev) | |||
182 | } | 201 | } |
183 | 202 | ||
184 | if (err <= 0 && !dev->recvd_msg) { | 203 | if (err <= 0 && !dev->recvd_msg) { |
185 | dev->mei_state = MEI_DISABLED; | 204 | dev->dev_state = MEI_DEV_DISABLED; |
186 | dev_dbg(&dev->pdev->dev, | 205 | dev_dbg(&dev->pdev->dev, |
187 | "wait_event_interruptible_timeout failed" | 206 | "wait_event_interruptible_timeout failed" |
188 | "on wait for ME to turn on ME_RDY.\n"); | 207 | "on wait for ME to turn on ME_RDY.\n"); |
@@ -192,7 +211,7 @@ int mei_hw_init(struct mei_device *dev) | |||
192 | 211 | ||
193 | if (!(((dev->host_hw_state & H_RDY) == H_RDY) && | 212 | if (!(((dev->host_hw_state & H_RDY) == H_RDY) && |
194 | ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { | 213 | ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { |
195 | dev->mei_state = MEI_DISABLED; | 214 | dev->dev_state = MEI_DEV_DISABLED; |
196 | dev_dbg(&dev->pdev->dev, | 215 | dev_dbg(&dev->pdev->dev, |
197 | "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", | 216 | "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", |
198 | dev->host_hw_state, dev->me_hw_state); | 217 | dev->host_hw_state, dev->me_hw_state); |
@@ -258,15 +277,15 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
258 | struct mei_cl_cb *cb_next = NULL; | 277 | struct mei_cl_cb *cb_next = NULL; |
259 | bool unexpected; | 278 | bool unexpected; |
260 | 279 | ||
261 | if (dev->mei_state == MEI_RECOVERING_FROM_RESET) { | 280 | if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { |
262 | dev->need_reset = true; | 281 | dev->need_reset = true; |
263 | return; | 282 | return; |
264 | } | 283 | } |
265 | 284 | ||
266 | unexpected = (dev->mei_state != MEI_INITIALIZING && | 285 | unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && |
267 | dev->mei_state != MEI_DISABLED && | 286 | dev->dev_state != MEI_DEV_DISABLED && |
268 | dev->mei_state != MEI_POWER_DOWN && | 287 | dev->dev_state != MEI_DEV_POWER_DOWN && |
269 | dev->mei_state != MEI_POWER_UP); | 288 | dev->dev_state != MEI_DEV_POWER_UP); |
270 | 289 | ||
271 | dev->host_hw_state = mei_hcsr_read(dev); | 290 | dev->host_hw_state = mei_hcsr_read(dev); |
272 | 291 | ||
@@ -285,10 +304,10 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
285 | 304 | ||
286 | dev->need_reset = false; | 305 | dev->need_reset = false; |
287 | 306 | ||
288 | if (dev->mei_state != MEI_INITIALIZING) { | 307 | if (dev->dev_state != MEI_DEV_INITIALIZING) { |
289 | if (dev->mei_state != MEI_DISABLED && | 308 | if (dev->dev_state != MEI_DEV_DISABLED && |
290 | dev->mei_state != MEI_POWER_DOWN) | 309 | dev->dev_state != MEI_DEV_POWER_DOWN) |
291 | dev->mei_state = MEI_RESETING; | 310 | dev->dev_state = MEI_DEV_RESETING; |
292 | 311 | ||
293 | list_for_each_entry_safe(cl_pos, | 312 | list_for_each_entry_safe(cl_pos, |
294 | cl_next, &dev->file_list, link) { | 313 | cl_next, &dev->file_list, link) { |
@@ -311,7 +330,6 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
311 | 330 | ||
312 | dev->me_clients_num = 0; | 331 | dev->me_clients_num = 0; |
313 | dev->rd_msg_hdr = 0; | 332 | dev->rd_msg_hdr = 0; |
314 | dev->stop = false; | ||
315 | dev->wd_pending = false; | 333 | dev->wd_pending = false; |
316 | 334 | ||
317 | /* update the state of the registers after reset */ | 335 | /* update the state of the registers after reset */ |
@@ -322,7 +340,8 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
322 | dev->host_hw_state, dev->me_hw_state); | 340 | dev->host_hw_state, dev->me_hw_state); |
323 | 341 | ||
324 | if (unexpected) | 342 | if (unexpected) |
325 | dev_warn(&dev->pdev->dev, "unexpected reset.\n"); | 343 | dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", |
344 | mei_dev_state_str(dev->dev_state)); | ||
326 | 345 | ||
327 | /* Wake up all readings so they can be interrupted */ | 346 | /* Wake up all readings so they can be interrupted */ |
328 | list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { | 347 | list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { |
@@ -371,7 +390,7 @@ void mei_host_start_message(struct mei_device *dev) | |||
371 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, | 390 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, |
372 | mei_hdr->length)) { | 391 | mei_hdr->length)) { |
373 | dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); | 392 | dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); |
374 | dev->mei_state = MEI_RESETING; | 393 | dev->dev_state = MEI_DEV_RESETING; |
375 | mei_reset(dev, 1); | 394 | mei_reset(dev, 1); |
376 | } | 395 | } |
377 | dev->init_clients_state = MEI_START_MESSAGE; | 396 | dev->init_clients_state = MEI_START_MESSAGE; |
@@ -403,7 +422,7 @@ void mei_host_enum_clients_message(struct mei_device *dev) | |||
403 | host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; | 422 | host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; |
404 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, | 423 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, |
405 | mei_hdr->length)) { | 424 | mei_hdr->length)) { |
406 | dev->mei_state = MEI_RESETING; | 425 | dev->dev_state = MEI_DEV_RESETING; |
407 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | 426 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); |
408 | mei_reset(dev, 1); | 427 | mei_reset(dev, 1); |
409 | } | 428 | } |
@@ -444,7 +463,7 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) | |||
444 | sizeof(struct mei_me_client), GFP_KERNEL); | 463 | sizeof(struct mei_me_client), GFP_KERNEL); |
445 | if (!clients) { | 464 | if (!clients) { |
446 | dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); | 465 | dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); |
447 | dev->mei_state = MEI_RESETING; | 466 | dev->dev_state = MEI_DEV_RESETING; |
448 | mei_reset(dev, 1); | 467 | mei_reset(dev, 1); |
449 | return ; | 468 | return ; |
450 | } | 469 | } |
@@ -490,7 +509,7 @@ int mei_host_client_properties(struct mei_device *dev) | |||
490 | if (mei_write_message(dev, mei_header, | 509 | if (mei_write_message(dev, mei_header, |
491 | (unsigned char *)host_cli_req, | 510 | (unsigned char *)host_cli_req, |
492 | mei_header->length)) { | 511 | mei_header->length)) { |
493 | dev->mei_state = MEI_RESETING; | 512 | dev->dev_state = MEI_DEV_RESETING; |
494 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | 513 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); |
495 | mei_reset(dev, 1); | 514 | mei_reset(dev, 1); |
496 | return -EIO; | 515 | return -EIO; |
@@ -522,12 +541,12 @@ void mei_cl_init(struct mei_cl *priv, struct mei_device *dev) | |||
522 | priv->dev = dev; | 541 | priv->dev = dev; |
523 | } | 542 | } |
524 | 543 | ||
525 | int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) | 544 | int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) |
526 | { | 545 | { |
527 | int i, res = -1; | 546 | int i, res = -ENOENT; |
528 | 547 | ||
529 | for (i = 0; i < dev->me_clients_num; ++i) | 548 | for (i = 0; i < dev->me_clients_num; ++i) |
530 | if (uuid_le_cmp(cuuid, | 549 | if (uuid_le_cmp(*cuuid, |
531 | dev->me_clients[i].props.protocol_name) == 0) { | 550 | dev->me_clients[i].props.protocol_name) == 0) { |
532 | res = i; | 551 | res = i; |
533 | break; | 552 | break; |
@@ -538,35 +557,35 @@ int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) | |||
538 | 557 | ||
539 | 558 | ||
540 | /** | 559 | /** |
541 | * mei_find_me_client_update_filext - searches for ME client guid | 560 | * mei_me_cl_update_filext - searches for ME client guid |
542 | * sets client_id in mei_file_private if found | 561 | * sets client_id in mei_file_private if found |
543 | * @dev: the device structure | 562 | * @dev: the device structure |
544 | * @priv: private file structure to set client_id in | 563 | * @cl: private file structure to set client_id in |
545 | * @cguid: searched guid of ME client | 564 | * @cuuid: searched uuid of ME client |
546 | * @client_id: id of host client to be set in file private structure | 565 | * @client_id: id of host client to be set in file private structure |
547 | * | 566 | * |
548 | * returns ME client index | 567 | * returns ME client index |
549 | */ | 568 | */ |
550 | u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, | 569 | int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, |
551 | const uuid_le *cguid, u8 client_id) | 570 | const uuid_le *cuuid, u8 host_cl_id) |
552 | { | 571 | { |
553 | int i; | 572 | int i; |
554 | 573 | ||
555 | if (!dev || !priv || !cguid) | 574 | if (!dev || !cl || !cuuid) |
556 | return 0; | 575 | return -EINVAL; |
557 | 576 | ||
558 | /* check for valid client id */ | 577 | /* check for valid client id */ |
559 | i = mei_find_me_client_index(dev, *cguid); | 578 | i = mei_me_cl_by_uuid(dev, cuuid); |
560 | if (i >= 0) { | 579 | if (i >= 0) { |
561 | priv->me_client_id = dev->me_clients[i].client_id; | 580 | cl->me_client_id = dev->me_clients[i].client_id; |
562 | priv->state = MEI_FILE_CONNECTING; | 581 | cl->state = MEI_FILE_CONNECTING; |
563 | priv->host_client_id = client_id; | 582 | cl->host_client_id = host_cl_id; |
564 | 583 | ||
565 | list_add_tail(&priv->link, &dev->file_list); | 584 | list_add_tail(&cl->link, &dev->file_list); |
566 | return (u8)i; | 585 | return (u8)i; |
567 | } | 586 | } |
568 | 587 | ||
569 | return 0; | 588 | return -ENOENT; |
570 | } | 589 | } |
571 | 590 | ||
572 | /** | 591 | /** |
@@ -577,16 +596,16 @@ u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, | |||
577 | */ | 596 | */ |
578 | void mei_host_init_iamthif(struct mei_device *dev) | 597 | void mei_host_init_iamthif(struct mei_device *dev) |
579 | { | 598 | { |
580 | u8 i; | 599 | int i; |
581 | unsigned char *msg_buf; | 600 | unsigned char *msg_buf; |
582 | 601 | ||
583 | mei_cl_init(&dev->iamthif_cl, dev); | 602 | mei_cl_init(&dev->iamthif_cl, dev); |
584 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | 603 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; |
585 | 604 | ||
586 | /* find ME amthi client */ | 605 | /* find ME amthi client */ |
587 | i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl, | 606 | i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, |
588 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | 607 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); |
589 | if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) { | 608 | if (i < 0) { |
590 | dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); | 609 | dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); |
591 | return; | 610 | return; |
592 | } | 611 | } |