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