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