diff options
Diffstat (limited to 'drivers/misc/mei/init.c')
-rw-r--r-- | drivers/misc/mei/init.c | 368 |
1 files changed, 149 insertions, 219 deletions
diff --git a/drivers/misc/mei/init.c b/drivers/misc/mei/init.c index 98f1430e3e14..a54cd5567ca2 100644 --- a/drivers/misc/mei/init.c +++ b/drivers/misc/mei/init.c | |||
@@ -43,21 +43,6 @@ const char *mei_dev_state_str(int state) | |||
43 | } | 43 | } |
44 | 44 | ||
45 | 45 | ||
46 | const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, | ||
47 | 0xa8, 0x46, 0xe0, 0xff, 0x65, | ||
48 | 0x81, 0x4c); | ||
49 | |||
50 | /** | ||
51 | * mei_io_list_init - Sets up a queue list. | ||
52 | * | ||
53 | * @list: An instance io list structure | ||
54 | * @dev: the device structure | ||
55 | */ | ||
56 | void mei_io_list_init(struct mei_io_list *list) | ||
57 | { | ||
58 | /* initialize our queue list */ | ||
59 | INIT_LIST_HEAD(&list->mei_cb.cb_list); | ||
60 | } | ||
61 | 46 | ||
62 | /** | 47 | /** |
63 | * mei_io_list_flush - removes list entry belonging to cl. | 48 | * mei_io_list_flush - removes list entry belonging to cl. |
@@ -65,17 +50,15 @@ void mei_io_list_init(struct mei_io_list *list) | |||
65 | * @list: An instance of our list structure | 50 | * @list: An instance of our list structure |
66 | * @cl: private data of the file object | 51 | * @cl: private data of the file object |
67 | */ | 52 | */ |
68 | void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl) | 53 | void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl) |
69 | { | 54 | { |
70 | struct mei_cl_cb *pos; | 55 | struct mei_cl_cb *pos; |
71 | struct mei_cl_cb *next; | 56 | struct mei_cl_cb *next; |
72 | 57 | ||
73 | list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) { | 58 | list_for_each_entry_safe(pos, next, &list->list, list) { |
74 | if (pos->file_private) { | 59 | if (pos->cl) { |
75 | struct mei_cl *cl_tmp; | 60 | if (mei_cl_cmp_id(cl, pos->cl)) |
76 | cl_tmp = (struct mei_cl *)pos->file_private; | 61 | list_del(&pos->list); |
77 | if (mei_cl_cmp_id(cl, cl_tmp)) | ||
78 | list_del(&pos->cb_list); | ||
79 | } | 62 | } |
80 | } | 63 | } |
81 | } | 64 | } |
@@ -96,31 +79,14 @@ int mei_cl_flush_queues(struct mei_cl *cl) | |||
96 | mei_io_list_flush(&cl->dev->write_waiting_list, cl); | 79 | mei_io_list_flush(&cl->dev->write_waiting_list, cl); |
97 | mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); | 80 | mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); |
98 | mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); | 81 | mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); |
99 | mei_io_list_flush(&cl->dev->amthi_cmd_list, cl); | 82 | mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); |
100 | mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl); | 83 | mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); |
101 | return 0; | 84 | return 0; |
102 | } | 85 | } |
103 | 86 | ||
104 | 87 | ||
105 | 88 | ||
106 | /** | 89 | /** |
107 | * mei_reset_iamthif_params - initializes mei device iamthif | ||
108 | * | ||
109 | * @dev: the device structure | ||
110 | */ | ||
111 | static void mei_reset_iamthif_params(struct mei_device *dev) | ||
112 | { | ||
113 | /* reset iamthif parameters. */ | ||
114 | dev->iamthif_current_cb = NULL; | ||
115 | dev->iamthif_msg_buf_size = 0; | ||
116 | dev->iamthif_msg_buf_index = 0; | ||
117 | dev->iamthif_canceled = false; | ||
118 | dev->iamthif_ioctl = false; | ||
119 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | ||
120 | dev->iamthif_timer = 0; | ||
121 | } | ||
122 | |||
123 | /** | ||
124 | * init_mei_device - allocates and initializes the mei device structure | 90 | * init_mei_device - allocates and initializes the mei device structure |
125 | * | 91 | * |
126 | * @pdev: The pci device structure | 92 | * @pdev: The pci device structure |
@@ -144,16 +110,14 @@ struct mei_device *mei_device_init(struct pci_dev *pdev) | |||
144 | init_waitqueue_head(&dev->wait_stop_wd); | 110 | init_waitqueue_head(&dev->wait_stop_wd); |
145 | dev->dev_state = MEI_DEV_INITIALIZING; | 111 | dev->dev_state = MEI_DEV_INITIALIZING; |
146 | dev->iamthif_state = MEI_IAMTHIF_IDLE; | 112 | dev->iamthif_state = MEI_IAMTHIF_IDLE; |
147 | dev->wd_interface_reg = false; | ||
148 | |||
149 | 113 | ||
150 | mei_io_list_init(&dev->read_list); | 114 | mei_io_list_init(&dev->read_list); |
151 | mei_io_list_init(&dev->write_list); | 115 | mei_io_list_init(&dev->write_list); |
152 | mei_io_list_init(&dev->write_waiting_list); | 116 | mei_io_list_init(&dev->write_waiting_list); |
153 | mei_io_list_init(&dev->ctrl_wr_list); | 117 | mei_io_list_init(&dev->ctrl_wr_list); |
154 | mei_io_list_init(&dev->ctrl_rd_list); | 118 | mei_io_list_init(&dev->ctrl_rd_list); |
155 | mei_io_list_init(&dev->amthi_cmd_list); | 119 | mei_io_list_init(&dev->amthif_cmd_list); |
156 | mei_io_list_init(&dev->amthi_read_complete_list); | 120 | mei_io_list_init(&dev->amthif_rd_complete_list); |
157 | dev->pdev = pdev; | 121 | dev->pdev = pdev; |
158 | return dev; | 122 | return dev; |
159 | } | 123 | } |
@@ -196,7 +160,8 @@ int mei_hw_init(struct mei_device *dev) | |||
196 | if (!dev->recvd_msg) { | 160 | if (!dev->recvd_msg) { |
197 | mutex_unlock(&dev->device_lock); | 161 | mutex_unlock(&dev->device_lock); |
198 | err = wait_event_interruptible_timeout(dev->wait_recvd_msg, | 162 | err = wait_event_interruptible_timeout(dev->wait_recvd_msg, |
199 | dev->recvd_msg, MEI_INTEROP_TIMEOUT); | 163 | dev->recvd_msg, |
164 | mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); | ||
200 | mutex_lock(&dev->device_lock); | 165 | mutex_lock(&dev->device_lock); |
201 | } | 166 | } |
202 | 167 | ||
@@ -317,15 +282,13 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
317 | cl_pos->timer_count = 0; | 282 | cl_pos->timer_count = 0; |
318 | } | 283 | } |
319 | /* remove entry if already in list */ | 284 | /* remove entry if already in list */ |
320 | dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n"); | 285 | dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); |
321 | mei_remove_client_from_file_list(dev, | 286 | mei_me_cl_unlink(dev, &dev->wd_cl); |
322 | dev->wd_cl.host_client_id); | ||
323 | 287 | ||
324 | mei_remove_client_from_file_list(dev, | 288 | mei_me_cl_unlink(dev, &dev->iamthif_cl); |
325 | dev->iamthif_cl.host_client_id); | ||
326 | 289 | ||
327 | mei_reset_iamthif_params(dev); | 290 | mei_amthif_reset_params(dev); |
328 | dev->extra_write_index = 0; | 291 | memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); |
329 | } | 292 | } |
330 | 293 | ||
331 | dev->me_clients_num = 0; | 294 | dev->me_clients_num = 0; |
@@ -351,10 +314,9 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
351 | } | 314 | } |
352 | } | 315 | } |
353 | /* remove all waiting requests */ | 316 | /* remove all waiting requests */ |
354 | list_for_each_entry_safe(cb_pos, cb_next, | 317 | list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) { |
355 | &dev->write_list.mei_cb.cb_list, cb_list) { | 318 | list_del(&cb_pos->list); |
356 | list_del(&cb_pos->cb_list); | 319 | mei_io_cb_free(cb_pos); |
357 | mei_free_cb_private(cb_pos); | ||
358 | } | 320 | } |
359 | } | 321 | } |
360 | 322 | ||
@@ -370,31 +332,26 @@ void mei_reset(struct mei_device *dev, int interrupts_enabled) | |||
370 | void mei_host_start_message(struct mei_device *dev) | 332 | void mei_host_start_message(struct mei_device *dev) |
371 | { | 333 | { |
372 | struct mei_msg_hdr *mei_hdr; | 334 | struct mei_msg_hdr *mei_hdr; |
373 | struct hbm_host_version_request *host_start_req; | 335 | struct hbm_host_version_request *start_req; |
336 | const size_t len = sizeof(struct hbm_host_version_request); | ||
337 | |||
338 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); | ||
374 | 339 | ||
375 | /* host start message */ | 340 | /* host start message */ |
376 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 341 | start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1]; |
377 | mei_hdr->host_addr = 0; | 342 | memset(start_req, 0, len); |
378 | mei_hdr->me_addr = 0; | 343 | start_req->hbm_cmd = HOST_START_REQ_CMD; |
379 | mei_hdr->length = sizeof(struct hbm_host_version_request); | 344 | start_req->host_version.major_version = HBM_MAJOR_VERSION; |
380 | mei_hdr->msg_complete = 1; | 345 | start_req->host_version.minor_version = HBM_MINOR_VERSION; |
381 | mei_hdr->reserved = 0; | 346 | |
382 | |||
383 | host_start_req = | ||
384 | (struct hbm_host_version_request *) &dev->wr_msg_buf[1]; | ||
385 | memset(host_start_req, 0, sizeof(struct hbm_host_version_request)); | ||
386 | host_start_req->hbm_cmd = HOST_START_REQ_CMD; | ||
387 | host_start_req->host_version.major_version = HBM_MAJOR_VERSION; | ||
388 | host_start_req->host_version.minor_version = HBM_MINOR_VERSION; | ||
389 | dev->recvd_msg = false; | 347 | dev->recvd_msg = false; |
390 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, | 348 | if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) { |
391 | mei_hdr->length)) { | ||
392 | dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); | 349 | dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); |
393 | dev->dev_state = MEI_DEV_RESETING; | 350 | dev->dev_state = MEI_DEV_RESETING; |
394 | mei_reset(dev, 1); | 351 | mei_reset(dev, 1); |
395 | } | 352 | } |
396 | dev->init_clients_state = MEI_START_MESSAGE; | 353 | dev->init_clients_state = MEI_START_MESSAGE; |
397 | dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; | 354 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
398 | return ; | 355 | return ; |
399 | } | 356 | } |
400 | 357 | ||
@@ -408,26 +365,22 @@ void mei_host_start_message(struct mei_device *dev) | |||
408 | void mei_host_enum_clients_message(struct mei_device *dev) | 365 | void mei_host_enum_clients_message(struct mei_device *dev) |
409 | { | 366 | { |
410 | struct mei_msg_hdr *mei_hdr; | 367 | struct mei_msg_hdr *mei_hdr; |
411 | struct hbm_host_enum_request *host_enum_req; | 368 | struct hbm_host_enum_request *enum_req; |
412 | mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; | 369 | const size_t len = sizeof(struct hbm_host_enum_request); |
413 | /* enumerate clients */ | 370 | /* enumerate clients */ |
414 | mei_hdr->host_addr = 0; | 371 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); |
415 | mei_hdr->me_addr = 0; | 372 | |
416 | mei_hdr->length = sizeof(struct hbm_host_enum_request); | 373 | enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; |
417 | mei_hdr->msg_complete = 1; | 374 | memset(enum_req, 0, sizeof(struct hbm_host_enum_request)); |
418 | mei_hdr->reserved = 0; | 375 | enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; |
419 | 376 | ||
420 | host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; | 377 | if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) { |
421 | memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request)); | ||
422 | host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; | ||
423 | if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, | ||
424 | mei_hdr->length)) { | ||
425 | dev->dev_state = MEI_DEV_RESETING; | 378 | dev->dev_state = MEI_DEV_RESETING; |
426 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | 379 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); |
427 | mei_reset(dev, 1); | 380 | mei_reset(dev, 1); |
428 | } | 381 | } |
429 | dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; | 382 | dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; |
430 | dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; | 383 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; |
431 | return; | 384 | return; |
432 | } | 385 | } |
433 | 386 | ||
@@ -470,56 +423,87 @@ void mei_allocate_me_clients_storage(struct mei_device *dev) | |||
470 | dev->me_clients = clients; | 423 | dev->me_clients = clients; |
471 | return ; | 424 | return ; |
472 | } | 425 | } |
473 | /** | 426 | |
474 | * host_client_properties - reads properties for client | 427 | void mei_host_client_init(struct work_struct *work) |
475 | * | ||
476 | * @dev: the device structure | ||
477 | * | ||
478 | * returns: | ||
479 | * < 0 - Error. | ||
480 | * = 0 - no more clients. | ||
481 | * = 1 - still have clients to send properties request. | ||
482 | */ | ||
483 | int mei_host_client_properties(struct mei_device *dev) | ||
484 | { | 428 | { |
485 | struct mei_msg_hdr *mei_header; | 429 | struct mei_device *dev = container_of(work, |
486 | struct hbm_props_request *host_cli_req; | 430 | struct mei_device, init_work); |
487 | int b; | 431 | struct mei_client_properties *client_props; |
488 | u8 client_num = dev->me_client_presentation_num; | 432 | int i; |
489 | 433 | ||
490 | b = dev->me_client_index; | 434 | mutex_lock(&dev->device_lock); |
491 | b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b); | 435 | |
492 | if (b < MEI_CLIENTS_MAX) { | 436 | bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); |
493 | dev->me_clients[client_num].client_id = b; | 437 | dev->open_handle_count = 0; |
494 | dev->me_clients[client_num].mei_flow_ctrl_creds = 0; | 438 | |
495 | mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; | 439 | /* |
496 | mei_header->host_addr = 0; | 440 | * Reserving the first three client IDs |
497 | mei_header->me_addr = 0; | 441 | * 0: Reserved for MEI Bus Message communications |
498 | mei_header->length = sizeof(struct hbm_props_request); | 442 | * 1: Reserved for Watchdog |
499 | mei_header->msg_complete = 1; | 443 | * 2: Reserved for AMTHI |
500 | mei_header->reserved = 0; | 444 | */ |
501 | 445 | bitmap_set(dev->host_clients_map, 0, 3); | |
502 | host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; | 446 | |
503 | 447 | for (i = 0; i < dev->me_clients_num; i++) { | |
504 | memset(host_cli_req, 0, sizeof(struct hbm_props_request)); | 448 | client_props = &dev->me_clients[i].props; |
505 | 449 | ||
506 | host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; | 450 | if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid)) |
507 | host_cli_req->address = b; | 451 | mei_amthif_host_init(dev); |
508 | 452 | else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid)) | |
509 | if (mei_write_message(dev, mei_header, | 453 | mei_wd_host_init(dev); |
510 | (unsigned char *)host_cli_req, | 454 | } |
511 | mei_header->length)) { | 455 | |
512 | dev->dev_state = MEI_DEV_RESETING; | 456 | dev->dev_state = MEI_DEV_ENABLED; |
513 | dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); | ||
514 | mei_reset(dev, 1); | ||
515 | return -EIO; | ||
516 | } | ||
517 | 457 | ||
518 | dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; | 458 | mutex_unlock(&dev->device_lock); |
519 | dev->me_client_index = b; | 459 | } |
520 | return 1; | 460 | |
461 | int mei_host_client_enumerate(struct mei_device *dev) | ||
462 | { | ||
463 | |||
464 | struct mei_msg_hdr *mei_hdr; | ||
465 | struct hbm_props_request *prop_req; | ||
466 | const size_t len = sizeof(struct hbm_props_request); | ||
467 | unsigned long next_client_index; | ||
468 | u8 client_num; | ||
469 | |||
470 | |||
471 | client_num = dev->me_client_presentation_num; | ||
472 | |||
473 | next_client_index = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, | ||
474 | dev->me_client_index); | ||
475 | |||
476 | /* We got all client properties */ | ||
477 | if (next_client_index == MEI_CLIENTS_MAX) { | ||
478 | schedule_work(&dev->init_work); | ||
479 | |||
480 | return 0; | ||
521 | } | 481 | } |
522 | 482 | ||
483 | dev->me_clients[client_num].client_id = next_client_index; | ||
484 | dev->me_clients[client_num].mei_flow_ctrl_creds = 0; | ||
485 | |||
486 | mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); | ||
487 | prop_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; | ||
488 | |||
489 | memset(prop_req, 0, sizeof(struct hbm_props_request)); | ||
490 | |||
491 | |||
492 | prop_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; | ||
493 | prop_req->address = next_client_index; | ||
494 | |||
495 | if (mei_write_message(dev, mei_hdr, (unsigned char *) prop_req, | ||
496 | mei_hdr->length)) { | ||
497 | dev->dev_state = MEI_DEV_RESETING; | ||
498 | dev_err(&dev->pdev->dev, "Properties request command failed\n"); | ||
499 | mei_reset(dev, 1); | ||
500 | |||
501 | return -EIO; | ||
502 | } | ||
503 | |||
504 | dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; | ||
505 | dev->me_client_index = next_client_index; | ||
506 | |||
523 | return 0; | 507 | return 0; |
524 | } | 508 | } |
525 | 509 | ||
@@ -557,17 +541,20 @@ int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) | |||
557 | 541 | ||
558 | 542 | ||
559 | /** | 543 | /** |
560 | * mei_me_cl_update_filext - searches for ME client guid | 544 | * mei_me_cl_link - create link between host and me clinet and add |
561 | * sets client_id in mei_file_private if found | 545 | * me_cl to the list |
546 | * | ||
562 | * @dev: the device structure | 547 | * @dev: the device structure |
563 | * @cl: private file structure to set client_id in | 548 | * @cl: link between me and host client assocated with opened file descriptor |
564 | * @cuuid: searched uuid of ME client | 549 | * @cuuid: uuid of ME client |
565 | * @client_id: id of host client to be set in file private structure | 550 | * @client_id: id of the host client |
566 | * | 551 | * |
567 | * returns ME client index | 552 | * returns ME client index if ME client |
553 | * -EINVAL on incorrect values | ||
554 | * -ENONET if client not found | ||
568 | */ | 555 | */ |
569 | int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, | 556 | int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl, |
570 | const uuid_le *cuuid, u8 host_cl_id) | 557 | const uuid_le *cuuid, u8 host_cl_id) |
571 | { | 558 | { |
572 | int i; | 559 | int i; |
573 | 560 | ||
@@ -587,54 +574,22 @@ int mei_me_cl_update_filext(struct mei_device *dev, struct mei_cl *cl, | |||
587 | 574 | ||
588 | return -ENOENT; | 575 | return -ENOENT; |
589 | } | 576 | } |
590 | |||
591 | /** | 577 | /** |
592 | * host_init_iamthif - mei initialization iamthif client. | 578 | * mei_me_cl_unlink - remove me_cl from the list |
593 | * | 579 | * |
594 | * @dev: the device structure | 580 | * @dev: the device structure |
595 | * | 581 | * @host_client_id: host client id to be removed |
596 | */ | 582 | */ |
597 | void mei_host_init_iamthif(struct mei_device *dev) | 583 | void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl) |
598 | { | 584 | { |
599 | int i; | 585 | struct mei_cl *pos, *next; |
600 | unsigned char *msg_buf; | 586 | list_for_each_entry_safe(pos, next, &dev->file_list, link) { |
601 | 587 | if (cl->host_client_id == pos->host_client_id) { | |
602 | mei_cl_init(&dev->iamthif_cl, dev); | 588 | dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", |
603 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | 589 | pos->host_client_id, pos->me_client_id); |
604 | 590 | list_del_init(&pos->link); | |
605 | /* find ME amthi client */ | 591 | break; |
606 | i = mei_me_cl_update_filext(dev, &dev->iamthif_cl, | 592 | } |
607 | &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); | ||
608 | if (i < 0) { | ||
609 | dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); | ||
610 | return; | ||
611 | } | ||
612 | |||
613 | /* Assign iamthif_mtu to the value received from ME */ | ||
614 | |||
615 | dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; | ||
616 | dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n", | ||
617 | dev->me_clients[i].props.max_msg_length); | ||
618 | |||
619 | kfree(dev->iamthif_msg_buf); | ||
620 | dev->iamthif_msg_buf = NULL; | ||
621 | |||
622 | /* allocate storage for ME message buffer */ | ||
623 | msg_buf = kcalloc(dev->iamthif_mtu, | ||
624 | sizeof(unsigned char), GFP_KERNEL); | ||
625 | if (!msg_buf) { | ||
626 | dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); | ||
627 | return; | ||
628 | } | ||
629 | |||
630 | dev->iamthif_msg_buf = msg_buf; | ||
631 | |||
632 | if (mei_connect(dev, &dev->iamthif_cl)) { | ||
633 | dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); | ||
634 | dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; | ||
635 | dev->iamthif_cl.host_client_id = 0; | ||
636 | } else { | ||
637 | dev->iamthif_cl.timer_count = CONNECT_TIMEOUT; | ||
638 | } | 593 | } |
639 | } | 594 | } |
640 | 595 | ||
@@ -671,9 +626,8 @@ struct mei_cl *mei_cl_allocate(struct mei_device *dev) | |||
671 | */ | 626 | */ |
672 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | 627 | int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) |
673 | { | 628 | { |
674 | int rets, err; | ||
675 | long timeout = 15; /* 15 seconds */ | ||
676 | struct mei_cl_cb *cb; | 629 | struct mei_cl_cb *cb; |
630 | int rets, err; | ||
677 | 631 | ||
678 | if (!dev || !cl) | 632 | if (!dev || !cl) |
679 | return -ENODEV; | 633 | return -ENODEV; |
@@ -681,13 +635,11 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | |||
681 | if (cl->state != MEI_FILE_DISCONNECTING) | 635 | if (cl->state != MEI_FILE_DISCONNECTING) |
682 | return 0; | 636 | return 0; |
683 | 637 | ||
684 | cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); | 638 | cb = mei_io_cb_init(cl, NULL); |
685 | if (!cb) | 639 | if (!cb) |
686 | return -ENOMEM; | 640 | return -ENOMEM; |
687 | 641 | ||
688 | INIT_LIST_HEAD(&cb->cb_list); | 642 | cb->fop_type = MEI_FOP_CLOSE; |
689 | cb->file_private = cl; | ||
690 | cb->major_file_operations = MEI_CLOSE; | ||
691 | if (dev->mei_host_buffer_is_empty) { | 643 | if (dev->mei_host_buffer_is_empty) { |
692 | dev->mei_host_buffer_is_empty = false; | 644 | dev->mei_host_buffer_is_empty = false; |
693 | if (mei_disconnect(dev, cl)) { | 645 | if (mei_disconnect(dev, cl)) { |
@@ -696,17 +648,17 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | |||
696 | goto free; | 648 | goto free; |
697 | } | 649 | } |
698 | mdelay(10); /* Wait for hardware disconnection ready */ | 650 | mdelay(10); /* Wait for hardware disconnection ready */ |
699 | list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list); | 651 | list_add_tail(&cb->list, &dev->ctrl_rd_list.list); |
700 | } else { | 652 | } else { |
701 | dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); | 653 | dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); |
702 | list_add_tail(&cb->cb_list, | 654 | list_add_tail(&cb->list, &dev->ctrl_wr_list.list); |
703 | &dev->ctrl_wr_list.mei_cb.cb_list); | 655 | |
704 | } | 656 | } |
705 | mutex_unlock(&dev->device_lock); | 657 | mutex_unlock(&dev->device_lock); |
706 | 658 | ||
707 | err = wait_event_timeout(dev->wait_recvd_msg, | 659 | err = wait_event_timeout(dev->wait_recvd_msg, |
708 | (MEI_FILE_DISCONNECTED == cl->state), | 660 | MEI_FILE_DISCONNECTED == cl->state, |
709 | timeout * HZ); | 661 | mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); |
710 | 662 | ||
711 | mutex_lock(&dev->device_lock); | 663 | mutex_lock(&dev->device_lock); |
712 | if (MEI_FILE_DISCONNECTED == cl->state) { | 664 | if (MEI_FILE_DISCONNECTED == cl->state) { |
@@ -728,29 +680,7 @@ int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) | |||
728 | mei_io_list_flush(&dev->ctrl_rd_list, cl); | 680 | mei_io_list_flush(&dev->ctrl_rd_list, cl); |
729 | mei_io_list_flush(&dev->ctrl_wr_list, cl); | 681 | mei_io_list_flush(&dev->ctrl_wr_list, cl); |
730 | free: | 682 | free: |
731 | mei_free_cb_private(cb); | 683 | mei_io_cb_free(cb); |
732 | return rets; | 684 | return rets; |
733 | } | 685 | } |
734 | 686 | ||
735 | /** | ||
736 | * mei_remove_client_from_file_list - | ||
737 | * removes file private data from device file list | ||
738 | * | ||
739 | * @dev: the device structure | ||
740 | * @host_client_id: host client id to be removed | ||
741 | */ | ||
742 | void mei_remove_client_from_file_list(struct mei_device *dev, | ||
743 | u8 host_client_id) | ||
744 | { | ||
745 | struct mei_cl *cl_pos = NULL; | ||
746 | struct mei_cl *cl_next = NULL; | ||
747 | list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { | ||
748 | if (host_client_id == cl_pos->host_client_id) { | ||
749 | dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", | ||
750 | cl_pos->host_client_id, | ||
751 | cl_pos->me_client_id); | ||
752 | list_del_init(&cl_pos->link); | ||
753 | break; | ||
754 | } | ||
755 | } | ||
756 | } | ||