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 18#include <linux/pci.h> 19#include <linux/kthread.h> 20#include <linux/interrupt.h> 21#include <linux/fs.h> 22#include <linux/jiffies.h> 23 24#include "mei_dev.h" 25#include "mei.h" 26#include "hw.h" 27#include "interface.h" 28 29 30/** 31 * mei_interrupt_quick_handler - The ISR of the MEI device 32 * 33 * @irq: The irq number 34 * @dev_id: pointer to the device structure 35 * 36 * returns irqreturn_t 37 */ 38irqreturn_t mei_interrupt_quick_handler(int irq, void *dev_id) 39{ 40 struct mei_device *dev = (struct mei_device *) dev_id; 41 u32 csr_reg = mei_hcsr_read(dev); 42 43 if ((csr_reg & H_IS) != H_IS) 44 return IRQ_NONE; 45 46 /* clear H_IS bit in H_CSR */ 47 mei_reg_write(dev, H_CSR, csr_reg); 48 49 return IRQ_WAKE_THREAD; 50} 51 52/** 53 * _mei_cmpl - processes completed operation. 54 * 55 * @cl: private data of the file object. 56 * @cb_pos: callback block. 57 */ 58static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) 59{ 60 if (cb_pos->major_file_operations == MEI_WRITE) { 61 mei_free_cb_private(cb_pos); 62 cb_pos = NULL; 63 cl->writing_state = MEI_WRITE_COMPLETE; 64 if (waitqueue_active(&cl->tx_wait)) 65 wake_up_interruptible(&cl->tx_wait); 66 67 } else if (cb_pos->major_file_operations == MEI_READ && 68 MEI_READING == cl->reading_state) { 69 cl->reading_state = MEI_READ_COMPLETE; 70 if (waitqueue_active(&cl->rx_wait)) 71 wake_up_interruptible(&cl->rx_wait); 72 73 } 74} 75 76/** 77 * _mei_cmpl_iamthif - processes completed iamthif operation. 78 * 79 * @dev: the device structure. 80 * @cb_pos: callback block. 81 */ 82static void _mei_cmpl_iamthif(struct mei_device *dev, struct mei_cl_cb *cb_pos) 83{ 84 if (dev->iamthif_canceled != 1) { 85 dev->iamthif_state = MEI_IAMTHIF_READ_COMPLETE; 86 dev->iamthif_stall_timer = 0; 87 memcpy(cb_pos->response_buffer.data, 88 dev->iamthif_msg_buf, 89 dev->iamthif_msg_buf_index); 90 list_add_tail(&cb_pos->cb_list, 91 &dev->amthi_read_complete_list.mei_cb.cb_list); 92 dev_dbg(&dev->pdev->dev, "amthi read completed.\n"); 93 dev->iamthif_timer = jiffies; 94 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", 95 dev->iamthif_timer); 96 } else { 97 mei_run_next_iamthif_cmd(dev); 98 } 99 100 dev_dbg(&dev->pdev->dev, "completing amthi call back.\n"); 101 wake_up_interruptible(&dev->iamthif_cl.wait); 102} 103 104 105/** 106 * mei_irq_thread_read_amthi_message - bottom half read routine after ISR to 107 * handle the read amthi message data processing. 108 * 109 * @complete_list: An instance of our list structure 110 * @dev: the device structure 111 * @mei_hdr: header of amthi message 112 * 113 * returns 0 on success, <0 on failure. 114 */ 115static int mei_irq_thread_read_amthi_message(struct mei_io_list *complete_list, 116 struct mei_device *dev, 117 struct mei_msg_hdr *mei_hdr) 118{ 119 struct mei_cl *cl; 120 struct mei_cl_cb *cb; 121 unsigned char *buffer; 122 123 BUG_ON(mei_hdr->me_addr != dev->iamthif_cl.me_client_id); 124 BUG_ON(dev->iamthif_state != MEI_IAMTHIF_READING); 125 126 buffer = dev->iamthif_msg_buf + dev->iamthif_msg_buf_index; 127 BUG_ON(dev->iamthif_mtu < dev->iamthif_msg_buf_index + mei_hdr->length); 128 129 mei_read_slots(dev, buffer, mei_hdr->length); 130 131 dev->iamthif_msg_buf_index += mei_hdr->length; 132 133 if (!mei_hdr->msg_complete) 134 return 0; 135 136 dev_dbg(&dev->pdev->dev, 137 "amthi_message_buffer_index =%d\n", 138 mei_hdr->length); 139 140 dev_dbg(&dev->pdev->dev, "completed amthi read.\n "); 141 if (!dev->iamthif_current_cb) 142 return -ENODEV; 143 144 cb = dev->iamthif_current_cb; 145 dev->iamthif_current_cb = NULL; 146 147 cl = (struct mei_cl *)cb->file_private; 148 if (!cl) 149 return -ENODEV; 150 151 dev->iamthif_stall_timer = 0; 152 cb->information = dev->iamthif_msg_buf_index; 153 cb->read_time = jiffies; 154 if (dev->iamthif_ioctl && cl == &dev->iamthif_cl) { 155 /* found the iamthif cb */ 156 dev_dbg(&dev->pdev->dev, "complete the amthi read cb.\n "); 157 dev_dbg(&dev->pdev->dev, "add the amthi read cb to complete.\n "); 158 list_add_tail(&cb->cb_list, 159 &complete_list->mei_cb.cb_list); 160 } 161 return 0; 162} 163 164/** 165 * _mei_irq_thread_state_ok - checks if mei header matches file private data 166 * 167 * @cl: private data of the file object 168 * @mei_hdr: header of mei client message 169 * 170 * returns !=0 if matches, 0 if no match. 171 */ 172static int _mei_irq_thread_state_ok(struct mei_cl *cl, 173 struct mei_msg_hdr *mei_hdr) 174{ 175 return (cl->host_client_id == mei_hdr->host_addr && 176 cl->me_client_id == mei_hdr->me_addr && 177 cl->state == MEI_FILE_CONNECTED && 178 MEI_READ_COMPLETE != cl->reading_state); 179} 180 181/** 182 * mei_irq_thread_read_client_message - bottom half read routine after ISR to 183 * handle the read mei client message data processing. 184 * 185 * @complete_list: An instance of our list structure 186 * @dev: the device structure 187 * @mei_hdr: header of mei client message 188 * 189 * returns 0 on success, <0 on failure. 190 */ 191static int mei_irq_thread_read_client_message(struct mei_io_list *complete_list, 192 struct mei_device *dev, 193 struct mei_msg_hdr *mei_hdr) 194{ 195 struct mei_cl *cl; 196 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 197 unsigned char *buffer = NULL; 198 199 dev_dbg(&dev->pdev->dev, "start client msg\n"); 200 if (list_empty(&dev->read_list.mei_cb.cb_list)) 201 goto quit; 202 203 list_for_each_entry_safe(cb_pos, cb_next, 204 &dev->read_list.mei_cb.cb_list, cb_list) { 205 cl = (struct mei_cl *)cb_pos->file_private; 206 if (cl && _mei_irq_thread_state_ok(cl, mei_hdr)) { 207 cl->reading_state = MEI_READING; 208 buffer = cb_pos->response_buffer.data + cb_pos->information; 209 210 if (cb_pos->response_buffer.size < 211 mei_hdr->length + cb_pos->information) { 212 dev_dbg(&dev->pdev->dev, "message overflow.\n"); 213 list_del(&cb_pos->cb_list); 214 return -ENOMEM; 215 } 216 if (buffer) 217 mei_read_slots(dev, buffer, mei_hdr->length); 218 219 cb_pos->information += mei_hdr->length; 220 if (mei_hdr->msg_complete) { 221 cl->status = 0; 222 list_del(&cb_pos->cb_list); 223 dev_dbg(&dev->pdev->dev, 224 "completed read host client = %d," 225 "ME client = %d, " 226 "data length = %lu\n", 227 cl->host_client_id, 228 cl->me_client_id, 229 cb_pos->information); 230 231 *(cb_pos->response_buffer.data + 232 cb_pos->information) = '\0'; 233 dev_dbg(&dev->pdev->dev, "cb_pos->res_buffer - %s\n", 234 cb_pos->response_buffer.data); 235 list_add_tail(&cb_pos->cb_list, 236 &complete_list->mei_cb.cb_list); 237 } 238 239 break; 240 } 241 242 } 243 244quit: 245 dev_dbg(&dev->pdev->dev, "message read\n"); 246 if (!buffer) { 247 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); 248 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n", 249 *(u32 *) dev->rd_msg_buf); 250 } 251 252 return 0; 253} 254 255/** 256 * _mei_irq_thread_iamthif_read - prepares to read iamthif data. 257 * 258 * @dev: the device structure. 259 * @slots: free slots. 260 * 261 * returns 0, OK; otherwise, error. 262 */ 263static int _mei_irq_thread_iamthif_read(struct mei_device *dev, s32 *slots) 264{ 265 266 if (((*slots) * sizeof(u32)) < (sizeof(struct mei_msg_hdr) 267 + sizeof(struct hbm_flow_control))) { 268 return -EMSGSIZE; 269 } 270 *slots -= (sizeof(struct mei_msg_hdr) + 271 sizeof(struct hbm_flow_control) + 3) / 4; 272 if (mei_send_flow_control(dev, &dev->iamthif_cl)) { 273 dev_dbg(&dev->pdev->dev, "iamthif flow control failed\n"); 274 return -EIO; 275 } 276 277 dev_dbg(&dev->pdev->dev, "iamthif flow control success\n"); 278 dev->iamthif_state = MEI_IAMTHIF_READING; 279 dev->iamthif_flow_control_pending = false; 280 dev->iamthif_msg_buf_index = 0; 281 dev->iamthif_msg_buf_size = 0; 282 dev->iamthif_stall_timer = IAMTHIF_STALL_TIMER; 283 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev); 284 return 0; 285} 286 287/** 288 * _mei_irq_thread_close - processes close related operation. 289 * 290 * @dev: the device structure. 291 * @slots: free slots. 292 * @cb_pos: callback block. 293 * @cl: private data of the file object. 294 * @cmpl_list: complete list. 295 * 296 * returns 0, OK; otherwise, error. 297 */ 298static int _mei_irq_thread_close(struct mei_device *dev, s32 *slots, 299 struct mei_cl_cb *cb_pos, 300 struct mei_cl *cl, 301 struct mei_io_list *cmpl_list) 302{ 303 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 304 sizeof(struct hbm_client_disconnect_request))) { 305 *slots -= (sizeof(struct mei_msg_hdr) + 306 sizeof(struct hbm_client_disconnect_request) + 3) / 4; 307 308 if (mei_disconnect(dev, cl)) { 309 cl->status = 0; 310 cb_pos->information = 0; 311 list_move_tail(&cb_pos->cb_list, 312 &cmpl_list->mei_cb.cb_list); 313 return -EMSGSIZE; 314 } else { 315 cl->state = MEI_FILE_DISCONNECTING; 316 cl->status = 0; 317 cb_pos->information = 0; 318 list_move_tail(&cb_pos->cb_list, 319 &dev->ctrl_rd_list.mei_cb.cb_list); 320 cl->timer_count = MEI_CONNECT_TIMEOUT; 321 } 322 } else { 323 /* return the cancel routine */ 324 return -EBADMSG; 325 } 326 327 return 0; 328} 329 330/** 331 * is_treat_specially_client - checks if the message belongs 332 * to the file private data. 333 * 334 * @cl: private data of the file object 335 * @rs: connect response bus message 336 * 337 */ 338static bool is_treat_specially_client(struct mei_cl *cl, 339 struct hbm_client_connect_response *rs) 340{ 341 342 if (cl->host_client_id == rs->host_addr && 343 cl->me_client_id == rs->me_addr) { 344 if (!rs->status) { 345 cl->state = MEI_FILE_CONNECTED; 346 cl->status = 0; 347 348 } else { 349 cl->state = MEI_FILE_DISCONNECTED; 350 cl->status = -ENODEV; 351 } 352 cl->timer_count = 0; 353 354 return true; 355 } 356 return false; 357} 358 359/** 360 * mei_client_connect_response - connects to response irq routine 361 * 362 * @dev: the device structure 363 * @rs: connect response bus message 364 */ 365static void mei_client_connect_response(struct mei_device *dev, 366 struct hbm_client_connect_response *rs) 367{ 368 369 struct mei_cl *cl; 370 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 371 372 dev_dbg(&dev->pdev->dev, 373 "connect_response:\n" 374 "ME Client = %d\n" 375 "Host Client = %d\n" 376 "Status = %d\n", 377 rs->me_addr, 378 rs->host_addr, 379 rs->status); 380 381 /* if WD or iamthif client treat specially */ 382 383 if (is_treat_specially_client(&(dev->wd_cl), rs)) { 384 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); 385 mei_watchdog_register(dev); 386 387 /* next step in the state maching */ 388 mei_host_init_iamthif(dev); 389 return; 390 } 391 392 if (is_treat_specially_client(&(dev->iamthif_cl), rs)) { 393 dev->iamthif_state = MEI_IAMTHIF_IDLE; 394 return; 395 } 396 list_for_each_entry_safe(cb_pos, cb_next, 397 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) { 398 399 cl = (struct mei_cl *)cb_pos->file_private; 400 if (!cl) { 401 list_del(&cb_pos->cb_list); 402 return; 403 } 404 if (MEI_IOCTL == cb_pos->major_file_operations) { 405 if (is_treat_specially_client(cl, rs)) { 406 list_del(&cb_pos->cb_list); 407 cl->status = 0; 408 cl->timer_count = 0; 409 break; 410 } 411 } 412 } 413} 414 415/** 416 * mei_client_disconnect_response - disconnects from response irq routine 417 * 418 * @dev: the device structure 419 * @rs: disconnect response bus message 420 */ 421static void mei_client_disconnect_response(struct mei_device *dev, 422 struct hbm_client_connect_response *rs) 423{ 424 struct mei_cl *cl; 425 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 426 427 dev_dbg(&dev->pdev->dev, 428 "disconnect_response:\n" 429 "ME Client = %d\n" 430 "Host Client = %d\n" 431 "Status = %d\n", 432 rs->me_addr, 433 rs->host_addr, 434 rs->status); 435 436 list_for_each_entry_safe(cb_pos, cb_next, 437 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) { 438 cl = (struct mei_cl *)cb_pos->file_private; 439 440 if (!cl) { 441 list_del(&cb_pos->cb_list); 442 return; 443 } 444 445 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n"); 446 if (cl->host_client_id == rs->host_addr && 447 cl->me_client_id == rs->me_addr) { 448 449 list_del(&cb_pos->cb_list); 450 if (!rs->status) 451 cl->state = MEI_FILE_DISCONNECTED; 452 453 cl->status = 0; 454 cl->timer_count = 0; 455 break; 456 } 457 } 458} 459 460/** 461 * same_flow_addr - tells if they have the same address. 462 * 463 * @file: private data of the file object. 464 * @flow: flow control. 465 * 466 * returns !=0, same; 0,not. 467 */ 468static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow) 469{ 470 return (cl->host_client_id == flow->host_addr && 471 cl->me_client_id == flow->me_addr); 472} 473 474/** 475 * add_single_flow_creds - adds single buffer credentials. 476 * 477 * @file: private data ot the file object. 478 * @flow: flow control. 479 */ 480static void add_single_flow_creds(struct mei_device *dev, 481 struct hbm_flow_control *flow) 482{ 483 struct mei_me_client *client; 484 int i; 485 486 for (i = 0; i < dev->me_clients_num; i++) { 487 client = &dev->me_clients[i]; 488 if (client && flow->me_addr == client->client_id) { 489 if (client->props.single_recv_buf) { 490 client->mei_flow_ctrl_creds++; 491 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n", 492 flow->me_addr); 493 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n", 494 client->mei_flow_ctrl_creds); 495 } else { 496 BUG(); /* error in flow control */ 497 } 498 } 499 } 500} 501 502/** 503 * mei_client_flow_control_response - flow control response irq routine 504 * 505 * @dev: the device structure 506 * @flow_control: flow control response bus message 507 */ 508static void mei_client_flow_control_response(struct mei_device *dev, 509 struct hbm_flow_control *flow_control) 510{ 511 struct mei_cl *cl_pos = NULL; 512 struct mei_cl *cl_next = NULL; 513 514 if (!flow_control->host_addr) { 515 /* single receive buffer */ 516 add_single_flow_creds(dev, flow_control); 517 } else { 518 /* normal connection */ 519 list_for_each_entry_safe(cl_pos, cl_next, 520 &dev->file_list, link) { 521 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n"); 522 523 dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n", 524 cl_pos->host_client_id, 525 cl_pos->me_client_id); 526 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n", 527 flow_control->host_addr, 528 flow_control->me_addr); 529 if (same_flow_addr(cl_pos, flow_control)) { 530 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n", 531 flow_control->host_addr, 532 flow_control->me_addr); 533 cl_pos->mei_flow_ctrl_creds++; 534 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n", 535 cl_pos->mei_flow_ctrl_creds); 536 break; 537 } 538 } 539 } 540} 541 542/** 543 * same_disconn_addr - tells if they have the same address 544 * 545 * @file: private data of the file object. 546 * @disconn: disconnection request. 547 * 548 * returns !=0, same; 0,not. 549 */ 550static int same_disconn_addr(struct mei_cl *cl, 551 struct hbm_client_disconnect_request *disconn) 552{ 553 return (cl->host_client_id == disconn->host_addr && 554 cl->me_client_id == disconn->me_addr); 555} 556 557/** 558 * mei_client_disconnect_request - disconnects from request irq routine 559 * 560 * @dev: the device structure. 561 * @disconnect_req: disconnect request bus message. 562 */ 563static void mei_client_disconnect_request(struct mei_device *dev, 564 struct hbm_client_disconnect_request *disconnect_req) 565{ 566 struct mei_msg_hdr *mei_hdr; 567 struct hbm_client_connect_response *disconnect_res; 568 struct mei_cl *cl_pos = NULL; 569 struct mei_cl *cl_next = NULL; 570 571 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 572 if (same_disconn_addr(cl_pos, disconnect_req)) { 573 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n", 574 disconnect_req->host_addr, 575 disconnect_req->me_addr); 576 cl_pos->state = MEI_FILE_DISCONNECTED; 577 cl_pos->timer_count = 0; 578 if (cl_pos == &dev->wd_cl) { 579 dev->wd_due_counter = 0; 580 dev->wd_pending = false; 581 } else if (cl_pos == &dev->iamthif_cl) 582 dev->iamthif_timer = 0; 583 584 /* prepare disconnect response */ 585 mei_hdr = 586 (struct mei_msg_hdr *) &dev->ext_msg_buf[0]; 587 mei_hdr->host_addr = 0; 588 mei_hdr->me_addr = 0; 589 mei_hdr->length = 590 sizeof(struct hbm_client_connect_response); 591 mei_hdr->msg_complete = 1; 592 mei_hdr->reserved = 0; 593 594 disconnect_res = 595 (struct hbm_client_connect_response *) 596 &dev->ext_msg_buf[1]; 597 disconnect_res->host_addr = cl_pos->host_client_id; 598 disconnect_res->me_addr = cl_pos->me_client_id; 599 disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD; 600 disconnect_res->status = 0; 601 dev->extra_write_index = 2; 602 break; 603 } 604 } 605} 606 607 608/** 609 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to 610 * handle the read bus message cmd processing. 611 * 612 * @dev: the device structure 613 * @mei_hdr: header of bus message 614 */ 615static void mei_irq_thread_read_bus_message(struct mei_device *dev, 616 struct mei_msg_hdr *mei_hdr) 617{ 618 struct mei_bus_message *mei_msg; 619 struct hbm_host_version_response *version_res; 620 struct hbm_client_connect_response *connect_res; 621 struct hbm_client_connect_response *disconnect_res; 622 struct hbm_flow_control *flow_control; 623 struct hbm_props_response *props_res; 624 struct hbm_host_enum_response *enum_res; 625 struct hbm_client_disconnect_request *disconnect_req; 626 struct hbm_host_stop_request *host_stop_req; 627 int res; 628 629 630 /* read the message to our buffer */ 631 BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); 632 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); 633 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf; 634 635 switch (mei_msg->hbm_cmd) { 636 case HOST_START_RES_CMD: 637 version_res = (struct hbm_host_version_response *) mei_msg; 638 if (version_res->host_version_supported) { 639 dev->version.major_version = HBM_MAJOR_VERSION; 640 dev->version.minor_version = HBM_MINOR_VERSION; 641 if (dev->mei_state == MEI_INIT_CLIENTS && 642 dev->init_clients_state == MEI_START_MESSAGE) { 643 dev->init_clients_timer = 0; 644 mei_host_enum_clients_message(dev); 645 } else { 646 dev->recvd_msg = false; 647 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n"); 648 mei_reset(dev, 1); 649 return; 650 } 651 } else { 652 dev->version = version_res->me_max_version; 653 /* send stop message */ 654 mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; 655 mei_hdr->host_addr = 0; 656 mei_hdr->me_addr = 0; 657 mei_hdr->length = sizeof(struct hbm_host_stop_request); 658 mei_hdr->msg_complete = 1; 659 mei_hdr->reserved = 0; 660 661 host_stop_req = (struct hbm_host_stop_request *) 662 &dev->wr_msg_buf[1]; 663 664 memset(host_stop_req, 665 0, 666 sizeof(struct hbm_host_stop_request)); 667 host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD; 668 host_stop_req->reason = DRIVER_STOP_REQUEST; 669 mei_write_message(dev, mei_hdr, 670 (unsigned char *) (host_stop_req), 671 mei_hdr->length); 672 dev_dbg(&dev->pdev->dev, "version mismatch.\n"); 673 return; 674 } 675 676 dev->recvd_msg = true; 677 dev_dbg(&dev->pdev->dev, "host start response message received.\n"); 678 break; 679 680 case CLIENT_CONNECT_RES_CMD: 681 connect_res = 682 (struct hbm_client_connect_response *) mei_msg; 683 mei_client_connect_response(dev, connect_res); 684 dev_dbg(&dev->pdev->dev, "client connect response message received.\n"); 685 wake_up(&dev->wait_recvd_msg); 686 break; 687 688 case CLIENT_DISCONNECT_RES_CMD: 689 disconnect_res = 690 (struct hbm_client_connect_response *) mei_msg; 691 mei_client_disconnect_response(dev, disconnect_res); 692 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n"); 693 wake_up(&dev->wait_recvd_msg); 694 break; 695 696 case MEI_FLOW_CONTROL_CMD: 697 flow_control = (struct hbm_flow_control *) mei_msg; 698 mei_client_flow_control_response(dev, flow_control); 699 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n"); 700 break; 701 702 case HOST_CLIENT_PROPERTIES_RES_CMD: 703 props_res = (struct hbm_props_response *)mei_msg; 704 if (props_res->status || !dev->me_clients) { 705 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); 706 mei_reset(dev, 1); 707 return; 708 } 709 if (dev->me_clients[dev->me_client_presentation_num] 710 .client_id == props_res->address) { 711 712 dev->me_clients[dev->me_client_presentation_num].props 713 = props_res->client_properties; 714 715 if (dev->mei_state == MEI_INIT_CLIENTS && 716 dev->init_clients_state == 717 MEI_CLIENT_PROPERTIES_MESSAGE) { 718 dev->me_client_index++; 719 dev->me_client_presentation_num++; 720 721 /** Send Client Properties request **/ 722 res = mei_host_client_properties(dev); 723 if (res < 0) { 724 dev_dbg(&dev->pdev->dev, "mei_host_client_properties() failed"); 725 return; 726 } else if (!res) { 727 /* 728 * No more clients to send to. 729 * Clear Map for indicating now ME clients 730 * with associated host client 731 */ 732 bitmap_zero(dev->host_clients_map, MEI_CLIENTS_MAX); 733 dev->open_handle_count = 0; 734 735 /* 736 * Reserving the first three client IDs 737 * Client Id 0 - Reserved for MEI Bus Message communications 738 * Client Id 1 - Reserved for Watchdog 739 * Client ID 2 - Reserved for AMTHI 740 */ 741 bitmap_set(dev->host_clients_map, 0, 3); 742 dev->mei_state = MEI_ENABLED; 743 744 /* if wd initialization fails, initialization the AMTHI client, 745 * otherwise the AMTHI client will be initialized after the WD client connect response 746 * will be received 747 */ 748 if (mei_wd_host_init(dev)) 749 mei_host_init_iamthif(dev); 750 } 751 752 } else { 753 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message"); 754 mei_reset(dev, 1); 755 return; 756 } 757 } else { 758 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n"); 759 mei_reset(dev, 1); 760 return; 761 } 762 break; 763 764 case HOST_ENUM_RES_CMD: 765 enum_res = (struct hbm_host_enum_response *) mei_msg; 766 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); 767 if (dev->mei_state == MEI_INIT_CLIENTS && 768 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { 769 dev->init_clients_timer = 0; 770 dev->me_client_presentation_num = 0; 771 dev->me_client_index = 0; 772 mei_allocate_me_clients_storage(dev); 773 dev->init_clients_state = 774 MEI_CLIENT_PROPERTIES_MESSAGE; 775 mei_host_client_properties(dev); 776 } else { 777 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); 778 mei_reset(dev, 1); 779 return; 780 } 781 break; 782 783 case HOST_STOP_RES_CMD: 784 dev->mei_state = MEI_DISABLED; 785 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n"); 786 mei_reset(dev, 1); 787 break; 788 789 case CLIENT_DISCONNECT_REQ_CMD: 790 /* search for client */ 791 disconnect_req = 792 (struct hbm_client_disconnect_request *) mei_msg; 793 mei_client_disconnect_request(dev, disconnect_req); 794 break; 795 796 case ME_STOP_REQ_CMD: 797 /* prepare stop request */ 798 mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0]; 799 mei_hdr->host_addr = 0; 800 mei_hdr->me_addr = 0; 801 mei_hdr->length = sizeof(struct hbm_host_stop_request); 802 mei_hdr->msg_complete = 1; 803 mei_hdr->reserved = 0; 804 host_stop_req = 805 (struct hbm_host_stop_request *) &dev->ext_msg_buf[1]; 806 memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request)); 807 host_stop_req->hbm_cmd = HOST_STOP_REQ_CMD; 808 host_stop_req->reason = DRIVER_STOP_REQUEST; 809 host_stop_req->reserved[0] = 0; 810 host_stop_req->reserved[1] = 0; 811 dev->extra_write_index = 2; 812 break; 813 814 default: 815 BUG(); 816 break; 817 818 } 819} 820 821 822/** 823 * _mei_hb_read - processes read related operation. 824 * 825 * @dev: the device structure. 826 * @slots: free slots. 827 * @cb_pos: callback block. 828 * @cl: private data of the file object. 829 * @cmpl_list: complete list. 830 * 831 * returns 0, OK; otherwise, error. 832 */ 833static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, 834 struct mei_cl_cb *cb_pos, 835 struct mei_cl *cl, 836 struct mei_io_list *cmpl_list) 837{ 838 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 839 sizeof(struct hbm_flow_control))) { 840 /* return the cancel routine */ 841 list_del(&cb_pos->cb_list); 842 return -EBADMSG; 843 } 844 845 *slots -= (sizeof(struct mei_msg_hdr) + 846 sizeof(struct hbm_flow_control) + 3) / 4; 847 if (mei_send_flow_control(dev, cl)) { 848 cl->status = -ENODEV; 849 cb_pos->information = 0; 850 list_move_tail(&cb_pos->cb_list, &cmpl_list->mei_cb.cb_list); 851 return -ENODEV; 852 } 853 list_move_tail(&cb_pos->cb_list, &dev->read_list.mei_cb.cb_list); 854 855 return 0; 856} 857 858 859/** 860 * _mei_irq_thread_ioctl - processes ioctl related operation. 861 * 862 * @dev: the device structure. 863 * @slots: free slots. 864 * @cb_pos: callback block. 865 * @cl: private data of the file object. 866 * @cmpl_list: complete list. 867 * 868 * returns 0, OK; otherwise, error. 869 */ 870static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, 871 struct mei_cl_cb *cb_pos, 872 struct mei_cl *cl, 873 struct mei_io_list *cmpl_list) 874{ 875 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 876 sizeof(struct hbm_client_connect_request))) { 877 cl->state = MEI_FILE_CONNECTING; 878 *slots -= (sizeof(struct mei_msg_hdr) + 879 sizeof(struct hbm_client_connect_request) + 3) / 4; 880 if (mei_connect(dev, cl)) { 881 cl->status = -ENODEV; 882 cb_pos->information = 0; 883 list_del(&cb_pos->cb_list); 884 return -ENODEV; 885 } else { 886 list_move_tail(&cb_pos->cb_list, 887 &dev->ctrl_rd_list.mei_cb.cb_list); 888 cl->timer_count = MEI_CONNECT_TIMEOUT; 889 } 890 } else { 891 /* return the cancel routine */ 892 list_del(&cb_pos->cb_list); 893 return -EBADMSG; 894 } 895 896 return 0; 897} 898 899/** 900 * _mei_irq_thread_cmpl - processes completed and no-iamthif operation. 901 * 902 * @dev: the device structure. 903 * @slots: free slots. 904 * @cb_pos: callback block. 905 * @cl: private data of the file object. 906 * @cmpl_list: complete list. 907 * 908 * returns 0, OK; otherwise, error. 909 */ 910static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots, 911 struct mei_cl_cb *cb_pos, 912 struct mei_cl *cl, 913 struct mei_io_list *cmpl_list) 914{ 915 struct mei_msg_hdr *mei_hdr; 916 917 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 918 (cb_pos->request_buffer.size - 919 cb_pos->information))) { 920 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 921 mei_hdr->host_addr = cl->host_client_id; 922 mei_hdr->me_addr = cl->me_client_id; 923 mei_hdr->length = cb_pos->request_buffer.size - 924 cb_pos->information; 925 mei_hdr->msg_complete = 1; 926 mei_hdr->reserved = 0; 927 dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d" 928 "mei_hdr->msg_complete = %d\n", 929 cb_pos->request_buffer.size, 930 mei_hdr->msg_complete); 931 dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n", 932 cb_pos->information); 933 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 934 mei_hdr->length); 935 *slots -= (sizeof(struct mei_msg_hdr) + 936 mei_hdr->length + 3) / 4; 937 if (mei_write_message(dev, mei_hdr, 938 (unsigned char *) 939 (cb_pos->request_buffer.data + 940 cb_pos->information), 941 mei_hdr->length)) { 942 cl->status = -ENODEV; 943 list_move_tail(&cb_pos->cb_list, 944 &cmpl_list->mei_cb.cb_list); 945 return -ENODEV; 946 } else { 947 if (mei_flow_ctrl_reduce(dev, cl)) 948 return -ENODEV; 949 cl->status = 0; 950 cb_pos->information += mei_hdr->length; 951 list_move_tail(&cb_pos->cb_list, 952 &dev->write_waiting_list.mei_cb.cb_list); 953 } 954 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { 955 /* buffer is still empty */ 956 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 957 mei_hdr->host_addr = cl->host_client_id; 958 mei_hdr->me_addr = cl->me_client_id; 959 mei_hdr->length = 960 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); 961 mei_hdr->msg_complete = 0; 962 mei_hdr->reserved = 0; 963 964 (*slots) -= (sizeof(struct mei_msg_hdr) + 965 mei_hdr->length + 3) / 4; 966 if (mei_write_message(dev, mei_hdr, 967 (unsigned char *) 968 (cb_pos->request_buffer.data + 969 cb_pos->information), 970 mei_hdr->length)) { 971 cl->status = -ENODEV; 972 list_move_tail(&cb_pos->cb_list, 973 &cmpl_list->mei_cb.cb_list); 974 return -ENODEV; 975 } else { 976 cb_pos->information += mei_hdr->length; 977 dev_dbg(&dev->pdev->dev, 978 "cb_pos->request_buffer.size =%d" 979 " mei_hdr->msg_complete = %d\n", 980 cb_pos->request_buffer.size, 981 mei_hdr->msg_complete); 982 dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n", 983 cb_pos->information); 984 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 985 mei_hdr->length); 986 } 987 return -EMSGSIZE; 988 } else { 989 return -EBADMSG; 990 } 991 992 return 0; 993} 994 995/** 996 * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation. 997 * 998 * @dev: the device structure. 999 * @slots: free slots. 1000 * @cb_pos: callback block. 1001 * @cl: private data of the file object. 1002 * @cmpl_list: complete list. 1003 * 1004 * returns 0, OK; otherwise, error. 1005 */ 1006static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, 1007 struct mei_cl_cb *cb_pos, 1008 struct mei_cl *cl, 1009 struct mei_io_list *cmpl_list) 1010{ 1011 struct mei_msg_hdr *mei_hdr; 1012 1013 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 1014 dev->iamthif_msg_buf_size - 1015 dev->iamthif_msg_buf_index)) { 1016 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 1017 mei_hdr->host_addr = cl->host_client_id; 1018 mei_hdr->me_addr = cl->me_client_id; 1019 mei_hdr->length = dev->iamthif_msg_buf_size - 1020 dev->iamthif_msg_buf_index; 1021 mei_hdr->msg_complete = 1; 1022 mei_hdr->reserved = 0; 1023 1024 *slots -= (sizeof(struct mei_msg_hdr) + 1025 mei_hdr->length + 3) / 4; 1026 1027 if (mei_write_message(dev, mei_hdr, 1028 (dev->iamthif_msg_buf + 1029 dev->iamthif_msg_buf_index), 1030 mei_hdr->length)) { 1031 dev->iamthif_state = MEI_IAMTHIF_IDLE; 1032 cl->status = -ENODEV; 1033 list_del(&cb_pos->cb_list); 1034 return -ENODEV; 1035 } else { 1036 if (mei_flow_ctrl_reduce(dev, cl)) 1037 return -ENODEV; 1038 dev->iamthif_msg_buf_index += mei_hdr->length; 1039 cb_pos->information = dev->iamthif_msg_buf_index; 1040 cl->status = 0; 1041 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; 1042 dev->iamthif_flow_control_pending = true; 1043 /* save iamthif cb sent to amthi client */ 1044 dev->iamthif_current_cb = cb_pos; 1045 list_move_tail(&cb_pos->cb_list, 1046 &dev->write_waiting_list.mei_cb.cb_list); 1047 1048 } 1049 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { 1050 /* buffer is still empty */ 1051 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 1052 mei_hdr->host_addr = cl->host_client_id; 1053 mei_hdr->me_addr = cl->me_client_id; 1054 mei_hdr->length = 1055 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); 1056 mei_hdr->msg_complete = 0; 1057 mei_hdr->reserved = 0; 1058 1059 *slots -= (sizeof(struct mei_msg_hdr) + 1060 mei_hdr->length + 3) / 4; 1061 1062 if (mei_write_message(dev, mei_hdr, 1063 (dev->iamthif_msg_buf + 1064 dev->iamthif_msg_buf_index), 1065 mei_hdr->length)) { 1066 cl->status = -ENODEV; 1067 list_del(&cb_pos->cb_list); 1068 } else { 1069 dev->iamthif_msg_buf_index += mei_hdr->length; 1070 } 1071 return -EMSGSIZE; 1072 } else { 1073 return -EBADMSG; 1074 } 1075 1076 return 0; 1077} 1078 1079/** 1080 * mei_irq_thread_read_handler - bottom half read routine after ISR to 1081 * handle the read processing. 1082 * 1083 * @cmpl_list: An instance of our list structure 1084 * @dev: the device structure 1085 * @slots: slots to read. 1086 * 1087 * returns 0 on success, <0 on failure. 1088 */ 1089static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list, 1090 struct mei_device *dev, 1091 s32 *slots) 1092{ 1093 struct mei_msg_hdr *mei_hdr; 1094 struct mei_cl *cl_pos = NULL; 1095 struct mei_cl *cl_next = NULL; 1096 int ret = 0; 1097 1098 if (!dev->rd_msg_hdr) { 1099 dev->rd_msg_hdr = mei_mecbrw_read(dev); 1100 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 1101 (*slots)--; 1102 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 1103 } 1104 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr; 1105 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length); 1106 1107 if (mei_hdr->reserved || !dev->rd_msg_hdr) { 1108 dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); 1109 ret = -EBADMSG; 1110 goto end; 1111 } 1112 1113 if (mei_hdr->host_addr || mei_hdr->me_addr) { 1114 list_for_each_entry_safe(cl_pos, cl_next, 1115 &dev->file_list, link) { 1116 dev_dbg(&dev->pdev->dev, 1117 "list_for_each_entry_safe read host" 1118 " client = %d, ME client = %d\n", 1119 cl_pos->host_client_id, 1120 cl_pos->me_client_id); 1121 if (cl_pos->host_client_id == mei_hdr->host_addr && 1122 cl_pos->me_client_id == mei_hdr->me_addr) 1123 break; 1124 } 1125 1126 if (&cl_pos->link == &dev->file_list) { 1127 dev_dbg(&dev->pdev->dev, "corrupted message header\n"); 1128 ret = -EBADMSG; 1129 goto end; 1130 } 1131 } 1132 if (((*slots) * sizeof(u32)) < mei_hdr->length) { 1133 dev_dbg(&dev->pdev->dev, 1134 "we can't read the message slots =%08x.\n", 1135 *slots); 1136 /* we can't read the message */ 1137 ret = -ERANGE; 1138 goto end; 1139 } 1140 1141 /* decide where to read the message too */ 1142 if (!mei_hdr->host_addr) { 1143 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n"); 1144 mei_irq_thread_read_bus_message(dev, mei_hdr); 1145 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n"); 1146 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 1147 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && 1148 (dev->iamthif_state == MEI_IAMTHIF_READING)) { 1149 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); 1150 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 1151 mei_hdr->length); 1152 ret = mei_irq_thread_read_amthi_message(cmpl_list, 1153 dev, mei_hdr); 1154 if (ret) 1155 goto end; 1156 1157 } else { 1158 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n"); 1159 ret = mei_irq_thread_read_client_message(cmpl_list, 1160 dev, mei_hdr); 1161 if (ret) 1162 goto end; 1163 1164 } 1165 1166 /* reset the number of slots and header */ 1167 *slots = mei_count_full_read_slots(dev); 1168 dev->rd_msg_hdr = 0; 1169 1170 if (*slots == -EOVERFLOW) { 1171 /* overflow - reset */ 1172 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n"); 1173 /* set the event since message has been read */ 1174 ret = -ERANGE; 1175 goto end; 1176 } 1177end: 1178 return ret; 1179} 1180 1181 1182/** 1183 * mei_irq_thread_write_handler - bottom half write routine after 1184 * ISR to handle the write processing. 1185 * 1186 * @cmpl_list: An instance of our list structure 1187 * @dev: the device structure 1188 * @slots: slots to write. 1189 * 1190 * returns 0 on success, <0 on failure. 1191 */ 1192static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, 1193 struct mei_device *dev, 1194 s32 *slots) 1195{ 1196 1197 struct mei_cl *cl; 1198 struct mei_cl_cb *pos = NULL, *next = NULL; 1199 struct mei_io_list *list; 1200 int ret; 1201 1202 if (!mei_host_buffer_is_empty(dev)) { 1203 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); 1204 return 0; 1205 } 1206 *slots = mei_count_empty_write_slots(dev); 1207 /* complete all waiting for write CB */ 1208 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); 1209 1210 list = &dev->write_waiting_list; 1211 list_for_each_entry_safe(pos, next, 1212 &list->mei_cb.cb_list, cb_list) { 1213 cl = (struct mei_cl *)pos->file_private; 1214 if (cl == NULL) 1215 continue; 1216 1217 cl->status = 0; 1218 list_del(&pos->cb_list); 1219 if (MEI_WRITING == cl->writing_state && 1220 (pos->major_file_operations == MEI_WRITE) && 1221 (cl != &dev->iamthif_cl)) { 1222 dev_dbg(&dev->pdev->dev, 1223 "MEI WRITE COMPLETE\n"); 1224 cl->writing_state = MEI_WRITE_COMPLETE; 1225 list_add_tail(&pos->cb_list, 1226 &cmpl_list->mei_cb.cb_list); 1227 } 1228 if (cl == &dev->iamthif_cl) { 1229 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); 1230 if (dev->iamthif_flow_control_pending) { 1231 ret = _mei_irq_thread_iamthif_read( 1232 dev, slots); 1233 if (ret) 1234 return ret; 1235 } 1236 } 1237 } 1238 1239 if (dev->stop && !dev->wd_pending) { 1240 dev->wd_stopped = true; 1241 wake_up_interruptible(&dev->wait_stop_wd); 1242 return 0; 1243 } 1244 1245 if (dev->extra_write_index) { 1246 dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n", 1247 dev->extra_write_index); 1248 mei_write_message(dev, 1249 (struct mei_msg_hdr *) &dev->ext_msg_buf[0], 1250 (unsigned char *) &dev->ext_msg_buf[1], 1251 (dev->extra_write_index - 1) * sizeof(u32)); 1252 *slots -= dev->extra_write_index; 1253 dev->extra_write_index = 0; 1254 } 1255 if (dev->mei_state == MEI_ENABLED) { 1256 if (dev->wd_pending && 1257 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { 1258 if (mei_wd_send(dev)) 1259 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); 1260 else 1261 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) 1262 return -ENODEV; 1263 1264 dev->wd_pending = false; 1265 1266 if (dev->wd_timeout) { 1267 *slots -= (sizeof(struct mei_msg_hdr) + 1268 MEI_START_WD_DATA_SIZE + 3) / 4; 1269 dev->wd_due_counter = 2; 1270 } else { 1271 *slots -= (sizeof(struct mei_msg_hdr) + 1272 MEI_WD_PARAMS_SIZE + 3) / 4; 1273 dev->wd_due_counter = 0; 1274 } 1275 1276 } 1277 } 1278 if (dev->stop) 1279 return -ENODEV; 1280 1281 /* complete control write list CB */ 1282 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); 1283 list_for_each_entry_safe(pos, next, 1284 &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) { 1285 cl = (struct mei_cl *) pos->file_private; 1286 if (!cl) { 1287 list_del(&pos->cb_list); 1288 return -ENODEV; 1289 } 1290 switch (pos->major_file_operations) { 1291 case MEI_CLOSE: 1292 /* send disconnect message */ 1293 ret = _mei_irq_thread_close(dev, slots, pos, cl, cmpl_list); 1294 if (ret) 1295 return ret; 1296 1297 break; 1298 case MEI_READ: 1299 /* send flow control message */ 1300 ret = _mei_irq_thread_read(dev, slots, pos, cl, cmpl_list); 1301 if (ret) 1302 return ret; 1303 1304 break; 1305 case MEI_IOCTL: 1306 /* connect message */ 1307 if (mei_other_client_is_connecting(dev, cl)) 1308 continue; 1309 ret = _mei_irq_thread_ioctl(dev, slots, pos, cl, cmpl_list); 1310 if (ret) 1311 return ret; 1312 1313 break; 1314 1315 default: 1316 BUG(); 1317 } 1318 1319 } 1320 /* complete write list CB */ 1321 dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); 1322 list_for_each_entry_safe(pos, next, 1323 &dev->write_list.mei_cb.cb_list, cb_list) { 1324 cl = (struct mei_cl *)pos->file_private; 1325 if (cl == NULL) 1326 continue; 1327 1328 if (cl != &dev->iamthif_cl) { 1329 if (!mei_flow_ctrl_creds(dev, cl)) { 1330 dev_dbg(&dev->pdev->dev, 1331 "No flow control" 1332 " credentials for client" 1333 " %d, not sending.\n", 1334 cl->host_client_id); 1335 continue; 1336 } 1337 ret = _mei_irq_thread_cmpl(dev, slots, 1338 pos, 1339 cl, cmpl_list); 1340 if (ret) 1341 return ret; 1342 1343 } else if (cl == &dev->iamthif_cl) { 1344 /* IAMTHIF IOCTL */ 1345 dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n"); 1346 if (!mei_flow_ctrl_creds(dev, cl)) { 1347 dev_dbg(&dev->pdev->dev, 1348 "No flow control" 1349 " credentials for amthi" 1350 " client %d.\n", 1351 cl->host_client_id); 1352 continue; 1353 } 1354 ret = _mei_irq_thread_cmpl_iamthif(dev, 1355 slots, 1356 pos, 1357 cl, 1358 cmpl_list); 1359 if (ret) 1360 return ret; 1361 1362 } 1363 1364 } 1365 return 0; 1366} 1367 1368 1369 1370/** 1371 * mei_timer - timer function. 1372 * 1373 * @work: pointer to the work_struct structure 1374 * 1375 * NOTE: This function is called by timer interrupt work 1376 */ 1377void mei_timer(struct work_struct *work) 1378{ 1379 unsigned long timeout; 1380 struct mei_cl *cl_pos = NULL; 1381 struct mei_cl *cl_next = NULL; 1382 struct list_head *amthi_complete_list = NULL; 1383 struct mei_cl_cb *cb_pos = NULL; 1384 struct mei_cl_cb *cb_next = NULL; 1385 1386 struct mei_device *dev = container_of(work, 1387 struct mei_device, timer_work.work); 1388 1389 1390 mutex_lock(&dev->device_lock); 1391 if (dev->mei_state != MEI_ENABLED) { 1392 if (dev->mei_state == MEI_INIT_CLIENTS) { 1393 if (dev->init_clients_timer) { 1394 if (--dev->init_clients_timer == 0) { 1395 dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n", 1396 dev->init_clients_state); 1397 mei_reset(dev, 1); 1398 } 1399 } 1400 } 1401 goto out; 1402 } 1403 /*** connect/disconnect timeouts ***/ 1404 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 1405 if (cl_pos->timer_count) { 1406 if (--cl_pos->timer_count == 0) { 1407 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n"); 1408 mei_reset(dev, 1); 1409 goto out; 1410 } 1411 } 1412 } 1413 1414 if (dev->iamthif_stall_timer) { 1415 if (--dev->iamthif_stall_timer == 0) { 1416 dev_dbg(&dev->pdev->dev, "resetting because of hang to amthi.\n"); 1417 mei_reset(dev, 1); 1418 dev->iamthif_msg_buf_size = 0; 1419 dev->iamthif_msg_buf_index = 0; 1420 dev->iamthif_canceled = false; 1421 dev->iamthif_ioctl = true; 1422 dev->iamthif_state = MEI_IAMTHIF_IDLE; 1423 dev->iamthif_timer = 0; 1424 1425 if (dev->iamthif_current_cb) 1426 mei_free_cb_private(dev->iamthif_current_cb); 1427 1428 dev->iamthif_file_object = NULL; 1429 dev->iamthif_current_cb = NULL; 1430 mei_run_next_iamthif_cmd(dev); 1431 } 1432 } 1433 1434 if (dev->iamthif_timer) { 1435 1436 timeout = dev->iamthif_timer + 1437 msecs_to_jiffies(IAMTHIF_READ_TIMER); 1438 1439 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", 1440 dev->iamthif_timer); 1441 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout); 1442 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies); 1443 if (time_after(jiffies, timeout)) { 1444 /* 1445 * User didn't read the AMTHI data on time (15sec) 1446 * freeing AMTHI for other requests 1447 */ 1448 1449 dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n"); 1450 1451 amthi_complete_list = &dev->amthi_read_complete_list. 1452 mei_cb.cb_list; 1453 1454 list_for_each_entry_safe(cb_pos, cb_next, amthi_complete_list, cb_list) { 1455 1456 cl_pos = cb_pos->file_object->private_data; 1457 1458 /* Finding the AMTHI entry. */ 1459 if (cl_pos == &dev->iamthif_cl) 1460 list_del(&cb_pos->cb_list); 1461 } 1462 if (dev->iamthif_current_cb) 1463 mei_free_cb_private(dev->iamthif_current_cb); 1464 1465 dev->iamthif_file_object->private_data = NULL; 1466 dev->iamthif_file_object = NULL; 1467 dev->iamthif_current_cb = NULL; 1468 dev->iamthif_timer = 0; 1469 mei_run_next_iamthif_cmd(dev); 1470 1471 } 1472 } 1473out: 1474 schedule_delayed_work(&dev->timer_work, 2 * HZ); 1475 mutex_unlock(&dev->device_lock); 1476} 1477 1478/** 1479 * mei_interrupt_thread_handler - function called after ISR to handle the interrupt 1480 * processing. 1481 * 1482 * @irq: The irq number 1483 * @dev_id: pointer to the device structure 1484 * 1485 * returns irqreturn_t 1486 * 1487 */ 1488irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) 1489{ 1490 struct mei_device *dev = (struct mei_device *) dev_id; 1491 struct mei_io_list complete_list; 1492 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 1493 struct mei_cl *cl; 1494 s32 slots; 1495 int rets; 1496 bool bus_message_received; 1497 1498 1499 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); 1500 /* initialize our complete list */ 1501 mutex_lock(&dev->device_lock); 1502 mei_io_list_init(&complete_list); 1503 dev->host_hw_state = mei_hcsr_read(dev); 1504 1505 /* Ack the interrupt here 1506 * In case of MSI we don't go through the quick handler */ 1507 if (pci_dev_msi_enabled(dev->pdev)) 1508 mei_reg_write(dev, H_CSR, dev->host_hw_state); 1509 1510 dev->me_hw_state = mei_mecsr_read(dev); 1511 1512 /* check if ME wants a reset */ 1513 if ((dev->me_hw_state & ME_RDY_HRA) == 0 && 1514 dev->mei_state != MEI_RESETING && 1515 dev->mei_state != MEI_INITIALIZING) { 1516 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 1517 mei_reset(dev, 1); 1518 mutex_unlock(&dev->device_lock); 1519 return IRQ_HANDLED; 1520 } 1521 1522 /* check if we need to start the dev */ 1523 if ((dev->host_hw_state & H_RDY) == 0) { 1524 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { 1525 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); 1526 dev->host_hw_state |= (H_IE | H_IG | H_RDY); 1527 mei_hcsr_set(dev); 1528 dev->mei_state = MEI_INIT_CLIENTS; 1529 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); 1530 /* link is established 1531 * start sending messages. 1532 */ 1533 mei_host_start_message(dev); 1534 mutex_unlock(&dev->device_lock); 1535 return IRQ_HANDLED; 1536 } else { 1537 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 1538 mutex_unlock(&dev->device_lock); 1539 return IRQ_HANDLED; 1540 } 1541 } 1542 /* check slots available for reading */ 1543 slots = mei_count_full_read_slots(dev); 1544 dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n", 1545 slots, dev->extra_write_index); 1546 while (slots > 0 && !dev->extra_write_index) { 1547 dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n", 1548 slots, dev->extra_write_index); 1549 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); 1550 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); 1551 if (rets) 1552 goto end; 1553 } 1554 rets = mei_irq_thread_write_handler(&complete_list, dev, &slots); 1555end: 1556 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); 1557 dev->host_hw_state = mei_hcsr_read(dev); 1558 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev); 1559 1560 bus_message_received = false; 1561 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { 1562 dev_dbg(&dev->pdev->dev, "received waiting bus message\n"); 1563 bus_message_received = true; 1564 } 1565 mutex_unlock(&dev->device_lock); 1566 if (bus_message_received) { 1567 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n"); 1568 wake_up_interruptible(&dev->wait_recvd_msg); 1569 bus_message_received = false; 1570 } 1571 if (list_empty(&complete_list.mei_cb.cb_list)) 1572 return IRQ_HANDLED; 1573 1574 1575 list_for_each_entry_safe(cb_pos, cb_next, 1576 &complete_list.mei_cb.cb_list, cb_list) { 1577 cl = (struct mei_cl *)cb_pos->file_private; 1578 list_del(&cb_pos->cb_list); 1579 if (cl) { 1580 if (cl != &dev->iamthif_cl) { 1581 dev_dbg(&dev->pdev->dev, "completing call back.\n"); 1582 _mei_cmpl(cl, cb_pos); 1583 cb_pos = NULL; 1584 } else if (cl == &dev->iamthif_cl) { 1585 _mei_cmpl_iamthif(dev, cb_pos); 1586 } 1587 } 1588 } 1589 return IRQ_HANDLED; 1590} 1591