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 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 46 47 /** 48 * mei_io_list_flush - removes list entry belonging to cl. 49 * 50 * @list: An instance of our list structure 51 * @cl: private data of the file object 52 */ 53 void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl) 54 { 55 struct mei_cl_cb *pos; 56 struct mei_cl_cb *next; 57 58 list_for_each_entry_safe(pos, next, &list->list, list) { 59 if (pos->cl) { 60 if (mei_cl_cmp_id(cl, pos->cl)) 61 list_del(&pos->list); 62 } 63 } 64 } 65 /** 66 * mei_cl_flush_queues - flushes queue lists belonging to cl. 67 * 68 * @dev: the device structure 69 * @cl: private data of the file object 70 */ 71 int mei_cl_flush_queues(struct mei_cl *cl) 72 { 73 if (!cl || !cl->dev) 74 return -EINVAL; 75 76 dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n"); 77 mei_io_list_flush(&cl->dev->read_list, cl); 78 mei_io_list_flush(&cl->dev->write_list, cl); 79 mei_io_list_flush(&cl->dev->write_waiting_list, cl); 80 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); 81 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); 82 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); 83 mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); 84 return 0; 85 } 86 87 88 89 /** 90 * init_mei_device - allocates and initializes the mei device structure 91 * 92 * @pdev: The pci device structure 93 * 94 * returns The mei_device_device pointer on success, NULL on failure. 95 */ 96 struct mei_device *mei_device_init(struct pci_dev *pdev) 97 { 98 struct mei_device *dev; 99 100 dev = kzalloc(sizeof(struct mei_device), GFP_KERNEL); 101 if (!dev) 102 return NULL; 103 104 /* setup our list array */ 105 INIT_LIST_HEAD(&dev->file_list); 106 INIT_LIST_HEAD(&dev->wd_cl.link); 107 INIT_LIST_HEAD(&dev->iamthif_cl.link); 108 mutex_init(&dev->device_lock); 109 init_waitqueue_head(&dev->wait_recvd_msg); 110 init_waitqueue_head(&dev->wait_stop_wd); 111 dev->dev_state = MEI_DEV_INITIALIZING; 112 dev->iamthif_state = MEI_IAMTHIF_IDLE; 113 114 mei_io_list_init(&dev->read_list); 115 mei_io_list_init(&dev->write_list); 116 mei_io_list_init(&dev->write_waiting_list); 117 mei_io_list_init(&dev->ctrl_wr_list); 118 mei_io_list_init(&dev->ctrl_rd_list); 119 mei_io_list_init(&dev->amthif_cmd_list); 120 mei_io_list_init(&dev->amthif_rd_complete_list); 121 dev->pdev = pdev; 122 return dev; 123 } 124 125 /** 126 * mei_hw_init - initializes host and fw to start work. 127 * 128 * @dev: the device structure 129 * 130 * returns 0 on success, <0 on failure. 131 */ 132 int mei_hw_init(struct mei_device *dev) 133 { 134 int err = 0; 135 int ret; 136 137 mutex_lock(&dev->device_lock); 138 139 dev->host_hw_state = mei_hcsr_read(dev); 140 dev->me_hw_state = mei_mecsr_read(dev); 141 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, mestate = 0x%08x.\n", 142 dev->host_hw_state, dev->me_hw_state); 143 144 /* acknowledge interrupt and stop interupts */ 145 if ((dev->host_hw_state & H_IS) == H_IS) 146 mei_reg_write(dev, H_CSR, dev->host_hw_state); 147 148 /* Doesn't change in runtime */ 149 dev->hbuf_depth = (dev->host_hw_state & H_CBD) >> 24; 150 151 dev->recvd_msg = false; 152 dev_dbg(&dev->pdev->dev, "reset in start the mei device.\n"); 153 154 mei_reset(dev, 1); 155 156 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 157 dev->host_hw_state, dev->me_hw_state); 158 159 /* wait for ME to turn on ME_RDY */ 160 if (!dev->recvd_msg) { 161 mutex_unlock(&dev->device_lock); 162 err = wait_event_interruptible_timeout(dev->wait_recvd_msg, 163 dev->recvd_msg, 164 mei_secs_to_jiffies(MEI_INTEROP_TIMEOUT)); 165 mutex_lock(&dev->device_lock); 166 } 167 168 if (err <= 0 && !dev->recvd_msg) { 169 dev->dev_state = MEI_DEV_DISABLED; 170 dev_dbg(&dev->pdev->dev, 171 "wait_event_interruptible_timeout failed" 172 "on wait for ME to turn on ME_RDY.\n"); 173 ret = -ENODEV; 174 goto out; 175 } 176 177 if (!(((dev->host_hw_state & H_RDY) == H_RDY) && 178 ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA))) { 179 dev->dev_state = MEI_DEV_DISABLED; 180 dev_dbg(&dev->pdev->dev, 181 "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 182 dev->host_hw_state, dev->me_hw_state); 183 184 if (!(dev->host_hw_state & H_RDY)) 185 dev_dbg(&dev->pdev->dev, "host turn off H_RDY.\n"); 186 187 if (!(dev->me_hw_state & ME_RDY_HRA)) 188 dev_dbg(&dev->pdev->dev, "ME turn off ME_RDY.\n"); 189 190 dev_err(&dev->pdev->dev, "link layer initialization failed.\n"); 191 ret = -ENODEV; 192 goto out; 193 } 194 195 if (dev->version.major_version != HBM_MAJOR_VERSION || 196 dev->version.minor_version != HBM_MINOR_VERSION) { 197 dev_dbg(&dev->pdev->dev, "MEI start failed.\n"); 198 ret = -ENODEV; 199 goto out; 200 } 201 202 dev->recvd_msg = false; 203 dev_dbg(&dev->pdev->dev, "host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 204 dev->host_hw_state, dev->me_hw_state); 205 dev_dbg(&dev->pdev->dev, "ME turn on ME_RDY and host turn on H_RDY.\n"); 206 dev_dbg(&dev->pdev->dev, "link layer has been established.\n"); 207 dev_dbg(&dev->pdev->dev, "MEI start success.\n"); 208 ret = 0; 209 210 out: 211 mutex_unlock(&dev->device_lock); 212 return ret; 213 } 214 215 /** 216 * mei_hw_reset - resets fw via mei csr register. 217 * 218 * @dev: the device structure 219 * @interrupts_enabled: if interrupt should be enabled after reset. 220 */ 221 static void mei_hw_reset(struct mei_device *dev, int interrupts_enabled) 222 { 223 dev->host_hw_state |= (H_RST | H_IG); 224 225 if (interrupts_enabled) 226 mei_enable_interrupts(dev); 227 else 228 mei_disable_interrupts(dev); 229 } 230 231 /** 232 * mei_reset - resets host and fw. 233 * 234 * @dev: the device structure 235 * @interrupts_enabled: if interrupt should be enabled after reset. 236 */ 237 void mei_reset(struct mei_device *dev, int interrupts_enabled) 238 { 239 struct mei_cl *cl_pos = NULL; 240 struct mei_cl *cl_next = NULL; 241 struct mei_cl_cb *cb_pos = NULL; 242 struct mei_cl_cb *cb_next = NULL; 243 bool unexpected; 244 245 if (dev->dev_state == MEI_DEV_RECOVERING_FROM_RESET) { 246 dev->need_reset = true; 247 return; 248 } 249 250 unexpected = (dev->dev_state != MEI_DEV_INITIALIZING && 251 dev->dev_state != MEI_DEV_DISABLED && 252 dev->dev_state != MEI_DEV_POWER_DOWN && 253 dev->dev_state != MEI_DEV_POWER_UP); 254 255 dev->host_hw_state = mei_hcsr_read(dev); 256 257 dev_dbg(&dev->pdev->dev, "before reset host_hw_state = 0x%08x.\n", 258 dev->host_hw_state); 259 260 mei_hw_reset(dev, interrupts_enabled); 261 262 dev->host_hw_state &= ~H_RST; 263 dev->host_hw_state |= H_IG; 264 265 mei_hcsr_set(dev); 266 267 dev_dbg(&dev->pdev->dev, "currently saved host_hw_state = 0x%08x.\n", 268 dev->host_hw_state); 269 270 dev->need_reset = false; 271 272 if (dev->dev_state != MEI_DEV_INITIALIZING) { 273 if (dev->dev_state != MEI_DEV_DISABLED && 274 dev->dev_state != MEI_DEV_POWER_DOWN) 275 dev->dev_state = MEI_DEV_RESETING; 276 277 list_for_each_entry_safe(cl_pos, 278 cl_next, &dev->file_list, link) { 279 cl_pos->state = MEI_FILE_DISCONNECTED; 280 cl_pos->mei_flow_ctrl_creds = 0; 281 cl_pos->read_cb = NULL; 282 cl_pos->timer_count = 0; 283 } 284 /* remove entry if already in list */ 285 dev_dbg(&dev->pdev->dev, "remove iamthif and wd from the file list.\n"); 286 mei_me_cl_unlink(dev, &dev->wd_cl); 287 288 mei_me_cl_unlink(dev, &dev->iamthif_cl); 289 290 mei_amthif_reset_params(dev); 291 memset(&dev->wr_ext_msg, 0, sizeof(dev->wr_ext_msg)); 292 } 293 294 dev->me_clients_num = 0; 295 dev->rd_msg_hdr = 0; 296 dev->wd_pending = false; 297 298 /* update the state of the registers after reset */ 299 dev->host_hw_state = mei_hcsr_read(dev); 300 dev->me_hw_state = mei_mecsr_read(dev); 301 302 dev_dbg(&dev->pdev->dev, "after reset host_hw_state = 0x%08x, me_hw_state = 0x%08x.\n", 303 dev->host_hw_state, dev->me_hw_state); 304 305 if (unexpected) 306 dev_warn(&dev->pdev->dev, "unexpected reset: dev_state = %s\n", 307 mei_dev_state_str(dev->dev_state)); 308 309 /* Wake up all readings so they can be interrupted */ 310 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 311 if (waitqueue_active(&cl_pos->rx_wait)) { 312 dev_dbg(&dev->pdev->dev, "Waking up client!\n"); 313 wake_up_interruptible(&cl_pos->rx_wait); 314 } 315 } 316 /* remove all waiting requests */ 317 list_for_each_entry_safe(cb_pos, cb_next, &dev->write_list.list, list) { 318 list_del(&cb_pos->list); 319 mei_io_cb_free(cb_pos); 320 } 321 } 322 323 324 325 /** 326 * host_start_message - mei host sends start message. 327 * 328 * @dev: the device structure 329 * 330 * returns none. 331 */ 332 void mei_host_start_message(struct mei_device *dev) 333 { 334 struct mei_msg_hdr *mei_hdr; 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); 339 340 /* host start message */ 341 start_req = (struct hbm_host_version_request *)&dev->wr_msg_buf[1]; 342 memset(start_req, 0, len); 343 start_req->hbm_cmd = HOST_START_REQ_CMD; 344 start_req->host_version.major_version = HBM_MAJOR_VERSION; 345 start_req->host_version.minor_version = HBM_MINOR_VERSION; 346 347 dev->recvd_msg = false; 348 if (mei_write_message(dev, mei_hdr, (unsigned char *)start_req, len)) { 349 dev_dbg(&dev->pdev->dev, "write send version message to FW fail.\n"); 350 dev->dev_state = MEI_DEV_RESETING; 351 mei_reset(dev, 1); 352 } 353 dev->init_clients_state = MEI_START_MESSAGE; 354 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 355 return ; 356 } 357 358 /** 359 * host_enum_clients_message - host sends enumeration client request message. 360 * 361 * @dev: the device structure 362 * 363 * returns none. 364 */ 365 void mei_host_enum_clients_message(struct mei_device *dev) 366 { 367 struct mei_msg_hdr *mei_hdr; 368 struct hbm_host_enum_request *enum_req; 369 const size_t len = sizeof(struct hbm_host_enum_request); 370 /* enumerate clients */ 371 mei_hdr = mei_hbm_hdr(&dev->wr_msg_buf[0], len); 372 373 enum_req = (struct hbm_host_enum_request *) &dev->wr_msg_buf[1]; 374 memset(enum_req, 0, sizeof(struct hbm_host_enum_request)); 375 enum_req->hbm_cmd = HOST_ENUM_REQ_CMD; 376 377 if (mei_write_message(dev, mei_hdr, (unsigned char *)enum_req, len)) { 378 dev->dev_state = MEI_DEV_RESETING; 379 dev_dbg(&dev->pdev->dev, "write send enumeration request message to FW fail.\n"); 380 mei_reset(dev, 1); 381 } 382 dev->init_clients_state = MEI_ENUM_CLIENTS_MESSAGE; 383 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 384 return; 385 } 386 387 388 /** 389 * allocate_me_clients_storage - allocates storage for me clients 390 * 391 * @dev: the device structure 392 * 393 * returns none. 394 */ 395 void mei_allocate_me_clients_storage(struct mei_device *dev) 396 { 397 struct mei_me_client *clients; 398 int b; 399 400 /* count how many ME clients we have */ 401 for_each_set_bit(b, dev->me_clients_map, MEI_CLIENTS_MAX) 402 dev->me_clients_num++; 403 404 if (dev->me_clients_num <= 0) 405 return ; 406 407 408 if (dev->me_clients != NULL) { 409 kfree(dev->me_clients); 410 dev->me_clients = NULL; 411 } 412 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients size=%zd.\n", 413 dev->me_clients_num * sizeof(struct mei_me_client)); 414 /* allocate storage for ME clients representation */ 415 clients = kcalloc(dev->me_clients_num, 416 sizeof(struct mei_me_client), GFP_KERNEL); 417 if (!clients) { 418 dev_dbg(&dev->pdev->dev, "memory allocation for ME clients failed.\n"); 419 dev->dev_state = MEI_DEV_RESETING; 420 mei_reset(dev, 1); 421 return ; 422 } 423 dev->me_clients = clients; 424 return ; 425 } 426 427 void mei_host_client_init(struct work_struct *work) 428 { 429 struct mei_device *dev = container_of(work, 430 struct mei_device, init_work); 431 struct mei_client_properties *client_props; 432 int i; 433 434 mutex_lock(&dev->device_lock); 435 436 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); 437 dev->open_handle_count = 0; 438 439 /* 440 * Reserving the first three client IDs 441 * 0: Reserved for MEI Bus Message communications 442 * 1: Reserved for Watchdog 443 * 2: Reserved for AMTHI 444 */ 445 bitmap_set(dev->host_clients_map, 0, 3); 446 447 for (i = 0; i < dev->me_clients_num; i++) { 448 client_props = &dev->me_clients[i].props; 449 450 if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid)) 451 mei_amthif_host_init(dev); 452 else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid)) 453 mei_wd_host_init(dev); 454 } 455 456 dev->dev_state = MEI_DEV_ENABLED; 457 458 mutex_unlock(&dev->device_lock); 459 } 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; 481 } 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 507 return 0; 508 } 509 510 /** 511 * mei_init_file_private - initializes private file structure. 512 * 513 * @priv: private file structure to be initialized 514 * @file: the file structure 515 */ 516 void mei_cl_init(struct mei_cl *priv, struct mei_device *dev) 517 { 518 memset(priv, 0, sizeof(struct mei_cl)); 519 init_waitqueue_head(&priv->wait); 520 init_waitqueue_head(&priv->rx_wait); 521 init_waitqueue_head(&priv->tx_wait); 522 INIT_LIST_HEAD(&priv->link); 523 priv->reading_state = MEI_IDLE; 524 priv->writing_state = MEI_IDLE; 525 priv->dev = dev; 526 } 527 528 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *cuuid) 529 { 530 int i, res = -ENOENT; 531 532 for (i = 0; i < dev->me_clients_num; ++i) 533 if (uuid_le_cmp(*cuuid, 534 dev->me_clients[i].props.protocol_name) == 0) { 535 res = i; 536 break; 537 } 538 539 return res; 540 } 541 542 543 /** 544 * mei_me_cl_link - create link between host and me clinet and add 545 * me_cl to the list 546 * 547 * @dev: the device structure 548 * @cl: link between me and host client assocated with opened file descriptor 549 * @cuuid: uuid of ME client 550 * @client_id: id of the host client 551 * 552 * returns ME client index if ME client 553 * -EINVAL on incorrect values 554 * -ENONET if client not found 555 */ 556 int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl, 557 const uuid_le *cuuid, u8 host_cl_id) 558 { 559 int i; 560 561 if (!dev || !cl || !cuuid) 562 return -EINVAL; 563 564 /* check for valid client id */ 565 i = mei_me_cl_by_uuid(dev, cuuid); 566 if (i >= 0) { 567 cl->me_client_id = dev->me_clients[i].client_id; 568 cl->state = MEI_FILE_CONNECTING; 569 cl->host_client_id = host_cl_id; 570 571 list_add_tail(&cl->link, &dev->file_list); 572 return (u8)i; 573 } 574 575 return -ENOENT; 576 } 577 /** 578 * mei_me_cl_unlink - remove me_cl from the list 579 * 580 * @dev: the device structure 581 * @host_client_id: host client id to be removed 582 */ 583 void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl) 584 { 585 struct mei_cl *pos, *next; 586 list_for_each_entry_safe(pos, next, &dev->file_list, link) { 587 if (cl->host_client_id == pos->host_client_id) { 588 dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", 589 pos->host_client_id, pos->me_client_id); 590 list_del_init(&pos->link); 591 break; 592 } 593 } 594 } 595 596 /** 597 * mei_alloc_file_private - allocates a private file structure and sets it up. 598 * @file: the file structure 599 * 600 * returns The allocated file or NULL on failure 601 */ 602 struct mei_cl *mei_cl_allocate(struct mei_device *dev) 603 { 604 struct mei_cl *cl; 605 606 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL); 607 if (!cl) 608 return NULL; 609 610 mei_cl_init(cl, dev); 611 612 return cl; 613 } 614 615 616 617 /** 618 * mei_disconnect_host_client - sends disconnect message to fw from host client. 619 * 620 * @dev: the device structure 621 * @cl: private data of the file object 622 * 623 * Locking: called under "dev->device_lock" lock 624 * 625 * returns 0 on success, <0 on failure. 626 */ 627 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) 628 { 629 struct mei_cl_cb *cb; 630 int rets, err; 631 632 if (!dev || !cl) 633 return -ENODEV; 634 635 if (cl->state != MEI_FILE_DISCONNECTING) 636 return 0; 637 638 cb = mei_io_cb_init(cl, NULL); 639 if (!cb) 640 return -ENOMEM; 641 642 cb->fop_type = MEI_FOP_CLOSE; 643 if (dev->mei_host_buffer_is_empty) { 644 dev->mei_host_buffer_is_empty = false; 645 if (mei_disconnect(dev, cl)) { 646 rets = -ENODEV; 647 dev_dbg(&dev->pdev->dev, "failed to call mei_disconnect.\n"); 648 goto free; 649 } 650 mdelay(10); /* Wait for hardware disconnection ready */ 651 list_add_tail(&cb->list, &dev->ctrl_rd_list.list); 652 } else { 653 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); 654 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 655 656 } 657 mutex_unlock(&dev->device_lock); 658 659 err = wait_event_timeout(dev->wait_recvd_msg, 660 MEI_FILE_DISCONNECTED == cl->state, 661 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); 662 663 mutex_lock(&dev->device_lock); 664 if (MEI_FILE_DISCONNECTED == cl->state) { 665 rets = 0; 666 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n"); 667 } else { 668 rets = -ENODEV; 669 if (MEI_FILE_DISCONNECTED != cl->state) 670 dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n"); 671 672 if (err) 673 dev_dbg(&dev->pdev->dev, 674 "wait failed disconnect err=%08x\n", 675 err); 676 677 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n"); 678 } 679 680 mei_io_list_flush(&dev->ctrl_rd_list, cl); 681 mei_io_list_flush(&dev->ctrl_wr_list, cl); 682 free: 683 mei_io_cb_free(cb); 684 return rets; 685 } 686 687