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 <linux/mei.h> 23 24 #include "mei_dev.h" 25 #include "hbm.h" 26 #include "interface.h" 27 28 29 /** 30 * mei_io_list_flush - removes list entry belonging to cl. 31 * 32 * @list: An instance of our list structure 33 * @cl: host client 34 */ 35 void mei_io_list_flush(struct mei_cl_cb *list, struct mei_cl *cl) 36 { 37 struct mei_cl_cb *cb; 38 struct mei_cl_cb *next; 39 40 list_for_each_entry_safe(cb, next, &list->list, list) { 41 if (cb->cl && mei_cl_cmp_id(cl, cb->cl)) 42 list_del(&cb->list); 43 } 44 } 45 46 /** 47 * mei_io_cb_free - free mei_cb_private related memory 48 * 49 * @cb: mei callback struct 50 */ 51 void mei_io_cb_free(struct mei_cl_cb *cb) 52 { 53 if (cb == NULL) 54 return; 55 56 kfree(cb->request_buffer.data); 57 kfree(cb->response_buffer.data); 58 kfree(cb); 59 } 60 61 /** 62 * mei_io_cb_init - allocate and initialize io callback 63 * 64 * @cl - mei client 65 * @file: pointer to file structure 66 * 67 * returns mei_cl_cb pointer or NULL; 68 */ 69 struct mei_cl_cb *mei_io_cb_init(struct mei_cl *cl, struct file *fp) 70 { 71 struct mei_cl_cb *cb; 72 73 cb = kzalloc(sizeof(struct mei_cl_cb), GFP_KERNEL); 74 if (!cb) 75 return NULL; 76 77 mei_io_list_init(cb); 78 79 cb->file_object = fp; 80 cb->cl = cl; 81 cb->buf_idx = 0; 82 return cb; 83 } 84 85 /** 86 * mei_io_cb_alloc_req_buf - allocate request buffer 87 * 88 * @cb - io callback structure 89 * @size: size of the buffer 90 * 91 * returns 0 on success 92 * -EINVAL if cb is NULL 93 * -ENOMEM if allocation failed 94 */ 95 int mei_io_cb_alloc_req_buf(struct mei_cl_cb *cb, size_t length) 96 { 97 if (!cb) 98 return -EINVAL; 99 100 if (length == 0) 101 return 0; 102 103 cb->request_buffer.data = kmalloc(length, GFP_KERNEL); 104 if (!cb->request_buffer.data) 105 return -ENOMEM; 106 cb->request_buffer.size = length; 107 return 0; 108 } 109 /** 110 * mei_io_cb_alloc_req_buf - allocate respose buffer 111 * 112 * @cb - io callback structure 113 * @size: size of the buffer 114 * 115 * returns 0 on success 116 * -EINVAL if cb is NULL 117 * -ENOMEM if allocation failed 118 */ 119 int mei_io_cb_alloc_resp_buf(struct mei_cl_cb *cb, size_t length) 120 { 121 if (!cb) 122 return -EINVAL; 123 124 if (length == 0) 125 return 0; 126 127 cb->response_buffer.data = kmalloc(length, GFP_KERNEL); 128 if (!cb->response_buffer.data) 129 return -ENOMEM; 130 cb->response_buffer.size = length; 131 return 0; 132 } 133 134 135 136 /** 137 * mei_cl_flush_queues - flushes queue lists belonging to cl. 138 * 139 * @dev: the device structure 140 * @cl: host client 141 */ 142 int mei_cl_flush_queues(struct mei_cl *cl) 143 { 144 if (!cl || !cl->dev) 145 return -EINVAL; 146 147 dev_dbg(&cl->dev->pdev->dev, "remove list entry belonging to cl\n"); 148 mei_io_list_flush(&cl->dev->read_list, cl); 149 mei_io_list_flush(&cl->dev->write_list, cl); 150 mei_io_list_flush(&cl->dev->write_waiting_list, cl); 151 mei_io_list_flush(&cl->dev->ctrl_wr_list, cl); 152 mei_io_list_flush(&cl->dev->ctrl_rd_list, cl); 153 mei_io_list_flush(&cl->dev->amthif_cmd_list, cl); 154 mei_io_list_flush(&cl->dev->amthif_rd_complete_list, cl); 155 return 0; 156 } 157 158 /** 159 * mei_me_cl_by_uuid - locate index of me client 160 * 161 * @dev: mei device 162 * returns me client index or -ENOENT if not found 163 */ 164 int mei_me_cl_by_uuid(const struct mei_device *dev, const uuid_le *uuid) 165 { 166 int i, res = -ENOENT; 167 168 for (i = 0; i < dev->me_clients_num; ++i) 169 if (uuid_le_cmp(*uuid, 170 dev->me_clients[i].props.protocol_name) == 0) { 171 res = i; 172 break; 173 } 174 175 return res; 176 } 177 178 179 /** 180 * mei_me_cl_by_id return index to me_clients for client_id 181 * 182 * @dev: the device structure 183 * @client_id: me client id 184 * 185 * Locking: called under "dev->device_lock" lock 186 * 187 * returns index on success, -ENOENT on failure. 188 */ 189 190 int mei_me_cl_by_id(struct mei_device *dev, u8 client_id) 191 { 192 int i; 193 for (i = 0; i < dev->me_clients_num; i++) 194 if (dev->me_clients[i].client_id == client_id) 195 break; 196 if (WARN_ON(dev->me_clients[i].client_id != client_id)) 197 return -ENOENT; 198 199 if (i == dev->me_clients_num) 200 return -ENOENT; 201 202 return i; 203 } 204 205 /** 206 * mei_cl_init - initializes intialize cl. 207 * 208 * @cl: host client to be initialized 209 * @dev: mei device 210 */ 211 void mei_cl_init(struct mei_cl *cl, struct mei_device *dev) 212 { 213 memset(cl, 0, sizeof(struct mei_cl)); 214 init_waitqueue_head(&cl->wait); 215 init_waitqueue_head(&cl->rx_wait); 216 init_waitqueue_head(&cl->tx_wait); 217 INIT_LIST_HEAD(&cl->link); 218 cl->reading_state = MEI_IDLE; 219 cl->writing_state = MEI_IDLE; 220 cl->dev = dev; 221 } 222 223 /** 224 * mei_cl_allocate - allocates cl structure and sets it up. 225 * 226 * @dev: mei device 227 * returns The allocated file or NULL on failure 228 */ 229 struct mei_cl *mei_cl_allocate(struct mei_device *dev) 230 { 231 struct mei_cl *cl; 232 233 cl = kmalloc(sizeof(struct mei_cl), GFP_KERNEL); 234 if (!cl) 235 return NULL; 236 237 mei_cl_init(cl, dev); 238 239 return cl; 240 } 241 242 243 /** 244 * mei_me_cl_link - create link between host and me clinet and add 245 * me_cl to the list 246 * 247 * @dev: the device structure 248 * @cl: link between me and host client assocated with opened file descriptor 249 * @uuid: uuid of ME client 250 * @client_id: id of the host client 251 * 252 * returns ME client index if ME client 253 * -EINVAL on incorrect values 254 * -ENONET if client not found 255 */ 256 int mei_me_cl_link(struct mei_device *dev, struct mei_cl *cl, 257 const uuid_le *uuid, u8 host_cl_id) 258 { 259 int i; 260 261 if (!dev || !cl || !uuid) 262 return -EINVAL; 263 264 /* check for valid client id */ 265 i = mei_me_cl_by_uuid(dev, uuid); 266 if (i >= 0) { 267 cl->me_client_id = dev->me_clients[i].client_id; 268 cl->state = MEI_FILE_CONNECTING; 269 cl->host_client_id = host_cl_id; 270 271 list_add_tail(&cl->link, &dev->file_list); 272 return (u8)i; 273 } 274 275 return -ENOENT; 276 } 277 /** 278 * mei_me_cl_unlink - remove me_cl from the list 279 * 280 * @dev: the device structure 281 * @host_client_id: host client id to be removed 282 */ 283 void mei_me_cl_unlink(struct mei_device *dev, struct mei_cl *cl) 284 { 285 struct mei_cl *pos, *next; 286 list_for_each_entry_safe(pos, next, &dev->file_list, link) { 287 if (cl->host_client_id == pos->host_client_id) { 288 dev_dbg(&dev->pdev->dev, "remove host client = %d, ME client = %d\n", 289 pos->host_client_id, pos->me_client_id); 290 list_del_init(&pos->link); 291 break; 292 } 293 } 294 } 295 296 297 void mei_host_client_init(struct work_struct *work) 298 { 299 struct mei_device *dev = container_of(work, 300 struct mei_device, init_work); 301 struct mei_client_properties *client_props; 302 int i; 303 304 mutex_lock(&dev->device_lock); 305 306 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); 307 dev->open_handle_count = 0; 308 309 /* 310 * Reserving the first three client IDs 311 * 0: Reserved for MEI Bus Message communications 312 * 1: Reserved for Watchdog 313 * 2: Reserved for AMTHI 314 */ 315 bitmap_set(dev->host_clients_map, 0, 3); 316 317 for (i = 0; i < dev->me_clients_num; i++) { 318 client_props = &dev->me_clients[i].props; 319 320 if (!uuid_le_cmp(client_props->protocol_name, mei_amthi_guid)) 321 mei_amthif_host_init(dev); 322 else if (!uuid_le_cmp(client_props->protocol_name, mei_wd_guid)) 323 mei_wd_host_init(dev); 324 } 325 326 dev->dev_state = MEI_DEV_ENABLED; 327 328 mutex_unlock(&dev->device_lock); 329 } 330 331 332 /** 333 * mei_disconnect_host_client - sends disconnect message to fw from host client. 334 * 335 * @dev: the device structure 336 * @cl: private data of the file object 337 * 338 * Locking: called under "dev->device_lock" lock 339 * 340 * returns 0 on success, <0 on failure. 341 */ 342 int mei_disconnect_host_client(struct mei_device *dev, struct mei_cl *cl) 343 { 344 struct mei_cl_cb *cb; 345 int rets, err; 346 347 if (!dev || !cl) 348 return -ENODEV; 349 350 if (cl->state != MEI_FILE_DISCONNECTING) 351 return 0; 352 353 cb = mei_io_cb_init(cl, NULL); 354 if (!cb) 355 return -ENOMEM; 356 357 cb->fop_type = MEI_FOP_CLOSE; 358 if (dev->mei_host_buffer_is_empty) { 359 dev->mei_host_buffer_is_empty = false; 360 if (mei_hbm_cl_disconnect_req(dev, cl)) { 361 rets = -ENODEV; 362 dev_err(&dev->pdev->dev, "failed to disconnect.\n"); 363 goto free; 364 } 365 mdelay(10); /* Wait for hardware disconnection ready */ 366 list_add_tail(&cb->list, &dev->ctrl_rd_list.list); 367 } else { 368 dev_dbg(&dev->pdev->dev, "add disconnect cb to control write list\n"); 369 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 370 371 } 372 mutex_unlock(&dev->device_lock); 373 374 err = wait_event_timeout(dev->wait_recvd_msg, 375 MEI_FILE_DISCONNECTED == cl->state, 376 mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); 377 378 mutex_lock(&dev->device_lock); 379 if (MEI_FILE_DISCONNECTED == cl->state) { 380 rets = 0; 381 dev_dbg(&dev->pdev->dev, "successfully disconnected from FW client.\n"); 382 } else { 383 rets = -ENODEV; 384 if (MEI_FILE_DISCONNECTED != cl->state) 385 dev_dbg(&dev->pdev->dev, "wrong status client disconnect.\n"); 386 387 if (err) 388 dev_dbg(&dev->pdev->dev, 389 "wait failed disconnect err=%08x\n", 390 err); 391 392 dev_dbg(&dev->pdev->dev, "failed to disconnect from FW client.\n"); 393 } 394 395 mei_io_list_flush(&dev->ctrl_rd_list, cl); 396 mei_io_list_flush(&dev->ctrl_wr_list, cl); 397 free: 398 mei_io_cb_free(cb); 399 return rets; 400 } 401 402 403 /** 404 * mei_other_client_is_connecting - checks if other 405 * client with the same client id is connected. 406 * 407 * @dev: the device structure 408 * @cl: private data of the file object 409 * 410 * returns 1 if other client is connected, 0 - otherwise. 411 */ 412 int mei_other_client_is_connecting(struct mei_device *dev, 413 struct mei_cl *cl) 414 { 415 struct mei_cl *cl_pos = NULL; 416 struct mei_cl *cl_next = NULL; 417 418 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 419 if ((cl_pos->state == MEI_FILE_CONNECTING) && 420 (cl_pos != cl) && 421 cl->me_client_id == cl_pos->me_client_id) 422 return 1; 423 424 } 425 return 0; 426 } 427 428 /** 429 * mei_flow_ctrl_creds - checks flow_control credentials. 430 * 431 * @dev: the device structure 432 * @cl: private data of the file object 433 * 434 * returns 1 if mei_flow_ctrl_creds >0, 0 - otherwise. 435 * -ENOENT if mei_cl is not present 436 * -EINVAL if single_recv_buf == 0 437 */ 438 int mei_flow_ctrl_creds(struct mei_device *dev, struct mei_cl *cl) 439 { 440 int i; 441 442 if (!dev->me_clients_num) 443 return 0; 444 445 if (cl->mei_flow_ctrl_creds > 0) 446 return 1; 447 448 for (i = 0; i < dev->me_clients_num; i++) { 449 struct mei_me_client *me_cl = &dev->me_clients[i]; 450 if (me_cl->client_id == cl->me_client_id) { 451 if (me_cl->mei_flow_ctrl_creds) { 452 if (WARN_ON(me_cl->props.single_recv_buf == 0)) 453 return -EINVAL; 454 return 1; 455 } else { 456 return 0; 457 } 458 } 459 } 460 return -ENOENT; 461 } 462 463 /** 464 * mei_flow_ctrl_reduce - reduces flow_control. 465 * 466 * @dev: the device structure 467 * @cl: private data of the file object 468 * @returns 469 * 0 on success 470 * -ENOENT when me client is not found 471 * -EINVAL when ctrl credits are <= 0 472 */ 473 int mei_flow_ctrl_reduce(struct mei_device *dev, struct mei_cl *cl) 474 { 475 int i; 476 477 if (!dev->me_clients_num) 478 return -ENOENT; 479 480 for (i = 0; i < dev->me_clients_num; i++) { 481 struct mei_me_client *me_cl = &dev->me_clients[i]; 482 if (me_cl->client_id == cl->me_client_id) { 483 if (me_cl->props.single_recv_buf != 0) { 484 if (WARN_ON(me_cl->mei_flow_ctrl_creds <= 0)) 485 return -EINVAL; 486 dev->me_clients[i].mei_flow_ctrl_creds--; 487 } else { 488 if (WARN_ON(cl->mei_flow_ctrl_creds <= 0)) 489 return -EINVAL; 490 cl->mei_flow_ctrl_creds--; 491 } 492 return 0; 493 } 494 } 495 return -ENOENT; 496 } 497 498 499 500 /** 501 * mei_ioctl_connect_client - the connect to fw client IOCTL function 502 * 503 * @dev: the device structure 504 * @data: IOCTL connect data, input and output parameters 505 * @file: private data of the file object 506 * 507 * Locking: called under "dev->device_lock" lock 508 * 509 * returns 0 on success, <0 on failure. 510 */ 511 int mei_ioctl_connect_client(struct file *file, 512 struct mei_connect_client_data *data) 513 { 514 struct mei_device *dev; 515 struct mei_cl_cb *cb; 516 struct mei_client *client; 517 struct mei_cl *cl; 518 long timeout = mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT); 519 int i; 520 int err; 521 int rets; 522 523 cl = file->private_data; 524 if (WARN_ON(!cl || !cl->dev)) 525 return -ENODEV; 526 527 dev = cl->dev; 528 529 dev_dbg(&dev->pdev->dev, "mei_ioctl_connect_client() Entry\n"); 530 531 /* buffered ioctl cb */ 532 cb = mei_io_cb_init(cl, file); 533 if (!cb) { 534 rets = -ENOMEM; 535 goto end; 536 } 537 538 cb->fop_type = MEI_FOP_IOCTL; 539 540 if (dev->dev_state != MEI_DEV_ENABLED) { 541 rets = -ENODEV; 542 goto end; 543 } 544 if (cl->state != MEI_FILE_INITIALIZING && 545 cl->state != MEI_FILE_DISCONNECTED) { 546 rets = -EBUSY; 547 goto end; 548 } 549 550 /* find ME client we're trying to connect to */ 551 i = mei_me_cl_by_uuid(dev, &data->in_client_uuid); 552 if (i >= 0 && !dev->me_clients[i].props.fixed_address) { 553 cl->me_client_id = dev->me_clients[i].client_id; 554 cl->state = MEI_FILE_CONNECTING; 555 } 556 557 dev_dbg(&dev->pdev->dev, "Connect to FW Client ID = %d\n", 558 cl->me_client_id); 559 dev_dbg(&dev->pdev->dev, "FW Client - Protocol Version = %d\n", 560 dev->me_clients[i].props.protocol_version); 561 dev_dbg(&dev->pdev->dev, "FW Client - Max Msg Len = %d\n", 562 dev->me_clients[i].props.max_msg_length); 563 564 /* if we're connecting to amthi client then we will use the 565 * existing connection 566 */ 567 if (uuid_le_cmp(data->in_client_uuid, mei_amthi_guid) == 0) { 568 dev_dbg(&dev->pdev->dev, "FW Client is amthi\n"); 569 if (dev->iamthif_cl.state != MEI_FILE_CONNECTED) { 570 rets = -ENODEV; 571 goto end; 572 } 573 clear_bit(cl->host_client_id, dev->host_clients_map); 574 mei_me_cl_unlink(dev, cl); 575 576 kfree(cl); 577 cl = NULL; 578 file->private_data = &dev->iamthif_cl; 579 580 client = &data->out_client_properties; 581 client->max_msg_length = 582 dev->me_clients[i].props.max_msg_length; 583 client->protocol_version = 584 dev->me_clients[i].props.protocol_version; 585 rets = dev->iamthif_cl.status; 586 587 goto end; 588 } 589 590 if (cl->state != MEI_FILE_CONNECTING) { 591 rets = -ENODEV; 592 goto end; 593 } 594 595 596 /* prepare the output buffer */ 597 client = &data->out_client_properties; 598 client->max_msg_length = dev->me_clients[i].props.max_msg_length; 599 client->protocol_version = dev->me_clients[i].props.protocol_version; 600 dev_dbg(&dev->pdev->dev, "Can connect?\n"); 601 if (dev->mei_host_buffer_is_empty 602 && !mei_other_client_is_connecting(dev, cl)) { 603 dev_dbg(&dev->pdev->dev, "Sending Connect Message\n"); 604 dev->mei_host_buffer_is_empty = false; 605 if (mei_hbm_cl_connect_req(dev, cl)) { 606 dev_dbg(&dev->pdev->dev, "Sending connect message - failed\n"); 607 rets = -ENODEV; 608 goto end; 609 } else { 610 dev_dbg(&dev->pdev->dev, "Sending connect message - succeeded\n"); 611 cl->timer_count = MEI_CONNECT_TIMEOUT; 612 list_add_tail(&cb->list, &dev->ctrl_rd_list.list); 613 } 614 615 616 } else { 617 dev_dbg(&dev->pdev->dev, "Queuing the connect request due to device busy\n"); 618 dev_dbg(&dev->pdev->dev, "add connect cb to control write list.\n"); 619 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 620 } 621 mutex_unlock(&dev->device_lock); 622 err = wait_event_timeout(dev->wait_recvd_msg, 623 (MEI_FILE_CONNECTED == cl->state || 624 MEI_FILE_DISCONNECTED == cl->state), timeout); 625 626 mutex_lock(&dev->device_lock); 627 if (MEI_FILE_CONNECTED == cl->state) { 628 dev_dbg(&dev->pdev->dev, "successfully connected to FW client.\n"); 629 rets = cl->status; 630 goto end; 631 } else { 632 dev_dbg(&dev->pdev->dev, "failed to connect to FW client.cl->state = %d.\n", 633 cl->state); 634 if (!err) { 635 dev_dbg(&dev->pdev->dev, 636 "wait_event_interruptible_timeout failed on client" 637 " connect message fw response message.\n"); 638 } 639 rets = -EFAULT; 640 641 mei_io_list_flush(&dev->ctrl_rd_list, cl); 642 mei_io_list_flush(&dev->ctrl_wr_list, cl); 643 goto end; 644 } 645 rets = 0; 646 end: 647 dev_dbg(&dev->pdev->dev, "free connect cb memory."); 648 mei_io_cb_free(cb); 649 return rets; 650 } 651 652 /** 653 * mei_start_read - the start read client message function. 654 * 655 * @dev: the device structure 656 * @if_num: minor number 657 * @cl: private data of the file object 658 * 659 * returns 0 on success, <0 on failure. 660 */ 661 int mei_start_read(struct mei_device *dev, struct mei_cl *cl) 662 { 663 struct mei_cl_cb *cb; 664 int rets; 665 int i; 666 667 if (cl->state != MEI_FILE_CONNECTED) 668 return -ENODEV; 669 670 if (dev->dev_state != MEI_DEV_ENABLED) 671 return -ENODEV; 672 673 if (cl->read_pending || cl->read_cb) { 674 dev_dbg(&dev->pdev->dev, "read is pending.\n"); 675 return -EBUSY; 676 } 677 i = mei_me_cl_by_id(dev, cl->me_client_id); 678 if (i < 0) { 679 dev_err(&dev->pdev->dev, "no such me client %d\n", 680 cl->me_client_id); 681 return -ENODEV; 682 } 683 684 cb = mei_io_cb_init(cl, NULL); 685 if (!cb) 686 return -ENOMEM; 687 688 rets = mei_io_cb_alloc_resp_buf(cb, 689 dev->me_clients[i].props.max_msg_length); 690 if (rets) 691 goto err; 692 693 cb->fop_type = MEI_FOP_READ; 694 cl->read_cb = cb; 695 if (dev->mei_host_buffer_is_empty) { 696 dev->mei_host_buffer_is_empty = false; 697 if (mei_hbm_cl_flow_control_req(dev, cl)) { 698 rets = -ENODEV; 699 goto err; 700 } 701 list_add_tail(&cb->list, &dev->read_list.list); 702 } else { 703 list_add_tail(&cb->list, &dev->ctrl_wr_list.list); 704 } 705 return rets; 706 err: 707 mei_io_cb_free(cb); 708 return rets; 709 } 710 711