1 /* 2 * 3 * Intel Management Engine Interface (Intel MEI) Linux driver 4 * Copyright (c) 2003-2012, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. 9 * 10 * This program is distributed in the hope it will be useful, but WITHOUT 11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 13 * more details. 14 * 15 */ 16 17 #include <linux/pci.h> 18 #include <linux/sched.h> 19 #include <linux/wait.h> 20 #include <linux/delay.h> 21 22 #include "mei_dev.h" 23 #include "hw.h" 24 #include "interface.h" 25 #include <linux/mei.h> 26 27 const uuid_le mei_amthi_guid = UUID_LE(0x12f80028, 0xb4b7, 0x4b2d, 0xac, 28 0xa8, 0x46, 0xe0, 0xff, 0x65, 29 0x81, 0x4c); 30 31 /** 32 * mei_io_list_init - Sets up a queue list. 33 * 34 * @list: An instance io list structure 35 * @dev: the device structure 36 */ 37 void mei_io_list_init(struct mei_io_list *list) 38 { 39 /* initialize our queue list */ 40 INIT_LIST_HEAD(&list->mei_cb.cb_list); 41 } 42 43 /** 44 * mei_io_list_flush - removes list entry belonging to cl. 45 * 46 * @list: An instance of our list structure 47 * @cl: private data of the file object 48 */ 49 void mei_io_list_flush(struct mei_io_list *list, struct mei_cl *cl) 50 { 51 struct mei_cl_cb *pos; 52 struct mei_cl_cb *next; 53 54 list_for_each_entry_safe(pos, next, &list->mei_cb.cb_list, cb_list) { 55 if (pos->file_private) { 56 struct mei_cl *cl_tmp; 57 cl_tmp = (struct mei_cl *)pos->file_private; 58 if (mei_cl_cmp_id(cl, cl_tmp)) 59 list_del(&pos->cb_list); 60 } 61 } 62 } 63 /** 64 * mei_cl_flush_queues - flushes queue lists belonging to cl. 65 * 66 * @dev: the device structure 67 * @cl: private data of the file object 68 */ 69 int mei_cl_flush_queues(struct mei_cl *cl) 70 { 71 if (!cl || !cl->dev) 72 return -EINVAL; 73 74 dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n"); 75 mei_io_list_flush(&cl->dev->read_list, cl); 76 mei_io_list_flush(&cl->dev->write_list, cl); 77 mei_io_list_flush(&cl->dev->write_waiting_list, cl); 78 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); 79 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); 80 mei_io_list_flush(&cl->dev->amthi_cmd_list, cl); 81 mei_io_list_flush(&cl->dev->amthi_read_complete_list, cl); 82 return 0; 83 } 84 85 86 87 /** 88 * mei_reset_iamthif_params - initializes mei device iamthif 89 * 90 * @dev: the device structure 91 */ 92 static void mei_reset_iamthif_params(struct mei_device *dev) 93 { 94 /* reset iamthif parameters. */ 95 dev->iamthif_current_cb = NULL; 96 dev->iamthif_msg_buf_size = 0; 97 dev->iamthif_msg_buf_index = 0; 98 dev->iamthif_canceled = false; 99 dev->iamthif_ioctl = false; 100 dev->iamthif_state = MEI_IAMTHIF_IDLE; 101 dev->iamthif_timer = 0; 102 } 103 104 /** 105 * init_mei_device - allocates and initializes the mei device structure 106 * 107 * @pdev: The pci device structure 108 * 109 * returns The mei_device_device pointer on success, NULL on failure. 110 */ 111 struct mei_device *mei_device_init(struct pci_dev *pdev) 112 { 113 struct mei_device *dev; 114 115 dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL); 116 if (!dev) 117 return NULL; 118 119 /* setup our list array */ 120 INIT_LIST_HEAD(&dev->file_list); 121 INIT_LIST_HEAD(&dev->wd_cl.link); 122 INIT_LIST_HEAD(&dev->iamthif_cl.link); 123 mutex_init(&dev->device_lock); 124 init_waitqueue_head(&dev->wait_recvd_msg); 125 init_waitqueue_head(&dev->wait_stop_wd); 126 dev->mei_state = MEI_INITIALIZING; 127 dev->iamthif_state = MEI_IAMTHIF_IDLE; 128 dev->wd_interface_reg = false; 129 130 131 mei_io_list_init(&dev->read_list); 132 mei_io_list_init(&dev->write_list); 133 mei_io_list_init(&dev->write_waiting_list); 134 mei_io_list_init(&dev->ctrl_wr_list); 135 mei_io_list_init(&dev->ctrl_rd_list); 136 mei_io_list_init(&dev->amthi_cmd_list); 137 mei_io_list_init(&dev->amthi_read_complete_list); 138 dev->pdev = pdev; 139 return dev; 140 } 141 142 /** 143 * mei_hw_init - initializes host and fw to start work. 144 * 145 * @dev: the device structure 146 * 147 * returns 0 on success, <0 on failure. 148 */ 149 int mei_hw_init(struct mei_device *dev) 150 { 151 int err = 0; 152 int ret; 153 154 mutex_lock(&dev->device_lock); 155 156 dev->host_hw_state = mei_hcsr_read(dev); 157 dev->me_hw_state = mei_mecsr_read(dev); 158 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n", 159 dev->host_hw_state, dev->me_hw_state); 160 161 /* acknowledge interrupt and stop interupts */ 162 if ((dev->host_hw_state & H_IS) == H_IS) 163 mei_reg_write(dev, H_CSR, dev->host_hw_state); 164 165 /* Doesn't change in runtime */ 166 dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24; 167 168 dev->recvd_msg = false; 169 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); 170 171 mei_reset(dev, 1); 172 173 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 174 dev->host_hw_state, dev->me_hw_state); 175 176 /* wait for ME to turn on ME_RDY */ 177 if (!dev->recvd_msg) { 178 mutex_unlock(&dev->device_lock); 179 err = wait_event_interruptible_timeout(dev->wait_recvd_msg, 180 dev->recvd_msg, MEI_INTEROP_TIMEOUT); 181 mutex_lock(&dev->device_lock); 182 } 183 184 if (err <= 0 && !dev->recvd_msg) { 185 dev->mei_state = MEI_DISABLED; 186 dev_dbg(&dev->pdev->dev, 187 "wait_event_interruptible_timeout failed" 188 "on wait for ME to turn on ME_RDY.\n"); 189 ret = -ENODEV; 190 goto out; 191 } 192 193 if (!(((dev->host_hw_state & H_RDY) == H_RDY) && 194 ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { 195 dev->mei_state = MEI_DISABLED; 196 dev_dbg(&dev->pdev->dev, 197 "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 198 dev->host_hw_state, dev->me_hw_state); 199 200 if (!(dev->host_hw_state & H_RDY)) 201 dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n"); 202 203 if (!(dev->me_hw_state & ME_RDY_HRA)) 204 dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n"); 205 206 dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); 207 ret = -ENODEV; 208 goto out; 209 } 210 211 if (dev->version.major_version != HBM_MAJOR_VERSION || 212 dev->version.minor_version != HBM_MINOR_VERSION) { 213 dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); 214 ret = -ENODEV; 215 goto out; 216 } 217 218 dev->recvd_msg = false; 219 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 220 dev->host_hw_state, dev->me_hw_state); 221 dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n"); 222 dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); 223 dev_dbg(&dev->pdev->dev, "MEI start success.\n"); 224 ret = 0; 225 226 out: 227 mutex_unlock(&dev->device_lock); 228 return ret; 229 } 230 231 /** 232 * mei_hw_reset - resets fw via mei csr register. 233 * 234 * @dev: the device structure 235 * @interrupts_enabled: if interrupt should be enabled after reset. 236 */ 237 static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled) 238 { 239 dev->host_hw_state |= (H_RST | H_IG); 240 241 if (interrupts_enabled) 242 mei_enable_interrupts(dev); 243 else 244 mei_disable_interrupts(dev); 245 } 246 247 /** 248 * mei_reset - resets host and fw. 249 * 250 * @dev: the device structure 251 * @interrupts_enabled: if interrupt should be enabled after reset. 252 */ 253 void mei_reset(struct mei_device *dev, int interrupts_enabled) 254 { 255 struct mei_cl *cl_pos = NULL; 256 struct mei_cl *cl_next = NULL; 257 struct mei_cl_cb *cb_pos = NULL; 258 struct mei_cl_cb *cb_next = NULL; 259 bool unexpected; 260 261 if (dev->mei_state == MEI_RECOVERING_FROM_RESET) { 262 dev->need_reset = true; 263 return; 264 } 265 266 unexpected = (dev->mei_state != MEI_INITIALIZING && 267 dev->mei_state != MEI_DISABLED && 268 dev->mei_state != MEI_POWER_DOWN && 269 dev->mei_state != MEI_POWER_UP); 270 271 dev->host_hw_state = mei_hcsr_read(dev); 272 273 dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n", 274 dev->host_hw_state); 275 276 mei_hw_reset(dev, interrupts_enabled); 277 278 dev->host_hw_state &= ~H_RST; 279 dev->host_hw_state |= H_IG; 280 281 mei_hcsr_set(dev); 282 283 dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n", 284 dev->host_hw_state); 285 286 dev->need_reset = false; 287 288 if (dev->mei_state != MEI_INITIALIZING) { 289 if (dev->mei_state != MEI_DISABLED && 290 dev->mei_state != MEI_POWER_DOWN) 291 dev->mei_state = MEI_RESETING; 292 293 list_for_each_entry_safe(cl_pos, 294 cl_next, &dev->file_list, link) { 295 cl_pos->state = MEI_FILE_DISCONNECTED; 296 cl_pos->mei_flow_ctrl_creds = 0; 297 cl_pos->read_cb = NULL; 298 cl_pos->timer_count = 0; 299 } 300 /* remove entry if already in list */ 301 dev_dbg(&dev->pdev->dev, "list del iamthif and wd file list.\n"); 302 mei_remove_client_from_file_list(dev, 303 dev->wd_cl.host_client_id); 304 305 mei_remove_client_from_file_list(dev, 306 dev->iamthif_cl.host_client_id); 307 308 mei_reset_iamthif_params(dev); 309 dev->extra_write_index = 0; 310 } 311 312 dev->me_clients_num = 0; 313 dev->rd_msg_hdr = 0; 314 dev->stop = false; 315 dev->wd_pending = false; 316 317 /* update the state of the registers after reset */ 318 dev->host_hw_state = mei_hcsr_read(dev); 319 dev->me_hw_state = mei_mecsr_read(dev); 320 321 dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 322 dev->host_hw_state, dev->me_hw_state); 323 324 if (unexpected) 325 dev_warn(&dev->pdev->dev, "unexpected reset.\n"); 326 327 /* Wake up all readings so they can be interrupted */ 328 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 329 if (waitqueue_active(&cl_pos->rx_wait)) { 330 dev_dbg(&dev->pdev->dev, "Waking up client!\n"); 331 wake_up_interruptible(&cl_pos->rx_wait); 332 } 333 } 334 /* remove all waiting requests */ 335 list_for_each_entry_safe(cb_pos, cb_next, 336 &dev->write_list.mei_cb.cb_list, cb_list) { 337 list_del(&cb_pos->cb_list); 338 mei_free_cb_private(cb_pos); 339 } 340 } 341 342 343 344 /** 345 * host_start_message - mei host sends start message. 346 * 347 * @dev: the device structure 348 * 349 * returns none. 350 */ 351 void mei_host_start_message(struct mei_device *dev) 352 { 353 struct mei_msg_hdr *mei_hdr; 354 struct hbm_host_version_request *host_start_req; 355 356 /* host start message */ 357 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 358 mei_hdr->host_addr = 0; 359 mei_hdr->me_addr = 0; 360 mei_hdr->length = sizeof(struct hbm_host_version_request); 361 mei_hdr->msg_complete = 1; 362 mei_hdr->reserved = 0; 363 364 host_start_req = 365 (struct hbm_host_version_request *) &dev->wr_msg_buf[1]; 366 memset(host_start_req, 0, sizeof(struct hbm_host_version_request)); 367 host_start_req->hbm_cmd = HOST_START_REQ_CMD; 368 host_start_req->host_version.major_version = HBM_MAJOR_VERSION; 369 host_start_req->host_version.minor_version = HBM_MINOR_VERSION; 370 dev->recvd_msg = false; 371 if (mei_write_message(dev, mei_hdr, (unsigned char *)host_start_req, 372 mei_hdr->length)) { 373 dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); 374 dev->mei_state = MEI_RESETING; 375 mei_reset(dev, 1); 376 } 377 dev->init_clients_state = MEI_START_MESSAGE; 378 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; 379 return ; 380 } 381 382 /** 383 * host_enum_clients_message - host sends enumeration client request message. 384 * 385 * @dev: the device structure 386 * 387 * returns none. 388 */ 389 void mei_host_enum_clients_message(struct mei_device *dev) 390 { 391 struct mei_msg_hdr *mei_hdr; 392 struct hbm_host_enum_request *host_enum_req; 393 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 394 /* enumerate clients */ 395 mei_hdr->host_addr = 0; 396 mei_hdr->me_addr = 0; 397 mei_hdr->length = sizeof(struct hbm_host_enum_request); 398 mei_hdr->msg_complete = 1; 399 mei_hdr->reserved = 0; 400 401 host_enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; 402 memset(host_enum_req, 0, sizeof(struct hbm_host_enum_request)); 403 host_enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; 404 if (mei_write_message(dev, mei_hdr, (unsigned char *)host_enum_req, 405 mei_hdr->length)) { 406 dev->mei_state = MEI_RESETING; 407 dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); 408 mei_reset(dev, 1); 409 } 410 dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; 411 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; 412 return; 413 } 414 415 416 /** 417 * allocate_me_clients_storage - allocates storage for me clients 418 * 419 * @dev: the device structure 420 * 421 * returns none. 422 */ 423 void mei_allocate_me_clients_storage(struct mei_device *dev) 424 { 425 struct mei_me_client *clients; 426 int b; 427 428 /* count how many ME clients we have */ 429 for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX) 430 dev->me_clients_num++; 431 432 if (dev->me_clients_num <= 0) 433 return ; 434 435 436 if (dev->me_clients != NULL) { 437 kfree(dev->me_clients); 438 dev->me_clients = NULL; 439 } 440 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n", 441 dev->me_clients_num * sizeof(struct mei_me_client)); 442 /* allocate storage for ME clients representation */ 443 clients = kcalloc(dev->me_clients_num, 444 sizeof(struct mei_me_client), GFP_KERNEL); 445 if (!clients) { 446 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); 447 dev->mei_state = MEI_RESETING; 448 mei_reset(dev, 1); 449 return ; 450 } 451 dev->me_clients = clients; 452 return ; 453 } 454 /** 455 * host_client_properties - reads properties for client 456 * 457 * @dev: the device structure 458 * 459 * returns: 460 * < 0 - Error. 461 * = 0 - no more clients. 462 * = 1 - still have clients to send properties request. 463 */ 464 int mei_host_client_properties(struct mei_device *dev) 465 { 466 struct mei_msg_hdr *mei_header; 467 struct hbm_props_request *host_cli_req; 468 int b; 469 u8 client_num = dev->me_client_presentation_num; 470 471 b = dev->me_client_index; 472 b = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, b); 473 if (b < MEI_CLIENTS_MAX) { 474 dev->me_clients[client_num].client_id = b; 475 dev->me_clients[client_num].mei_flow_ctrl_creds = 0; 476 mei_header = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; 477 mei_header->host_addr = 0; 478 mei_header->me_addr = 0; 479 mei_header->length = sizeof(struct hbm_props_request); 480 mei_header->msg_complete = 1; 481 mei_header->reserved = 0; 482 483 host_cli_req = (struct hbm_props_request *)&dev->wr_msg_buf[1]; 484 485 memset(host_cli_req, 0, sizeof(struct hbm_props_request)); 486 487 host_cli_req->hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; 488 host_cli_req->address = b; 489 490 if (mei_write_message(dev, mei_header, 491 (unsigned char *)host_cli_req, 492 mei_header->length)) { 493 dev->mei_state = MEI_RESETING; 494 dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); 495 mei_reset(dev, 1); 496 return -EIO; 497 } 498 499 dev->init_clients_timer = INIT_CLIENTS_TIMEOUT; 500 dev->me_client_index = b; 501 return 1; 502 } 503 504 return 0; 505 } 506 507 /** 508 * mei_init_file_private - initializes private file structure. 509 * 510 * @priv: private file structure to be initialized 511 * @file: the file structure 512 */ 513 void mei_cl_init(struct mei_cl *priv, struct mei_device *dev) 514 { 515 memset(priv, 0, sizeof(struct mei_cl)); 516 init_waitqueue_head(&priv->wait); 517 init_waitqueue_head(&priv->rx_wait); 518 init_waitqueue_head(&priv->tx_wait); 519 INIT_LIST_HEAD(&priv->link); 520 priv->reading_state = MEI_IDLE; 521 priv->writing_state = MEI_IDLE; 522 priv->dev = dev; 523 } 524 525 int mei_find_me_client_index(const struct mei_device *dev, uuid_le cuuid) 526 { 527 int i, res = -1; 528 529 for (i = 0; i < dev->me_clients_num; ++i) 530 if (uuid_le_cmp(cuuid, 531 dev->me_clients[i].props.protocol_name) == 0) { 532 res = i; 533 break; 534 } 535 536 return res; 537 } 538 539 540 /** 541 * mei_find_me_client_update_filext - searches for ME client guid 542 * sets client_id in mei_file_private if found 543 * @dev: the device structure 544 * @priv: private file structure to set client_id in 545 * @cguid: searched guid of ME client 546 * @client_id: id of host client to be set in file private structure 547 * 548 * returns ME client index 549 */ 550 u8 mei_find_me_client_update_filext(struct mei_device *dev, struct mei_cl *priv, 551 const uuid_le *cguid, u8 client_id) 552 { 553 int i; 554 555 if (!dev || !priv || !cguid) 556 return 0; 557 558 /* check for valid client id */ 559 i = mei_find_me_client_index(dev, *cguid); 560 if (i >= 0) { 561 priv->me_client_id = dev->me_clients[i].client_id; 562 priv->state = MEI_FILE_CONNECTING; 563 priv->host_client_id = client_id; 564 565 list_add_tail(&priv->link, &dev->file_list); 566 return (u8)i; 567 } 568 569 return 0; 570 } 571 572 /** 573 * host_init_iamthif - mei initialization iamthif client. 574 * 575 * @dev: the device structure 576 * 577 */ 578 void mei_host_init_iamthif(struct mei_device *dev) 579 { 580 u8 i; 581 unsigned char *msg_buf; 582 583 mei_cl_init(&dev->iamthif_cl, dev); 584 dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; 585 586 /* find ME amthi client */ 587 i = mei_find_me_client_update_filext(dev, &dev->iamthif_cl, 588 &mei_amthi_guid, MEI_IAMTHIF_HOST_CLIENT_ID); 589 if (dev->iamthif_cl.state != MEI_FILE_CONNECTING) { 590 dev_dbg(&dev->pdev->dev, "failed to find iamthif client.\n"); 591 return; 592 } 593 594 /* Assign iamthif_mtu to the value received from ME */ 595 596 dev->iamthif_mtu = dev->me_clients[i].props.max_msg_length; 597 dev_dbg(&dev->pdev->dev, "IAMTHIF_MTU = %d\n", 598 dev->me_clients[i].props.max_msg_length); 599 600 kfree(dev->iamthif_msg_buf); 601 dev->iamthif_msg_buf = NULL; 602 603 /* allocate storage for ME message buffer */ 604 msg_buf = kcalloc(dev->iamthif_mtu, 605 sizeof(unsigned char), GFP_KERNEL); 606 if (!msg_buf) { 607 dev_dbg(&dev->pdev->dev, "memory allocation for ME message buffer failed.\n"); 608 return; 609 } 610 611 dev->iamthif_msg_buf = msg_buf; 612 613 if (mei_connect(dev, &dev->iamthif_cl)) { 614 dev_dbg(&dev->pdev->dev, "Failed to connect to AMTHI client\n"); 615 dev->iamthif_cl.state = MEI_FILE_DISCONNECTED; 616 dev->iamthif_cl.host_client_id = 0; 617 } else { 618 dev->iamthif_cl.timer_count = CONNECT_TIMEOUT; 619 } 620 } 621 622 /** 623 * mei_alloc_file_private - allocates a private file structure and sets it up. 624 * @file: the file structure 625 * 626 * returns The allocated file or NULL on failure 627 */ 628 struct mei_cl *mei_cl_allocate(struct mei_device *dev) 629 { 630 struct mei_cl *cl; 631 632 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL); 633 if (!cl) 634 return NULL; 635 636 mei_cl_init(cl, dev); 637 638 return cl; 639 } 640 641 642 643 /** 644 * mei_disconnect_host_client - sends disconnect message to fw from host client. 645 * 646 * @dev: the device structure 647 * @cl: private data of the file object 648 * 649 * Locking: called under "dev->device_lock" lock 650 * 651 * returns 0 on success, <0 on failure. 652 */ 653 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) 654 { 655 int rets, err; 656 long timeout = 15; /* 15 seconds */ 657 struct mei_cl_cb *cb; 658 659 if (!dev || !cl) 660 return -ENODEV; 661 662 if (cl->state != MEI_FILE_DISCONNECTING) 663 return 0; 664 665 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); 666 if (!cb) 667 return -ENOMEM; 668 669 INIT_LIST_HEAD(&cb->cb_list); 670 cb->file_private = cl; 671 cb->major_file_operations = MEI_CLOSE; 672 if (dev->mei_host_buffer_is_empty) { 673 dev->mei_host_buffer_is_empty = false; 674 if (mei_disconnect(dev, cl)) { 675 rets = -ENODEV; 676 dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n"); 677 goto free; 678 } 679 mdelay(10); /* Wait for hardware disconnection ready */ 680 list_add_tail(&cb->cb_list, &dev->ctrl_rd_list.mei_cb.cb_list); 681 } else { 682 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); 683 list_add_tail(&cb->cb_list, 684 &dev->ctrl_wr_list.mei_cb.cb_list); 685 } 686 mutex_unlock(&dev->device_lock); 687 688 err = wait_event_timeout(dev->wait_recvd_msg, 689 (MEI_FILE_DISCONNECTED == cl->state), 690 timeout * HZ); 691 692 mutex_lock(&dev->device_lock); 693 if (MEI_FILE_DISCONNECTED == cl->state) { 694 rets = 0; 695 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n"); 696 } else { 697 rets = -ENODEV; 698 if (MEI_FILE_DISCONNECTED != cl->state) 699 dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n"); 700 701 if (err) 702 dev_dbg(&dev->pdev->dev, 703 "wait failed disconnect err=%08x\n", 704 err); 705 706 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n"); 707 } 708 709 mei_io_list_flush(&dev->ctrl_rd_list, cl); 710 mei_io_list_flush(&dev->ctrl_wr_list, cl); 711 free: 712 mei_free_cb_private(cb); 713 return rets; 714 } 715 716 /** 717 * mei_remove_client_from_file_list - 718 * removes file private data from device file list 719 * 720 * @dev: the device structure 721 * @host_client_id: host client id to be removed 722 */ 723 void mei_remove_client_from_file_list(struct mei_device *dev, 724 u8 host_client_id) 725 { 726 struct mei_cl *cl_pos = NULL; 727 struct mei_cl *cl_next = NULL; 728 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 729 if (host_client_id == cl_pos->host_client_id) { 730 dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", 731 cl_pos->host_client_id, 732 cl_pos->me_client_id); 733 list_del_init(&cl_pos->link); 734 break; 735 } 736 } 737 } 738