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/export.h> 18 #include <linux/sched.h> 19 #include <linux/wait.h> 20 #include <linux/pm_runtime.h> 21 #include <linux/slab.h> 22 23 #include <linux/mei.h> 24 25 #include "mei_dev.h" 26 #include "hbm.h" 27 #include "client.h" 28 29 static const char *mei_hbm_status_str(enum mei_hbm_status status) 30 { 31 #define MEI_HBM_STATUS(status) case MEI_HBMS_##status: return #status 32 switch (status) { 33 MEI_HBM_STATUS(SUCCESS); 34 MEI_HBM_STATUS(CLIENT_NOT_FOUND); 35 MEI_HBM_STATUS(ALREADY_EXISTS); 36 MEI_HBM_STATUS(REJECTED); 37 MEI_HBM_STATUS(INVALID_PARAMETER); 38 MEI_HBM_STATUS(NOT_ALLOWED); 39 MEI_HBM_STATUS(ALREADY_STARTED); 40 MEI_HBM_STATUS(NOT_STARTED); 41 default: return "unknown"; 42 } 43 #undef MEI_HBM_STATUS 44 }; 45 46 static const char *mei_cl_conn_status_str(enum mei_cl_connect_status status) 47 { 48 #define MEI_CL_CS(status) case MEI_CL_CONN_##status: return #status 49 switch (status) { 50 MEI_CL_CS(SUCCESS); 51 MEI_CL_CS(NOT_FOUND); 52 MEI_CL_CS(ALREADY_STARTED); 53 MEI_CL_CS(OUT_OF_RESOURCES); 54 MEI_CL_CS(MESSAGE_SMALL); 55 MEI_CL_CS(NOT_ALLOWED); 56 default: return "unknown"; 57 } 58 #undef MEI_CL_CCS 59 } 60 61 const char *mei_hbm_state_str(enum mei_hbm_state state) 62 { 63 #define MEI_HBM_STATE(state) case MEI_HBM_##state: return #state 64 switch (state) { 65 MEI_HBM_STATE(IDLE); 66 MEI_HBM_STATE(STARTING); 67 MEI_HBM_STATE(STARTED); 68 MEI_HBM_STATE(ENUM_CLIENTS); 69 MEI_HBM_STATE(CLIENT_PROPERTIES); 70 MEI_HBM_STATE(STOPPED); 71 default: 72 return "unknown"; 73 } 74 #undef MEI_HBM_STATE 75 } 76 77 /** 78 * mei_cl_conn_status_to_errno - convert client connect response 79 * status to error code 80 * 81 * @status: client connect response status 82 * 83 * Return: corresponding error code 84 */ 85 static int mei_cl_conn_status_to_errno(enum mei_cl_connect_status status) 86 { 87 switch (status) { 88 case MEI_CL_CONN_SUCCESS: return 0; 89 case MEI_CL_CONN_NOT_FOUND: return -ENOTTY; 90 case MEI_CL_CONN_ALREADY_STARTED: return -EBUSY; 91 case MEI_CL_CONN_OUT_OF_RESOURCES: return -EBUSY; 92 case MEI_CL_CONN_MESSAGE_SMALL: return -EINVAL; 93 case MEI_CL_CONN_NOT_ALLOWED: return -EBUSY; 94 default: return -EINVAL; 95 } 96 } 97 98 /** 99 * mei_hbm_idle - set hbm to idle state 100 * 101 * @dev: the device structure 102 */ 103 void mei_hbm_idle(struct mei_device *dev) 104 { 105 dev->init_clients_timer = 0; 106 dev->hbm_state = MEI_HBM_IDLE; 107 } 108 109 /** 110 * mei_hbm_reset - reset hbm counters and book keeping data structurs 111 * 112 * @dev: the device structure 113 */ 114 void mei_hbm_reset(struct mei_device *dev) 115 { 116 mei_me_cl_rm_all(dev); 117 118 mei_hbm_idle(dev); 119 } 120 121 /** 122 * mei_hbm_hdr - construct hbm header 123 * 124 * @hdr: hbm header 125 * @length: payload length 126 */ 127 128 static inline void mei_hbm_hdr(struct mei_msg_hdr *hdr, size_t length) 129 { 130 hdr->host_addr = 0; 131 hdr->me_addr = 0; 132 hdr->length = length; 133 hdr->msg_complete = 1; 134 hdr->reserved = 0; 135 hdr->internal = 0; 136 } 137 138 /** 139 * mei_hbm_cl_hdr - construct client hbm header 140 * 141 * @cl: client 142 * @hbm_cmd: host bus message command 143 * @buf: buffer for cl header 144 * @len: buffer length 145 */ 146 static inline 147 void mei_hbm_cl_hdr(struct mei_cl *cl, u8 hbm_cmd, void *buf, size_t len) 148 { 149 struct mei_hbm_cl_cmd *cmd = buf; 150 151 memset(cmd, 0, len); 152 153 cmd->hbm_cmd = hbm_cmd; 154 cmd->host_addr = mei_cl_host_addr(cl); 155 cmd->me_addr = mei_cl_me_id(cl); 156 } 157 158 /** 159 * mei_hbm_cl_write - write simple hbm client message 160 * 161 * @dev: the device structure 162 * @cl: client 163 * @hbm_cmd: host bus message command 164 * @buf: message buffer 165 * @len: buffer length 166 * 167 * Return: 0 on success, <0 on failure. 168 */ 169 static inline int mei_hbm_cl_write(struct mei_device *dev, struct mei_cl *cl, 170 u8 hbm_cmd, void *buf, size_t len) 171 { 172 struct mei_msg_hdr mei_hdr; 173 174 mei_hbm_hdr(&mei_hdr, len); 175 mei_hbm_cl_hdr(cl, hbm_cmd, buf, len); 176 177 return mei_write_message(dev, &mei_hdr, buf); 178 } 179 180 /** 181 * mei_hbm_cl_addr_equal - check if the client's and 182 * the message address match 183 * 184 * @cl: client 185 * @cmd: hbm client message 186 * 187 * Return: true if addresses are the same 188 */ 189 static inline 190 bool mei_hbm_cl_addr_equal(struct mei_cl *cl, struct mei_hbm_cl_cmd *cmd) 191 { 192 return mei_cl_host_addr(cl) == cmd->host_addr && 193 mei_cl_me_id(cl) == cmd->me_addr; 194 } 195 196 /** 197 * mei_hbm_cl_find_by_cmd - find recipient client 198 * 199 * @dev: the device structure 200 * @buf: a buffer with hbm cl command 201 * 202 * Return: the recipient client or NULL if not found 203 */ 204 static inline 205 struct mei_cl *mei_hbm_cl_find_by_cmd(struct mei_device *dev, void *buf) 206 { 207 struct mei_hbm_cl_cmd *cmd = (struct mei_hbm_cl_cmd *)buf; 208 struct mei_cl *cl; 209 210 list_for_each_entry(cl, &dev->file_list, link) 211 if (mei_hbm_cl_addr_equal(cl, cmd)) 212 return cl; 213 return NULL; 214 } 215 216 217 /** 218 * mei_hbm_start_wait - wait for start response message. 219 * 220 * @dev: the device structure 221 * 222 * Return: 0 on success and < 0 on failure 223 */ 224 int mei_hbm_start_wait(struct mei_device *dev) 225 { 226 int ret; 227 228 if (dev->hbm_state > MEI_HBM_STARTING) 229 return 0; 230 231 mutex_unlock(&dev->device_lock); 232 ret = wait_event_timeout(dev->wait_hbm_start, 233 dev->hbm_state != MEI_HBM_STARTING, 234 mei_secs_to_jiffies(MEI_HBM_TIMEOUT)); 235 mutex_lock(&dev->device_lock); 236 237 if (ret == 0 && (dev->hbm_state <= MEI_HBM_STARTING)) { 238 dev->hbm_state = MEI_HBM_IDLE; 239 dev_err(dev->dev, "waiting for mei start failed\n"); 240 return -ETIME; 241 } 242 return 0; 243 } 244 245 /** 246 * mei_hbm_start_req - sends start request message. 247 * 248 * @dev: the device structure 249 * 250 * Return: 0 on success and < 0 on failure 251 */ 252 int mei_hbm_start_req(struct mei_device *dev) 253 { 254 struct mei_msg_hdr mei_hdr; 255 struct hbm_host_version_request start_req; 256 const size_t len = sizeof(struct hbm_host_version_request); 257 int ret; 258 259 mei_hbm_reset(dev); 260 261 mei_hbm_hdr(&mei_hdr, len); 262 263 /* host start message */ 264 memset(&start_req, 0, len); 265 start_req.hbm_cmd = HOST_START_REQ_CMD; 266 start_req.host_version.major_version = HBM_MAJOR_VERSION; 267 start_req.host_version.minor_version = HBM_MINOR_VERSION; 268 269 dev->hbm_state = MEI_HBM_IDLE; 270 ret = mei_write_message(dev, &mei_hdr, &start_req); 271 if (ret) { 272 dev_err(dev->dev, "version message write failed: ret = %d\n", 273 ret); 274 return ret; 275 } 276 277 dev->hbm_state = MEI_HBM_STARTING; 278 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 279 mei_schedule_stall_timer(dev); 280 return 0; 281 } 282 283 /** 284 * mei_hbm_enum_clients_req - sends enumeration client request message. 285 * 286 * @dev: the device structure 287 * 288 * Return: 0 on success and < 0 on failure 289 */ 290 static int mei_hbm_enum_clients_req(struct mei_device *dev) 291 { 292 struct mei_msg_hdr mei_hdr; 293 struct hbm_host_enum_request enum_req; 294 const size_t len = sizeof(struct hbm_host_enum_request); 295 int ret; 296 297 /* enumerate clients */ 298 mei_hbm_hdr(&mei_hdr, len); 299 300 memset(&enum_req, 0, len); 301 enum_req.hbm_cmd = HOST_ENUM_REQ_CMD; 302 enum_req.flags |= dev->hbm_f_dc_supported ? 303 MEI_HBM_ENUM_F_ALLOW_ADD : 0; 304 enum_req.flags |= dev->hbm_f_ie_supported ? 305 MEI_HBM_ENUM_F_IMMEDIATE_ENUM : 0; 306 307 ret = mei_write_message(dev, &mei_hdr, &enum_req); 308 if (ret) { 309 dev_err(dev->dev, "enumeration request write failed: ret = %d.\n", 310 ret); 311 return ret; 312 } 313 dev->hbm_state = MEI_HBM_ENUM_CLIENTS; 314 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 315 mei_schedule_stall_timer(dev); 316 return 0; 317 } 318 319 /** 320 * mei_hbm_me_cl_add - add new me client to the list 321 * 322 * @dev: the device structure 323 * @res: hbm property response 324 * 325 * Return: 0 on success and -ENOMEM on allocation failure 326 */ 327 328 static int mei_hbm_me_cl_add(struct mei_device *dev, 329 struct hbm_props_response *res) 330 { 331 struct mei_me_client *me_cl; 332 const uuid_le *uuid = &res->client_properties.protocol_name; 333 334 mei_me_cl_rm_by_uuid(dev, uuid); 335 336 me_cl = kzalloc(sizeof(struct mei_me_client), GFP_KERNEL); 337 if (!me_cl) 338 return -ENOMEM; 339 340 mei_me_cl_init(me_cl); 341 342 me_cl->props = res->client_properties; 343 me_cl->client_id = res->me_addr; 344 me_cl->tx_flow_ctrl_creds = 0; 345 346 mei_me_cl_add(dev, me_cl); 347 348 return 0; 349 } 350 351 /** 352 * mei_hbm_add_cl_resp - send response to fw on client add request 353 * 354 * @dev: the device structure 355 * @addr: me address 356 * @status: response status 357 * 358 * Return: 0 on success and < 0 on failure 359 */ 360 static int mei_hbm_add_cl_resp(struct mei_device *dev, u8 addr, u8 status) 361 { 362 struct mei_msg_hdr mei_hdr; 363 struct hbm_add_client_response resp; 364 const size_t len = sizeof(struct hbm_add_client_response); 365 int ret; 366 367 dev_dbg(dev->dev, "adding client response\n"); 368 369 mei_hbm_hdr(&mei_hdr, len); 370 371 memset(&resp, 0, sizeof(struct hbm_add_client_response)); 372 resp.hbm_cmd = MEI_HBM_ADD_CLIENT_RES_CMD; 373 resp.me_addr = addr; 374 resp.status = status; 375 376 ret = mei_write_message(dev, &mei_hdr, &resp); 377 if (ret) 378 dev_err(dev->dev, "add client response write failed: ret = %d\n", 379 ret); 380 return ret; 381 } 382 383 /** 384 * mei_hbm_fw_add_cl_req - request from the fw to add a client 385 * 386 * @dev: the device structure 387 * @req: add client request 388 * 389 * Return: 0 on success and < 0 on failure 390 */ 391 static int mei_hbm_fw_add_cl_req(struct mei_device *dev, 392 struct hbm_add_client_request *req) 393 { 394 int ret; 395 u8 status = MEI_HBMS_SUCCESS; 396 397 BUILD_BUG_ON(sizeof(struct hbm_add_client_request) != 398 sizeof(struct hbm_props_response)); 399 400 ret = mei_hbm_me_cl_add(dev, (struct hbm_props_response *)req); 401 if (ret) 402 status = !MEI_HBMS_SUCCESS; 403 404 if (dev->dev_state == MEI_DEV_ENABLED) 405 schedule_work(&dev->bus_rescan_work); 406 407 return mei_hbm_add_cl_resp(dev, req->me_addr, status); 408 } 409 410 /** 411 * mei_hbm_cl_notify_req - send notification request 412 * 413 * @dev: the device structure 414 * @cl: a client to disconnect from 415 * @start: true for start false for stop 416 * 417 * Return: 0 on success and -EIO on write failure 418 */ 419 int mei_hbm_cl_notify_req(struct mei_device *dev, 420 struct mei_cl *cl, u8 start) 421 { 422 423 struct mei_msg_hdr mei_hdr; 424 struct hbm_notification_request req; 425 const size_t len = sizeof(struct hbm_notification_request); 426 int ret; 427 428 mei_hbm_hdr(&mei_hdr, len); 429 mei_hbm_cl_hdr(cl, MEI_HBM_NOTIFY_REQ_CMD, &req, len); 430 431 req.start = start; 432 433 ret = mei_write_message(dev, &mei_hdr, &req); 434 if (ret) 435 dev_err(dev->dev, "notify request failed: ret = %d\n", ret); 436 437 return ret; 438 } 439 440 /** 441 * notify_res_to_fop - convert notification response to the proper 442 * notification FOP 443 * 444 * @cmd: client notification start response command 445 * 446 * Return: MEI_FOP_NOTIFY_START or MEI_FOP_NOTIFY_STOP; 447 */ 448 static inline enum mei_cb_file_ops notify_res_to_fop(struct mei_hbm_cl_cmd *cmd) 449 { 450 struct hbm_notification_response *rs = 451 (struct hbm_notification_response *)cmd; 452 453 return mei_cl_notify_req2fop(rs->start); 454 } 455 456 /** 457 * mei_hbm_cl_notify_start_res - update the client state according 458 * notify start response 459 * 460 * @dev: the device structure 461 * @cl: mei host client 462 * @cmd: client notification start response command 463 */ 464 static void mei_hbm_cl_notify_start_res(struct mei_device *dev, 465 struct mei_cl *cl, 466 struct mei_hbm_cl_cmd *cmd) 467 { 468 struct hbm_notification_response *rs = 469 (struct hbm_notification_response *)cmd; 470 471 cl_dbg(dev, cl, "hbm: notify start response status=%d\n", rs->status); 472 473 if (rs->status == MEI_HBMS_SUCCESS || 474 rs->status == MEI_HBMS_ALREADY_STARTED) { 475 cl->notify_en = true; 476 cl->status = 0; 477 } else { 478 cl->status = -EINVAL; 479 } 480 } 481 482 /** 483 * mei_hbm_cl_notify_stop_res - update the client state according 484 * notify stop response 485 * 486 * @dev: the device structure 487 * @cl: mei host client 488 * @cmd: client notification stop response command 489 */ 490 static void mei_hbm_cl_notify_stop_res(struct mei_device *dev, 491 struct mei_cl *cl, 492 struct mei_hbm_cl_cmd *cmd) 493 { 494 struct hbm_notification_response *rs = 495 (struct hbm_notification_response *)cmd; 496 497 cl_dbg(dev, cl, "hbm: notify stop response status=%d\n", rs->status); 498 499 if (rs->status == MEI_HBMS_SUCCESS || 500 rs->status == MEI_HBMS_NOT_STARTED) { 501 cl->notify_en = false; 502 cl->status = 0; 503 } else { 504 /* TODO: spec is not clear yet about other possible issues */ 505 cl->status = -EINVAL; 506 } 507 } 508 509 /** 510 * mei_hbm_cl_notify - signal notification event 511 * 512 * @dev: the device structure 513 * @cmd: notification client message 514 */ 515 static void mei_hbm_cl_notify(struct mei_device *dev, 516 struct mei_hbm_cl_cmd *cmd) 517 { 518 struct mei_cl *cl; 519 520 cl = mei_hbm_cl_find_by_cmd(dev, cmd); 521 if (cl) 522 mei_cl_notify(cl); 523 } 524 525 /** 526 * mei_hbm_prop_req - request property for a single client 527 * 528 * @dev: the device structure 529 * @start_idx: client index to start search 530 * 531 * Return: 0 on success and < 0 on failure 532 */ 533 static int mei_hbm_prop_req(struct mei_device *dev, unsigned long start_idx) 534 { 535 struct mei_msg_hdr mei_hdr; 536 struct hbm_props_request prop_req; 537 const size_t len = sizeof(struct hbm_props_request); 538 unsigned long addr; 539 int ret; 540 541 addr = find_next_bit(dev->me_clients_map, MEI_CLIENTS_MAX, start_idx); 542 543 /* We got all client properties */ 544 if (addr == MEI_CLIENTS_MAX) { 545 dev->hbm_state = MEI_HBM_STARTED; 546 mei_host_client_init(dev); 547 548 return 0; 549 } 550 551 mei_hbm_hdr(&mei_hdr, len); 552 553 memset(&prop_req, 0, sizeof(struct hbm_props_request)); 554 555 prop_req.hbm_cmd = HOST_CLIENT_PROPERTIES_REQ_CMD; 556 prop_req.me_addr = addr; 557 558 ret = mei_write_message(dev, &mei_hdr, &prop_req); 559 if (ret) { 560 dev_err(dev->dev, "properties request write failed: ret = %d\n", 561 ret); 562 return ret; 563 } 564 565 dev->init_clients_timer = MEI_CLIENTS_INIT_TIMEOUT; 566 mei_schedule_stall_timer(dev); 567 568 return 0; 569 } 570 571 /** 572 * mei_hbm_pg - sends pg command 573 * 574 * @dev: the device structure 575 * @pg_cmd: the pg command code 576 * 577 * Return: -EIO on write failure 578 * -EOPNOTSUPP if the operation is not supported by the protocol 579 */ 580 int mei_hbm_pg(struct mei_device *dev, u8 pg_cmd) 581 { 582 struct mei_msg_hdr mei_hdr; 583 struct hbm_power_gate req; 584 const size_t len = sizeof(struct hbm_power_gate); 585 int ret; 586 587 if (!dev->hbm_f_pg_supported) 588 return -EOPNOTSUPP; 589 590 mei_hbm_hdr(&mei_hdr, len); 591 592 memset(&req, 0, len); 593 req.hbm_cmd = pg_cmd; 594 595 ret = mei_write_message(dev, &mei_hdr, &req); 596 if (ret) 597 dev_err(dev->dev, "power gate command write failed.\n"); 598 return ret; 599 } 600 EXPORT_SYMBOL_GPL(mei_hbm_pg); 601 602 /** 603 * mei_hbm_stop_req - send stop request message 604 * 605 * @dev: mei device 606 * 607 * Return: -EIO on write failure 608 */ 609 static int mei_hbm_stop_req(struct mei_device *dev) 610 { 611 struct mei_msg_hdr mei_hdr; 612 struct hbm_host_stop_request req; 613 const size_t len = sizeof(struct hbm_host_stop_request); 614 615 mei_hbm_hdr(&mei_hdr, len); 616 617 memset(&req, 0, len); 618 req.hbm_cmd = HOST_STOP_REQ_CMD; 619 req.reason = DRIVER_STOP_REQUEST; 620 621 return mei_write_message(dev, &mei_hdr, &req); 622 } 623 624 /** 625 * mei_hbm_cl_flow_control_req - sends flow control request. 626 * 627 * @dev: the device structure 628 * @cl: client info 629 * 630 * Return: -EIO on write failure 631 */ 632 int mei_hbm_cl_flow_control_req(struct mei_device *dev, struct mei_cl *cl) 633 { 634 struct hbm_flow_control req; 635 636 cl_dbg(dev, cl, "sending flow control\n"); 637 return mei_hbm_cl_write(dev, cl, MEI_FLOW_CONTROL_CMD, 638 &req, sizeof(req)); 639 } 640 641 /** 642 * mei_hbm_add_single_tx_flow_ctrl_creds - adds single buffer credentials. 643 * 644 * @dev: the device structure 645 * @fctrl: flow control response bus message 646 * 647 * Return: 0 on success, < 0 otherwise 648 */ 649 static int mei_hbm_add_single_tx_flow_ctrl_creds(struct mei_device *dev, 650 struct hbm_flow_control *fctrl) 651 { 652 struct mei_me_client *me_cl; 653 int rets; 654 655 me_cl = mei_me_cl_by_id(dev, fctrl->me_addr); 656 if (!me_cl) { 657 dev_err(dev->dev, "no such me client %d\n", fctrl->me_addr); 658 return -ENOENT; 659 } 660 661 if (WARN_ON(me_cl->props.single_recv_buf == 0)) { 662 rets = -EINVAL; 663 goto out; 664 } 665 666 me_cl->tx_flow_ctrl_creds++; 667 dev_dbg(dev->dev, "recv flow ctrl msg ME %d (single) creds = %d.\n", 668 fctrl->me_addr, me_cl->tx_flow_ctrl_creds); 669 670 rets = 0; 671 out: 672 mei_me_cl_put(me_cl); 673 return rets; 674 } 675 676 /** 677 * mei_hbm_cl_flow_control_res - flow control response from me 678 * 679 * @dev: the device structure 680 * @fctrl: flow control response bus message 681 */ 682 static void mei_hbm_cl_tx_flow_ctrl_creds_res(struct mei_device *dev, 683 struct hbm_flow_control *fctrl) 684 { 685 struct mei_cl *cl; 686 687 if (!fctrl->host_addr) { 688 /* single receive buffer */ 689 mei_hbm_add_single_tx_flow_ctrl_creds(dev, fctrl); 690 return; 691 } 692 693 cl = mei_hbm_cl_find_by_cmd(dev, fctrl); 694 if (cl) { 695 cl->tx_flow_ctrl_creds++; 696 cl_dbg(dev, cl, "flow control creds = %d.\n", 697 cl->tx_flow_ctrl_creds); 698 } 699 } 700 701 702 /** 703 * mei_hbm_cl_disconnect_req - sends disconnect message to fw. 704 * 705 * @dev: the device structure 706 * @cl: a client to disconnect from 707 * 708 * Return: -EIO on write failure 709 */ 710 int mei_hbm_cl_disconnect_req(struct mei_device *dev, struct mei_cl *cl) 711 { 712 struct hbm_client_connect_request req; 713 714 return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_REQ_CMD, 715 &req, sizeof(req)); 716 } 717 718 /** 719 * mei_hbm_cl_disconnect_rsp - sends disconnect respose to the FW 720 * 721 * @dev: the device structure 722 * @cl: a client to disconnect from 723 * 724 * Return: -EIO on write failure 725 */ 726 int mei_hbm_cl_disconnect_rsp(struct mei_device *dev, struct mei_cl *cl) 727 { 728 struct hbm_client_connect_response resp; 729 730 return mei_hbm_cl_write(dev, cl, CLIENT_DISCONNECT_RES_CMD, 731 &resp, sizeof(resp)); 732 } 733 734 /** 735 * mei_hbm_cl_disconnect_res - update the client state according 736 * disconnect response 737 * 738 * @dev: the device structure 739 * @cl: mei host client 740 * @cmd: disconnect client response host bus message 741 */ 742 static void mei_hbm_cl_disconnect_res(struct mei_device *dev, struct mei_cl *cl, 743 struct mei_hbm_cl_cmd *cmd) 744 { 745 struct hbm_client_connect_response *rs = 746 (struct hbm_client_connect_response *)cmd; 747 748 cl_dbg(dev, cl, "hbm: disconnect response status=%d\n", rs->status); 749 750 if (rs->status == MEI_CL_DISCONN_SUCCESS) 751 cl->state = MEI_FILE_DISCONNECT_REPLY; 752 cl->status = 0; 753 } 754 755 /** 756 * mei_hbm_cl_connect_req - send connection request to specific me client 757 * 758 * @dev: the device structure 759 * @cl: a client to connect to 760 * 761 * Return: -EIO on write failure 762 */ 763 int mei_hbm_cl_connect_req(struct mei_device *dev, struct mei_cl *cl) 764 { 765 struct hbm_client_connect_request req; 766 767 return mei_hbm_cl_write(dev, cl, CLIENT_CONNECT_REQ_CMD, 768 &req, sizeof(req)); 769 } 770 771 /** 772 * mei_hbm_cl_connect_res - update the client state according 773 * connection response 774 * 775 * @dev: the device structure 776 * @cl: mei host client 777 * @cmd: connect client response host bus message 778 */ 779 static void mei_hbm_cl_connect_res(struct mei_device *dev, struct mei_cl *cl, 780 struct mei_hbm_cl_cmd *cmd) 781 { 782 struct hbm_client_connect_response *rs = 783 (struct hbm_client_connect_response *)cmd; 784 785 cl_dbg(dev, cl, "hbm: connect response status=%s\n", 786 mei_cl_conn_status_str(rs->status)); 787 788 if (rs->status == MEI_CL_CONN_SUCCESS) 789 cl->state = MEI_FILE_CONNECTED; 790 else { 791 cl->state = MEI_FILE_DISCONNECT_REPLY; 792 if (rs->status == MEI_CL_CONN_NOT_FOUND) { 793 mei_me_cl_del(dev, cl->me_cl); 794 if (dev->dev_state == MEI_DEV_ENABLED) 795 schedule_work(&dev->bus_rescan_work); 796 } 797 } 798 cl->status = mei_cl_conn_status_to_errno(rs->status); 799 } 800 801 /** 802 * mei_hbm_cl_res - process hbm response received on behalf 803 * an client 804 * 805 * @dev: the device structure 806 * @rs: hbm client message 807 * @fop_type: file operation type 808 */ 809 static void mei_hbm_cl_res(struct mei_device *dev, 810 struct mei_hbm_cl_cmd *rs, 811 enum mei_cb_file_ops fop_type) 812 { 813 struct mei_cl *cl; 814 struct mei_cl_cb *cb, *next; 815 816 cl = NULL; 817 list_for_each_entry_safe(cb, next, &dev->ctrl_rd_list, list) { 818 819 cl = cb->cl; 820 821 if (cb->fop_type != fop_type) 822 continue; 823 824 if (mei_hbm_cl_addr_equal(cl, rs)) { 825 list_del_init(&cb->list); 826 break; 827 } 828 } 829 830 if (!cl) 831 return; 832 833 switch (fop_type) { 834 case MEI_FOP_CONNECT: 835 mei_hbm_cl_connect_res(dev, cl, rs); 836 break; 837 case MEI_FOP_DISCONNECT: 838 mei_hbm_cl_disconnect_res(dev, cl, rs); 839 break; 840 case MEI_FOP_NOTIFY_START: 841 mei_hbm_cl_notify_start_res(dev, cl, rs); 842 break; 843 case MEI_FOP_NOTIFY_STOP: 844 mei_hbm_cl_notify_stop_res(dev, cl, rs); 845 break; 846 default: 847 return; 848 } 849 850 cl->timer_count = 0; 851 wake_up(&cl->wait); 852 } 853 854 855 /** 856 * mei_hbm_fw_disconnect_req - disconnect request initiated by ME firmware 857 * host sends disconnect response 858 * 859 * @dev: the device structure. 860 * @disconnect_req: disconnect request bus message from the me 861 * 862 * Return: -ENOMEM on allocation failure 863 */ 864 static int mei_hbm_fw_disconnect_req(struct mei_device *dev, 865 struct hbm_client_connect_request *disconnect_req) 866 { 867 struct mei_cl *cl; 868 struct mei_cl_cb *cb; 869 870 cl = mei_hbm_cl_find_by_cmd(dev, disconnect_req); 871 if (cl) { 872 cl_warn(dev, cl, "fw disconnect request received\n"); 873 cl->state = MEI_FILE_DISCONNECTING; 874 cl->timer_count = 0; 875 876 cb = mei_cl_enqueue_ctrl_wr_cb(cl, 0, MEI_FOP_DISCONNECT_RSP, 877 NULL); 878 if (!cb) 879 return -ENOMEM; 880 } 881 return 0; 882 } 883 884 /** 885 * mei_hbm_pg_enter_res - PG enter response received 886 * 887 * @dev: the device structure. 888 * 889 * Return: 0 on success, -EPROTO on state mismatch 890 */ 891 static int mei_hbm_pg_enter_res(struct mei_device *dev) 892 { 893 if (mei_pg_state(dev) != MEI_PG_OFF || 894 dev->pg_event != MEI_PG_EVENT_WAIT) { 895 dev_err(dev->dev, "hbm: pg entry response: state mismatch [%s, %d]\n", 896 mei_pg_state_str(mei_pg_state(dev)), dev->pg_event); 897 return -EPROTO; 898 } 899 900 dev->pg_event = MEI_PG_EVENT_RECEIVED; 901 wake_up(&dev->wait_pg); 902 903 return 0; 904 } 905 906 /** 907 * mei_hbm_pg_resume - process with PG resume 908 * 909 * @dev: the device structure. 910 */ 911 void mei_hbm_pg_resume(struct mei_device *dev) 912 { 913 pm_request_resume(dev->dev); 914 } 915 EXPORT_SYMBOL_GPL(mei_hbm_pg_resume); 916 917 /** 918 * mei_hbm_pg_exit_res - PG exit response received 919 * 920 * @dev: the device structure. 921 * 922 * Return: 0 on success, -EPROTO on state mismatch 923 */ 924 static int mei_hbm_pg_exit_res(struct mei_device *dev) 925 { 926 if (mei_pg_state(dev) != MEI_PG_ON || 927 (dev->pg_event != MEI_PG_EVENT_WAIT && 928 dev->pg_event != MEI_PG_EVENT_IDLE)) { 929 dev_err(dev->dev, "hbm: pg exit response: state mismatch [%s, %d]\n", 930 mei_pg_state_str(mei_pg_state(dev)), dev->pg_event); 931 return -EPROTO; 932 } 933 934 switch (dev->pg_event) { 935 case MEI_PG_EVENT_WAIT: 936 dev->pg_event = MEI_PG_EVENT_RECEIVED; 937 wake_up(&dev->wait_pg); 938 break; 939 case MEI_PG_EVENT_IDLE: 940 /* 941 * If the driver is not waiting on this then 942 * this is HW initiated exit from PG. 943 * Start runtime pm resume sequence to exit from PG. 944 */ 945 dev->pg_event = MEI_PG_EVENT_RECEIVED; 946 mei_hbm_pg_resume(dev); 947 break; 948 default: 949 WARN(1, "hbm: pg exit response: unexpected pg event = %d\n", 950 dev->pg_event); 951 return -EPROTO; 952 } 953 954 return 0; 955 } 956 957 /** 958 * mei_hbm_config_features - check what hbm features and commands 959 * are supported by the fw 960 * 961 * @dev: the device structure 962 */ 963 static void mei_hbm_config_features(struct mei_device *dev) 964 { 965 /* Power Gating Isolation Support */ 966 dev->hbm_f_pg_supported = 0; 967 if (dev->version.major_version > HBM_MAJOR_VERSION_PGI) 968 dev->hbm_f_pg_supported = 1; 969 970 if (dev->version.major_version == HBM_MAJOR_VERSION_PGI && 971 dev->version.minor_version >= HBM_MINOR_VERSION_PGI) 972 dev->hbm_f_pg_supported = 1; 973 974 if (dev->version.major_version >= HBM_MAJOR_VERSION_DC) 975 dev->hbm_f_dc_supported = 1; 976 977 if (dev->version.major_version >= HBM_MAJOR_VERSION_IE) 978 dev->hbm_f_ie_supported = 1; 979 980 /* disconnect on connect timeout instead of link reset */ 981 if (dev->version.major_version >= HBM_MAJOR_VERSION_DOT) 982 dev->hbm_f_dot_supported = 1; 983 984 /* Notification Event Support */ 985 if (dev->version.major_version >= HBM_MAJOR_VERSION_EV) 986 dev->hbm_f_ev_supported = 1; 987 988 /* Fixed Address Client Support */ 989 if (dev->version.major_version >= HBM_MAJOR_VERSION_FA) 990 dev->hbm_f_fa_supported = 1; 991 992 /* OS ver message Support */ 993 if (dev->version.major_version >= HBM_MAJOR_VERSION_OS) 994 dev->hbm_f_os_supported = 1; 995 } 996 997 /** 998 * mei_hbm_version_is_supported - checks whether the driver can 999 * support the hbm version of the device 1000 * 1001 * @dev: the device structure 1002 * Return: true if driver can support hbm version of the device 1003 */ 1004 bool mei_hbm_version_is_supported(struct mei_device *dev) 1005 { 1006 return (dev->version.major_version < HBM_MAJOR_VERSION) || 1007 (dev->version.major_version == HBM_MAJOR_VERSION && 1008 dev->version.minor_version <= HBM_MINOR_VERSION); 1009 } 1010 1011 /** 1012 * mei_hbm_dispatch - bottom half read routine after ISR to 1013 * handle the read bus message cmd processing. 1014 * 1015 * @dev: the device structure 1016 * @hdr: header of bus message 1017 * 1018 * Return: 0 on success and < 0 on failure 1019 */ 1020 int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr) 1021 { 1022 struct mei_bus_message *mei_msg; 1023 struct hbm_host_version_response *version_res; 1024 struct hbm_props_response *props_res; 1025 struct hbm_host_enum_response *enum_res; 1026 struct hbm_add_client_request *add_cl_req; 1027 int ret; 1028 1029 struct mei_hbm_cl_cmd *cl_cmd; 1030 struct hbm_client_connect_request *disconnect_req; 1031 struct hbm_flow_control *fctrl; 1032 1033 /* read the message to our buffer */ 1034 BUG_ON(hdr->length >= sizeof(dev->rd_msg_buf)); 1035 mei_read_slots(dev, dev->rd_msg_buf, hdr->length); 1036 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf; 1037 cl_cmd = (struct mei_hbm_cl_cmd *)mei_msg; 1038 1039 /* ignore spurious message and prevent reset nesting 1040 * hbm is put to idle during system reset 1041 */ 1042 if (dev->hbm_state == MEI_HBM_IDLE) { 1043 dev_dbg(dev->dev, "hbm: state is idle ignore spurious messages\n"); 1044 return 0; 1045 } 1046 1047 switch (mei_msg->hbm_cmd) { 1048 case HOST_START_RES_CMD: 1049 dev_dbg(dev->dev, "hbm: start: response message received.\n"); 1050 1051 dev->init_clients_timer = 0; 1052 1053 version_res = (struct hbm_host_version_response *)mei_msg; 1054 1055 dev_dbg(dev->dev, "HBM VERSION: DRIVER=%02d:%02d DEVICE=%02d:%02d\n", 1056 HBM_MAJOR_VERSION, HBM_MINOR_VERSION, 1057 version_res->me_max_version.major_version, 1058 version_res->me_max_version.minor_version); 1059 1060 if (version_res->host_version_supported) { 1061 dev->version.major_version = HBM_MAJOR_VERSION; 1062 dev->version.minor_version = HBM_MINOR_VERSION; 1063 } else { 1064 dev->version.major_version = 1065 version_res->me_max_version.major_version; 1066 dev->version.minor_version = 1067 version_res->me_max_version.minor_version; 1068 } 1069 1070 if (!mei_hbm_version_is_supported(dev)) { 1071 dev_warn(dev->dev, "hbm: start: version mismatch - stopping the driver.\n"); 1072 1073 dev->hbm_state = MEI_HBM_STOPPED; 1074 if (mei_hbm_stop_req(dev)) { 1075 dev_err(dev->dev, "hbm: start: failed to send stop request\n"); 1076 return -EIO; 1077 } 1078 break; 1079 } 1080 1081 mei_hbm_config_features(dev); 1082 1083 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 1084 dev->hbm_state != MEI_HBM_STARTING) { 1085 dev_err(dev->dev, "hbm: start: state mismatch, [%d, %d]\n", 1086 dev->dev_state, dev->hbm_state); 1087 return -EPROTO; 1088 } 1089 1090 if (mei_hbm_enum_clients_req(dev)) { 1091 dev_err(dev->dev, "hbm: start: failed to send enumeration request\n"); 1092 return -EIO; 1093 } 1094 1095 wake_up(&dev->wait_hbm_start); 1096 break; 1097 1098 case CLIENT_CONNECT_RES_CMD: 1099 dev_dbg(dev->dev, "hbm: client connect response: message received.\n"); 1100 mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_CONNECT); 1101 break; 1102 1103 case CLIENT_DISCONNECT_RES_CMD: 1104 dev_dbg(dev->dev, "hbm: client disconnect response: message received.\n"); 1105 mei_hbm_cl_res(dev, cl_cmd, MEI_FOP_DISCONNECT); 1106 break; 1107 1108 case MEI_FLOW_CONTROL_CMD: 1109 dev_dbg(dev->dev, "hbm: client flow control response: message received.\n"); 1110 1111 fctrl = (struct hbm_flow_control *)mei_msg; 1112 mei_hbm_cl_tx_flow_ctrl_creds_res(dev, fctrl); 1113 break; 1114 1115 case MEI_PG_ISOLATION_ENTRY_RES_CMD: 1116 dev_dbg(dev->dev, "hbm: power gate isolation entry response received\n"); 1117 ret = mei_hbm_pg_enter_res(dev); 1118 if (ret) 1119 return ret; 1120 break; 1121 1122 case MEI_PG_ISOLATION_EXIT_REQ_CMD: 1123 dev_dbg(dev->dev, "hbm: power gate isolation exit request received\n"); 1124 ret = mei_hbm_pg_exit_res(dev); 1125 if (ret) 1126 return ret; 1127 break; 1128 1129 case HOST_CLIENT_PROPERTIES_RES_CMD: 1130 dev_dbg(dev->dev, "hbm: properties response: message received.\n"); 1131 1132 dev->init_clients_timer = 0; 1133 1134 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 1135 dev->hbm_state != MEI_HBM_CLIENT_PROPERTIES) { 1136 dev_err(dev->dev, "hbm: properties response: state mismatch, [%d, %d]\n", 1137 dev->dev_state, dev->hbm_state); 1138 return -EPROTO; 1139 } 1140 1141 props_res = (struct hbm_props_response *)mei_msg; 1142 1143 if (props_res->status) { 1144 dev_err(dev->dev, "hbm: properties response: wrong status = %d %s\n", 1145 props_res->status, 1146 mei_hbm_status_str(props_res->status)); 1147 return -EPROTO; 1148 } 1149 1150 mei_hbm_me_cl_add(dev, props_res); 1151 1152 /* request property for the next client */ 1153 if (mei_hbm_prop_req(dev, props_res->me_addr + 1)) 1154 return -EIO; 1155 1156 break; 1157 1158 case HOST_ENUM_RES_CMD: 1159 dev_dbg(dev->dev, "hbm: enumeration response: message received\n"); 1160 1161 dev->init_clients_timer = 0; 1162 1163 enum_res = (struct hbm_host_enum_response *) mei_msg; 1164 BUILD_BUG_ON(sizeof(dev->me_clients_map) 1165 < sizeof(enum_res->valid_addresses)); 1166 memcpy(dev->me_clients_map, enum_res->valid_addresses, 1167 sizeof(enum_res->valid_addresses)); 1168 1169 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 1170 dev->hbm_state != MEI_HBM_ENUM_CLIENTS) { 1171 dev_err(dev->dev, "hbm: enumeration response: state mismatch, [%d, %d]\n", 1172 dev->dev_state, dev->hbm_state); 1173 return -EPROTO; 1174 } 1175 1176 dev->hbm_state = MEI_HBM_CLIENT_PROPERTIES; 1177 1178 /* first property request */ 1179 if (mei_hbm_prop_req(dev, 0)) 1180 return -EIO; 1181 1182 break; 1183 1184 case HOST_STOP_RES_CMD: 1185 dev_dbg(dev->dev, "hbm: stop response: message received\n"); 1186 1187 dev->init_clients_timer = 0; 1188 1189 if (dev->hbm_state != MEI_HBM_STOPPED) { 1190 dev_err(dev->dev, "hbm: stop response: state mismatch, [%d, %d]\n", 1191 dev->dev_state, dev->hbm_state); 1192 return -EPROTO; 1193 } 1194 1195 dev->dev_state = MEI_DEV_POWER_DOWN; 1196 dev_info(dev->dev, "hbm: stop response: resetting.\n"); 1197 /* force the reset */ 1198 return -EPROTO; 1199 break; 1200 1201 case CLIENT_DISCONNECT_REQ_CMD: 1202 dev_dbg(dev->dev, "hbm: disconnect request: message received\n"); 1203 1204 disconnect_req = (struct hbm_client_connect_request *)mei_msg; 1205 mei_hbm_fw_disconnect_req(dev, disconnect_req); 1206 break; 1207 1208 case ME_STOP_REQ_CMD: 1209 dev_dbg(dev->dev, "hbm: stop request: message received\n"); 1210 dev->hbm_state = MEI_HBM_STOPPED; 1211 if (mei_hbm_stop_req(dev)) { 1212 dev_err(dev->dev, "hbm: stop request: failed to send stop request\n"); 1213 return -EIO; 1214 } 1215 break; 1216 1217 case MEI_HBM_ADD_CLIENT_REQ_CMD: 1218 dev_dbg(dev->dev, "hbm: add client request received\n"); 1219 /* 1220 * after the host receives the enum_resp 1221 * message clients may be added or removed 1222 */ 1223 if (dev->hbm_state <= MEI_HBM_ENUM_CLIENTS || 1224 dev->hbm_state >= MEI_HBM_STOPPED) { 1225 dev_err(dev->dev, "hbm: add client: state mismatch, [%d, %d]\n", 1226 dev->dev_state, dev->hbm_state); 1227 return -EPROTO; 1228 } 1229 add_cl_req = (struct hbm_add_client_request *)mei_msg; 1230 ret = mei_hbm_fw_add_cl_req(dev, add_cl_req); 1231 if (ret) { 1232 dev_err(dev->dev, "hbm: add client: failed to send response %d\n", 1233 ret); 1234 return -EIO; 1235 } 1236 dev_dbg(dev->dev, "hbm: add client request processed\n"); 1237 break; 1238 1239 case MEI_HBM_NOTIFY_RES_CMD: 1240 dev_dbg(dev->dev, "hbm: notify response received\n"); 1241 mei_hbm_cl_res(dev, cl_cmd, notify_res_to_fop(cl_cmd)); 1242 break; 1243 1244 case MEI_HBM_NOTIFICATION_CMD: 1245 dev_dbg(dev->dev, "hbm: notification\n"); 1246 mei_hbm_cl_notify(dev, cl_cmd); 1247 break; 1248 1249 default: 1250 BUG(); 1251 break; 1252 1253 } 1254 return 0; 1255 } 1256 1257