at v3.0 1624 lines 45 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 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; 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 = 0; 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 host_init_iamthif(dev); 400 return; 401 } 402 403 if (is_treat_specially_client(&(dev->iamthif_cl), rs)) { 404 dev->iamthif_state = MEI_IAMTHIF_IDLE; 405 return; 406 } 407 if (!dev->ctrl_rd_list.status && 408 !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) { 409 list_for_each_entry_safe(cb_pos, cb_next, 410 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) { 411 cl = (struct mei_cl *)cb_pos->file_private; 412 if (!cl) { 413 list_del(&cb_pos->cb_list); 414 return; 415 } 416 if (MEI_IOCTL == cb_pos->major_file_operations) { 417 if (is_treat_specially_client(cl, rs)) { 418 list_del(&cb_pos->cb_list); 419 cl->status = 0; 420 cl->timer_count = 0; 421 break; 422 } 423 } 424 } 425 } 426} 427 428/** 429 * mei_client_disconnect_response - disconnects from response irq routine 430 * 431 * @dev: the device structure 432 * @rs: disconnect response bus message 433 */ 434static void mei_client_disconnect_response(struct mei_device *dev, 435 struct hbm_client_connect_response *rs) 436{ 437 struct mei_cl *cl; 438 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 439 440 dev_dbg(&dev->pdev->dev, 441 "disconnect_response:\n" 442 "ME Client = %d\n" 443 "Host Client = %d\n" 444 "Status = %d\n", 445 rs->me_addr, 446 rs->host_addr, 447 rs->status); 448 449 if (!dev->ctrl_rd_list.status && 450 !list_empty(&dev->ctrl_rd_list.mei_cb.cb_list)) { 451 list_for_each_entry_safe(cb_pos, cb_next, 452 &dev->ctrl_rd_list.mei_cb.cb_list, cb_list) { 453 cl = (struct mei_cl *)cb_pos->file_private; 454 455 if (!cl) { 456 list_del(&cb_pos->cb_list); 457 return; 458 } 459 460 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n"); 461 if (cl->host_client_id == rs->host_addr && 462 cl->me_client_id == rs->me_addr) { 463 464 list_del(&cb_pos->cb_list); 465 if (!rs->status) 466 cl->state = MEI_FILE_DISCONNECTED; 467 468 cl->status = 0; 469 cl->timer_count = 0; 470 break; 471 } 472 } 473 } 474} 475 476/** 477 * same_flow_addr - tells if they have the same address. 478 * 479 * @file: private data of the file object. 480 * @flow: flow control. 481 * 482 * returns !=0, same; 0,not. 483 */ 484static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow) 485{ 486 return (cl->host_client_id == flow->host_addr && 487 cl->me_client_id == flow->me_addr); 488} 489 490/** 491 * add_single_flow_creds - adds single buffer credentials. 492 * 493 * @file: private data ot the file object. 494 * @flow: flow control. 495 */ 496static void add_single_flow_creds(struct mei_device *dev, 497 struct hbm_flow_control *flow) 498{ 499 struct mei_me_client *client; 500 int i; 501 502 for (i = 0; i < dev->num_mei_me_clients; i++) { 503 client = &dev->me_clients[i]; 504 if (client && flow->me_addr == client->client_id) { 505 if (client->props.single_recv_buf) { 506 client->mei_flow_ctrl_creds++; 507 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n", 508 flow->me_addr); 509 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n", 510 client->mei_flow_ctrl_creds); 511 } else { 512 BUG(); /* error in flow control */ 513 } 514 } 515 } 516} 517 518/** 519 * mei_client_flow_control_response - flow control response irq routine 520 * 521 * @dev: the device structure 522 * @flow_control: flow control response bus message 523 */ 524static void mei_client_flow_control_response(struct mei_device *dev, 525 struct hbm_flow_control *flow_control) 526{ 527 struct mei_cl *cl_pos = NULL; 528 struct mei_cl *cl_next = NULL; 529 530 if (!flow_control->host_addr) { 531 /* single receive buffer */ 532 add_single_flow_creds(dev, flow_control); 533 } else { 534 /* normal connection */ 535 list_for_each_entry_safe(cl_pos, cl_next, 536 &dev->file_list, link) { 537 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n"); 538 539 dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n", 540 cl_pos->host_client_id, 541 cl_pos->me_client_id); 542 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n", 543 flow_control->host_addr, 544 flow_control->me_addr); 545 if (same_flow_addr(cl_pos, flow_control)) { 546 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n", 547 flow_control->host_addr, 548 flow_control->me_addr); 549 cl_pos->mei_flow_ctrl_creds++; 550 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n", 551 cl_pos->mei_flow_ctrl_creds); 552 break; 553 } 554 } 555 } 556} 557 558/** 559 * same_disconn_addr - tells if they have the same address 560 * 561 * @file: private data of the file object. 562 * @disconn: disconnection request. 563 * 564 * returns !=0, same; 0,not. 565 */ 566static int same_disconn_addr(struct mei_cl *cl, 567 struct hbm_client_disconnect_request *disconn) 568{ 569 return (cl->host_client_id == disconn->host_addr && 570 cl->me_client_id == disconn->me_addr); 571} 572 573/** 574 * mei_client_disconnect_request - disconnects from request irq routine 575 * 576 * @dev: the device structure. 577 * @disconnect_req: disconnect request bus message. 578 */ 579static void mei_client_disconnect_request(struct mei_device *dev, 580 struct hbm_client_disconnect_request *disconnect_req) 581{ 582 struct mei_msg_hdr *mei_hdr; 583 struct hbm_client_connect_response *disconnect_res; 584 struct mei_cl *cl_pos = NULL; 585 struct mei_cl *cl_next = NULL; 586 587 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 588 if (same_disconn_addr(cl_pos, disconnect_req)) { 589 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n", 590 disconnect_req->host_addr, 591 disconnect_req->me_addr); 592 cl_pos->state = MEI_FILE_DISCONNECTED; 593 cl_pos->timer_count = 0; 594 if (cl_pos == &dev->wd_cl) { 595 dev->wd_due_counter = 0; 596 dev->wd_pending = 0; 597 } else if (cl_pos == &dev->iamthif_cl) 598 dev->iamthif_timer = 0; 599 600 /* prepare disconnect response */ 601 mei_hdr = 602 (struct mei_msg_hdr *) &dev->ext_msg_buf[0]; 603 mei_hdr->host_addr = 0; 604 mei_hdr->me_addr = 0; 605 mei_hdr->length = 606 sizeof(struct hbm_client_connect_response); 607 mei_hdr->msg_complete = 1; 608 mei_hdr->reserved = 0; 609 610 disconnect_res = 611 (struct hbm_client_connect_response *) 612 &dev->ext_msg_buf[1]; 613 disconnect_res->host_addr = cl_pos->host_client_id; 614 disconnect_res->me_addr = cl_pos->me_client_id; 615 *(u8 *) (&disconnect_res->cmd) = 616 CLIENT_DISCONNECT_RES_CMD; 617 disconnect_res->status = 0; 618 dev->extra_write_index = 2; 619 break; 620 } 621 } 622} 623 624 625/** 626 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to 627 * handle the read bus message cmd processing. 628 * 629 * @dev: the device structure 630 * @mei_hdr: header of bus message 631 */ 632static void mei_irq_thread_read_bus_message(struct mei_device *dev, 633 struct mei_msg_hdr *mei_hdr) 634{ 635 struct mei_bus_message *mei_msg; 636 struct hbm_host_version_response *version_res; 637 struct hbm_client_connect_response *connect_res; 638 struct hbm_client_connect_response *disconnect_res; 639 struct hbm_flow_control *flow_control; 640 struct hbm_props_response *props_res; 641 struct hbm_host_enum_response *enum_res; 642 struct hbm_client_disconnect_request *disconnect_req; 643 struct hbm_host_stop_request *host_stop_req; 644 645 unsigned char *buffer; 646 647 /* read the message to our buffer */ 648 buffer = (unsigned char *) dev->rd_msg_buf; 649 BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); 650 mei_read_slots(dev, buffer, mei_hdr->length); 651 mei_msg = (struct mei_bus_message *) buffer; 652 653 switch (*(u8 *) mei_msg) { 654 case HOST_START_RES_CMD: 655 version_res = (struct hbm_host_version_response *) mei_msg; 656 if (version_res->host_version_supported) { 657 dev->version.major_version = HBM_MAJOR_VERSION; 658 dev->version.minor_version = HBM_MINOR_VERSION; 659 if (dev->mei_state == MEI_INIT_CLIENTS && 660 dev->init_clients_state == MEI_START_MESSAGE) { 661 dev->init_clients_timer = 0; 662 host_enum_clients_message(dev); 663 } else { 664 dev->recvd_msg = 0; 665 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n"); 666 mei_reset(dev, 1); 667 return; 668 } 669 } else { 670 dev->version = version_res->me_max_version; 671 /* send stop message */ 672 mei_hdr->host_addr = 0; 673 mei_hdr->me_addr = 0; 674 mei_hdr->length = sizeof(struct hbm_host_stop_request); 675 mei_hdr->msg_complete = 1; 676 mei_hdr->reserved = 0; 677 678 host_stop_req = (struct hbm_host_stop_request *) 679 &dev->wr_msg_buf[1]; 680 681 memset(host_stop_req, 682 0, 683 sizeof(struct hbm_host_stop_request)); 684 host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD; 685 host_stop_req->reason = DRIVER_STOP_REQUEST; 686 mei_write_message(dev, mei_hdr, 687 (unsigned char *) (host_stop_req), 688 mei_hdr->length); 689 dev_dbg(&dev->pdev->dev, "version mismatch.\n"); 690 return; 691 } 692 693 dev->recvd_msg = 1; 694 dev_dbg(&dev->pdev->dev, "host start response message received.\n"); 695 break; 696 697 case CLIENT_CONNECT_RES_CMD: 698 connect_res = 699 (struct hbm_client_connect_response *) mei_msg; 700 mei_client_connect_response(dev, connect_res); 701 dev_dbg(&dev->pdev->dev, "client connect response message received.\n"); 702 wake_up(&dev->wait_recvd_msg); 703 break; 704 705 case CLIENT_DISCONNECT_RES_CMD: 706 disconnect_res = 707 (struct hbm_client_connect_response *) mei_msg; 708 mei_client_disconnect_response(dev, disconnect_res); 709 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n"); 710 wake_up(&dev->wait_recvd_msg); 711 break; 712 713 case MEI_FLOW_CONTROL_CMD: 714 flow_control = (struct hbm_flow_control *) mei_msg; 715 mei_client_flow_control_response(dev, flow_control); 716 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n"); 717 break; 718 719 case HOST_CLIENT_PROPERTIES_RES_CMD: 720 props_res = (struct hbm_props_response *)mei_msg; 721 if (props_res->status || !dev->me_clients) { 722 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); 723 mei_reset(dev, 1); 724 return; 725 } 726 if (dev->me_clients[dev->me_client_presentation_num] 727 .client_id == props_res->address) { 728 729 dev->me_clients[dev->me_client_presentation_num].props 730 = props_res->client_properties; 731 732 if (dev->mei_state == MEI_INIT_CLIENTS && 733 dev->init_clients_state == 734 MEI_CLIENT_PROPERTIES_MESSAGE) { 735 dev->me_client_index++; 736 dev->me_client_presentation_num++; 737 host_client_properties(dev); 738 } else { 739 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message"); 740 mei_reset(dev, 1); 741 return; 742 } 743 } else { 744 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message for wrong client ID\n"); 745 mei_reset(dev, 1); 746 return; 747 } 748 break; 749 750 case HOST_ENUM_RES_CMD: 751 enum_res = (struct hbm_host_enum_response *) mei_msg; 752 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); 753 if (dev->mei_state == MEI_INIT_CLIENTS && 754 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { 755 dev->init_clients_timer = 0; 756 dev->me_client_presentation_num = 0; 757 dev->me_client_index = 0; 758 allocate_me_clients_storage(dev); 759 dev->init_clients_state = 760 MEI_CLIENT_PROPERTIES_MESSAGE; 761 host_client_properties(dev); 762 } else { 763 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); 764 mei_reset(dev, 1); 765 return; 766 } 767 break; 768 769 case HOST_STOP_RES_CMD: 770 dev->mei_state = MEI_DISABLED; 771 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n"); 772 mei_reset(dev, 1); 773 break; 774 775 case CLIENT_DISCONNECT_REQ_CMD: 776 /* search for client */ 777 disconnect_req = 778 (struct hbm_client_disconnect_request *) mei_msg; 779 mei_client_disconnect_request(dev, disconnect_req); 780 break; 781 782 case ME_STOP_REQ_CMD: 783 /* prepare stop request */ 784 mei_hdr = (struct mei_msg_hdr *) &dev->ext_msg_buf[0]; 785 mei_hdr->host_addr = 0; 786 mei_hdr->me_addr = 0; 787 mei_hdr->length = sizeof(struct hbm_host_stop_request); 788 mei_hdr->msg_complete = 1; 789 mei_hdr->reserved = 0; 790 host_stop_req = 791 (struct hbm_host_stop_request *) &dev->ext_msg_buf[1]; 792 memset(host_stop_req, 0, sizeof(struct hbm_host_stop_request)); 793 host_stop_req->cmd.cmd = HOST_STOP_REQ_CMD; 794 host_stop_req->reason = DRIVER_STOP_REQUEST; 795 host_stop_req->reserved[0] = 0; 796 host_stop_req->reserved[1] = 0; 797 dev->extra_write_index = 2; 798 break; 799 800 default: 801 BUG(); 802 break; 803 804 } 805} 806 807 808/** 809 * _mei_hb_read - processes read related operation. 810 * 811 * @dev: the device structure. 812 * @slots: free slots. 813 * @cb_pos: callback block. 814 * @cl: private data of the file object. 815 * @cmpl_list: complete list. 816 * 817 * returns 0, OK; otherwise, error. 818 */ 819static int _mei_irq_thread_read(struct mei_device *dev, s32 *slots, 820 struct mei_cl_cb *cb_pos, 821 struct mei_cl *cl, 822 struct mei_io_list *cmpl_list) 823{ 824 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 825 sizeof(struct hbm_flow_control))) { 826 *slots -= (sizeof(struct mei_msg_hdr) + 827 sizeof(struct hbm_flow_control) + 3) / 4; 828 if (!mei_send_flow_control(dev, cl)) { 829 cl->status = -ENODEV; 830 cb_pos->information = 0; 831 list_move_tail(&cb_pos->cb_list, 832 &cmpl_list->mei_cb.cb_list); 833 return -ENODEV; 834 } else { 835 list_move_tail(&cb_pos->cb_list, 836 &dev->read_list.mei_cb.cb_list); 837 } 838 } else { 839 /* return the cancel routine */ 840 list_del(&cb_pos->cb_list); 841 return -EBADMSG; 842 } 843 844 return 0; 845} 846 847 848/** 849 * _mei_irq_thread_ioctl - processes ioctl related operation. 850 * 851 * @dev: the device structure. 852 * @slots: free slots. 853 * @cb_pos: callback block. 854 * @cl: private data of the file object. 855 * @cmpl_list: complete list. 856 * 857 * returns 0, OK; otherwise, error. 858 */ 859static int _mei_irq_thread_ioctl(struct mei_device *dev, s32 *slots, 860 struct mei_cl_cb *cb_pos, 861 struct mei_cl *cl, 862 struct mei_io_list *cmpl_list) 863{ 864 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 865 sizeof(struct hbm_client_connect_request))) { 866 cl->state = MEI_FILE_CONNECTING; 867 *slots -= (sizeof(struct mei_msg_hdr) + 868 sizeof(struct hbm_client_connect_request) + 3) / 4; 869 if (!mei_connect(dev, cl)) { 870 cl->status = -ENODEV; 871 cb_pos->information = 0; 872 list_del(&cb_pos->cb_list); 873 return -ENODEV; 874 } else { 875 list_move_tail(&cb_pos->cb_list, 876 &dev->ctrl_rd_list.mei_cb.cb_list); 877 cl->timer_count = MEI_CONNECT_TIMEOUT; 878 } 879 } else { 880 /* return the cancel routine */ 881 list_del(&cb_pos->cb_list); 882 return -EBADMSG; 883 } 884 885 return 0; 886} 887 888/** 889 * _mei_irq_thread_cmpl - processes completed and no-iamthif operation. 890 * 891 * @dev: the device structure. 892 * @slots: free slots. 893 * @cb_pos: callback block. 894 * @cl: private data of the file object. 895 * @cmpl_list: complete list. 896 * 897 * returns 0, OK; otherwise, error. 898 */ 899static int _mei_irq_thread_cmpl(struct mei_device *dev, s32 *slots, 900 struct mei_cl_cb *cb_pos, 901 struct mei_cl *cl, 902 struct mei_io_list *cmpl_list) 903{ 904 struct mei_msg_hdr *mei_hdr; 905 906 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 907 (cb_pos->request_buffer.size - 908 cb_pos->information))) { 909 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 910 mei_hdr->host_addr = cl->host_client_id; 911 mei_hdr->me_addr = cl->me_client_id; 912 mei_hdr->length = cb_pos->request_buffer.size - 913 cb_pos->information; 914 mei_hdr->msg_complete = 1; 915 mei_hdr->reserved = 0; 916 dev_dbg(&dev->pdev->dev, "cb_pos->request_buffer.size =%d" 917 "mei_hdr->msg_complete = %d\n", 918 cb_pos->request_buffer.size, 919 mei_hdr->msg_complete); 920 dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n", 921 cb_pos->information); 922 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 923 mei_hdr->length); 924 *slots -= (sizeof(struct mei_msg_hdr) + 925 mei_hdr->length + 3) / 4; 926 if (!mei_write_message(dev, mei_hdr, 927 (unsigned char *) 928 (cb_pos->request_buffer.data + 929 cb_pos->information), 930 mei_hdr->length)) { 931 cl->status = -ENODEV; 932 list_move_tail(&cb_pos->cb_list, 933 &cmpl_list->mei_cb.cb_list); 934 return -ENODEV; 935 } else { 936 if (mei_flow_ctrl_reduce(dev, cl)) 937 return -ENODEV; 938 cl->status = 0; 939 cb_pos->information += mei_hdr->length; 940 list_move_tail(&cb_pos->cb_list, 941 &dev->write_waiting_list.mei_cb.cb_list); 942 } 943 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { 944 /* buffer is still empty */ 945 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 946 mei_hdr->host_addr = cl->host_client_id; 947 mei_hdr->me_addr = cl->me_client_id; 948 mei_hdr->length = 949 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); 950 mei_hdr->msg_complete = 0; 951 mei_hdr->reserved = 0; 952 953 (*slots) -= (sizeof(struct mei_msg_hdr) + 954 mei_hdr->length + 3) / 4; 955 if (!mei_write_message(dev, mei_hdr, 956 (unsigned char *) 957 (cb_pos->request_buffer.data + 958 cb_pos->information), 959 mei_hdr->length)) { 960 cl->status = -ENODEV; 961 list_move_tail(&cb_pos->cb_list, 962 &cmpl_list->mei_cb.cb_list); 963 return -ENODEV; 964 } else { 965 cb_pos->information += mei_hdr->length; 966 dev_dbg(&dev->pdev->dev, 967 "cb_pos->request_buffer.size =%d" 968 " mei_hdr->msg_complete = %d\n", 969 cb_pos->request_buffer.size, 970 mei_hdr->msg_complete); 971 dev_dbg(&dev->pdev->dev, "cb_pos->information =%lu\n", 972 cb_pos->information); 973 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 974 mei_hdr->length); 975 } 976 return -EMSGSIZE; 977 } else { 978 return -EBADMSG; 979 } 980 981 return 0; 982} 983 984/** 985 * _mei_irq_thread_cmpl_iamthif - processes completed iamthif operation. 986 * 987 * @dev: the device structure. 988 * @slots: free slots. 989 * @cb_pos: callback block. 990 * @cl: private data of the file object. 991 * @cmpl_list: complete list. 992 * 993 * returns 0, OK; otherwise, error. 994 */ 995static int _mei_irq_thread_cmpl_iamthif(struct mei_device *dev, s32 *slots, 996 struct mei_cl_cb *cb_pos, 997 struct mei_cl *cl, 998 struct mei_io_list *cmpl_list) 999{ 1000 struct mei_msg_hdr *mei_hdr; 1001 1002 if ((*slots * sizeof(u32)) >= (sizeof(struct mei_msg_hdr) + 1003 dev->iamthif_msg_buf_size - 1004 dev->iamthif_msg_buf_index)) { 1005 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 1006 mei_hdr->host_addr = cl->host_client_id; 1007 mei_hdr->me_addr = cl->me_client_id; 1008 mei_hdr->length = dev->iamthif_msg_buf_size - 1009 dev->iamthif_msg_buf_index; 1010 mei_hdr->msg_complete = 1; 1011 mei_hdr->reserved = 0; 1012 1013 *slots -= (sizeof(struct mei_msg_hdr) + 1014 mei_hdr->length + 3) / 4; 1015 1016 if (!mei_write_message(dev, mei_hdr, 1017 (dev->iamthif_msg_buf + 1018 dev->iamthif_msg_buf_index), 1019 mei_hdr->length)) { 1020 dev->iamthif_state = MEI_IAMTHIF_IDLE; 1021 cl->status = -ENODEV; 1022 list_del(&cb_pos->cb_list); 1023 return -ENODEV; 1024 } else { 1025 if (mei_flow_ctrl_reduce(dev, cl)) 1026 return -ENODEV; 1027 dev->iamthif_msg_buf_index += mei_hdr->length; 1028 cb_pos->information = dev->iamthif_msg_buf_index; 1029 cl->status = 0; 1030 dev->iamthif_state = MEI_IAMTHIF_FLOW_CONTROL; 1031 dev->iamthif_flow_control_pending = 1; 1032 /* save iamthif cb sent to amthi client */ 1033 dev->iamthif_current_cb = cb_pos; 1034 list_move_tail(&cb_pos->cb_list, 1035 &dev->write_waiting_list.mei_cb.cb_list); 1036 1037 } 1038 } else if (*slots == ((dev->host_hw_state & H_CBD) >> 24)) { 1039 /* buffer is still empty */ 1040 mei_hdr = (struct mei_msg_hdr *) &dev->wr_msg_buf[0]; 1041 mei_hdr->host_addr = cl->host_client_id; 1042 mei_hdr->me_addr = cl->me_client_id; 1043 mei_hdr->length = 1044 (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); 1045 mei_hdr->msg_complete = 0; 1046 mei_hdr->reserved = 0; 1047 1048 *slots -= (sizeof(struct mei_msg_hdr) + 1049 mei_hdr->length + 3) / 4; 1050 1051 if (!mei_write_message(dev, mei_hdr, 1052 (dev->iamthif_msg_buf + 1053 dev->iamthif_msg_buf_index), 1054 mei_hdr->length)) { 1055 cl->status = -ENODEV; 1056 list_del(&cb_pos->cb_list); 1057 } else { 1058 dev->iamthif_msg_buf_index += mei_hdr->length; 1059 } 1060 return -EMSGSIZE; 1061 } else { 1062 return -EBADMSG; 1063 } 1064 1065 return 0; 1066} 1067 1068/** 1069 * mei_irq_thread_read_handler - bottom half read routine after ISR to 1070 * handle the read processing. 1071 * 1072 * @cmpl_list: An instance of our list structure 1073 * @dev: the device structure 1074 * @slots: slots to read. 1075 * 1076 * returns 0 on success, <0 on failure. 1077 */ 1078static int mei_irq_thread_read_handler(struct mei_io_list *cmpl_list, 1079 struct mei_device *dev, 1080 s32 *slots) 1081{ 1082 struct mei_msg_hdr *mei_hdr; 1083 struct mei_cl *cl_pos = NULL; 1084 struct mei_cl *cl_next = NULL; 1085 int ret = 0; 1086 1087 if (!dev->rd_msg_hdr) { 1088 dev->rd_msg_hdr = mei_mecbrw_read(dev); 1089 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 1090 (*slots)--; 1091 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 1092 } 1093 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr; 1094 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length); 1095 1096 if (mei_hdr->reserved || !dev->rd_msg_hdr) { 1097 dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); 1098 ret = -EBADMSG; 1099 goto end; 1100 } 1101 1102 if (mei_hdr->host_addr || mei_hdr->me_addr) { 1103 list_for_each_entry_safe(cl_pos, cl_next, 1104 &dev->file_list, link) { 1105 dev_dbg(&dev->pdev->dev, 1106 "list_for_each_entry_safe read host" 1107 " client = %d, ME client = %d\n", 1108 cl_pos->host_client_id, 1109 cl_pos->me_client_id); 1110 if (cl_pos->host_client_id == mei_hdr->host_addr && 1111 cl_pos->me_client_id == mei_hdr->me_addr) 1112 break; 1113 } 1114 1115 if (&cl_pos->link == &dev->file_list) { 1116 dev_dbg(&dev->pdev->dev, "corrupted message header\n"); 1117 ret = -EBADMSG; 1118 goto end; 1119 } 1120 } 1121 if (((*slots) * sizeof(u32)) < mei_hdr->length) { 1122 dev_dbg(&dev->pdev->dev, 1123 "we can't read the message slots =%08x.\n", 1124 *slots); 1125 /* we can't read the message */ 1126 ret = -ERANGE; 1127 goto end; 1128 } 1129 1130 /* decide where to read the message too */ 1131 if (!mei_hdr->host_addr) { 1132 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n"); 1133 mei_irq_thread_read_bus_message(dev, mei_hdr); 1134 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n"); 1135 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 1136 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && 1137 (dev->iamthif_state == MEI_IAMTHIF_READING)) { 1138 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); 1139 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 1140 mei_hdr->length); 1141 ret = mei_irq_thread_read_amthi_message(cmpl_list, 1142 dev, mei_hdr); 1143 if (ret) 1144 goto end; 1145 1146 } else { 1147 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n"); 1148 ret = mei_irq_thread_read_client_message(cmpl_list, 1149 dev, mei_hdr); 1150 if (ret) 1151 goto end; 1152 1153 } 1154 1155 /* reset the number of slots and header */ 1156 *slots = mei_count_full_read_slots(dev); 1157 dev->rd_msg_hdr = 0; 1158 1159 if (*slots == -EOVERFLOW) { 1160 /* overflow - reset */ 1161 dev_dbg(&dev->pdev->dev, "resetting due to slots overflow.\n"); 1162 /* set the event since message has been read */ 1163 ret = -ERANGE; 1164 goto end; 1165 } 1166end: 1167 return ret; 1168} 1169 1170 1171/** 1172 * mei_irq_thread_write_handler - bottom half write routine after 1173 * ISR to handle the write processing. 1174 * 1175 * @cmpl_list: An instance of our list structure 1176 * @dev: the device structure 1177 * @slots: slots to write. 1178 * 1179 * returns 0 on success, <0 on failure. 1180 */ 1181static int mei_irq_thread_write_handler(struct mei_io_list *cmpl_list, 1182 struct mei_device *dev, 1183 s32 *slots) 1184{ 1185 1186 struct mei_cl *cl; 1187 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 1188 struct mei_io_list *list; 1189 int ret; 1190 1191 if (!mei_host_buffer_is_empty(dev)) { 1192 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); 1193 return 0; 1194 } 1195 dev->write_hang = -1; 1196 *slots = mei_count_empty_write_slots(dev); 1197 /* complete all waiting for write CB */ 1198 dev_dbg(&dev->pdev->dev, "complete all waiting for write cb.\n"); 1199 1200 list = &dev->write_waiting_list; 1201 if (!list->status && !list_empty(&list->mei_cb.cb_list)) { 1202 list_for_each_entry_safe(cb_pos, cb_next, 1203 &list->mei_cb.cb_list, cb_list) { 1204 cl = (struct mei_cl *)cb_pos->file_private; 1205 if (cl) { 1206 cl->status = 0; 1207 list_del(&cb_pos->cb_list); 1208 if (MEI_WRITING == cl->writing_state && 1209 (cb_pos->major_file_operations == 1210 MEI_WRITE) && 1211 (cl != &dev->iamthif_cl)) { 1212 dev_dbg(&dev->pdev->dev, 1213 "MEI WRITE COMPLETE\n"); 1214 cl->writing_state = 1215 MEI_WRITE_COMPLETE; 1216 list_add_tail(&cb_pos->cb_list, 1217 &cmpl_list->mei_cb.cb_list); 1218 } 1219 if (cl == &dev->iamthif_cl) { 1220 dev_dbg(&dev->pdev->dev, "check iamthif flow control.\n"); 1221 if (dev->iamthif_flow_control_pending) { 1222 ret = 1223 _mei_irq_thread_iamthif_read( 1224 dev, slots); 1225 if (ret) 1226 return ret; 1227 } 1228 } 1229 } 1230 1231 } 1232 } 1233 1234 if (dev->stop && !dev->wd_pending) { 1235 dev->wd_stopped = 1; 1236 wake_up_interruptible(&dev->wait_stop_wd); 1237 return 0; 1238 } 1239 1240 if (dev->extra_write_index) { 1241 dev_dbg(&dev->pdev->dev, "extra_write_index =%d.\n", 1242 dev->extra_write_index); 1243 mei_write_message(dev, 1244 (struct mei_msg_hdr *) &dev->ext_msg_buf[0], 1245 (unsigned char *) &dev->ext_msg_buf[1], 1246 (dev->extra_write_index - 1) * sizeof(u32)); 1247 *slots -= dev->extra_write_index; 1248 dev->extra_write_index = 0; 1249 } 1250 if (dev->mei_state == MEI_ENABLED) { 1251 if (dev->wd_pending && 1252 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { 1253 if (mei_wd_send(dev)) 1254 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); 1255 else 1256 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) 1257 return -ENODEV; 1258 1259 dev->wd_pending = 0; 1260 1261 if (dev->wd_timeout) { 1262 *slots -= (sizeof(struct mei_msg_hdr) + 1263 MEI_START_WD_DATA_SIZE + 3) / 4; 1264 dev->wd_due_counter = 2; 1265 } else { 1266 *slots -= (sizeof(struct mei_msg_hdr) + 1267 MEI_WD_PARAMS_SIZE + 3) / 4; 1268 dev->wd_due_counter = 0; 1269 } 1270 1271 } 1272 } 1273 if (dev->stop) 1274 return ~ENODEV; 1275 1276 /* complete control write list CB */ 1277 if (!dev->ctrl_wr_list.status) { 1278 /* complete control write list CB */ 1279 dev_dbg(&dev->pdev->dev, "complete control write list cb.\n"); 1280 list_for_each_entry_safe(cb_pos, cb_next, 1281 &dev->ctrl_wr_list.mei_cb.cb_list, cb_list) { 1282 cl = (struct mei_cl *) 1283 cb_pos->file_private; 1284 if (!cl) { 1285 list_del(&cb_pos->cb_list); 1286 return -ENODEV; 1287 } 1288 switch (cb_pos->major_file_operations) { 1289 case MEI_CLOSE: 1290 /* send disconnect message */ 1291 ret = _mei_irq_thread_close(dev, slots, 1292 cb_pos, cl, cmpl_list); 1293 if (ret) 1294 return ret; 1295 1296 break; 1297 case MEI_READ: 1298 /* send flow control message */ 1299 ret = _mei_irq_thread_read(dev, slots, 1300 cb_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, 1308 cl)) 1309 continue; 1310 ret = _mei_irq_thread_ioctl(dev, slots, 1311 cb_pos, cl, cmpl_list); 1312 if (ret) 1313 return ret; 1314 1315 break; 1316 1317 default: 1318 BUG(); 1319 } 1320 1321 } 1322 } 1323 /* complete write list CB */ 1324 if (!dev->write_list.status && 1325 !list_empty(&dev->write_list.mei_cb.cb_list)) { 1326 dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); 1327 list_for_each_entry_safe(cb_pos, cb_next, 1328 &dev->write_list.mei_cb.cb_list, cb_list) { 1329 cl = (struct mei_cl *)cb_pos->file_private; 1330 1331 if (cl) { 1332 if (cl != &dev->iamthif_cl) { 1333 if (!mei_flow_ctrl_creds(dev, 1334 cl)) { 1335 dev_dbg(&dev->pdev->dev, 1336 "No flow control" 1337 " credentials for client" 1338 " %d, not sending.\n", 1339 cl->host_client_id); 1340 continue; 1341 } 1342 ret = _mei_irq_thread_cmpl(dev, slots, 1343 cb_pos, 1344 cl, cmpl_list); 1345 if (ret) 1346 return ret; 1347 1348 } else if (cl == &dev->iamthif_cl) { 1349 /* IAMTHIF IOCTL */ 1350 dev_dbg(&dev->pdev->dev, "complete amthi write cb.\n"); 1351 if (!mei_flow_ctrl_creds(dev, 1352 cl)) { 1353 dev_dbg(&dev->pdev->dev, 1354 "No flow control" 1355 " credentials for amthi" 1356 " client %d.\n", 1357 cl->host_client_id); 1358 continue; 1359 } 1360 ret = _mei_irq_thread_cmpl_iamthif(dev, 1361 slots, 1362 cb_pos, 1363 cl, 1364 cmpl_list); 1365 if (ret) 1366 return ret; 1367 1368 } 1369 } 1370 1371 } 1372 } 1373 return 0; 1374} 1375 1376 1377 1378/** 1379 * mei_timer - timer function. 1380 * 1381 * @work: pointer to the work_struct structure 1382 * 1383 * NOTE: This function is called by timer interrupt work 1384 */ 1385void mei_wd_timer(struct work_struct *work) 1386{ 1387 unsigned long timeout; 1388 struct mei_cl *cl_pos = NULL; 1389 struct mei_cl *cl_next = NULL; 1390 struct list_head *amthi_complete_list = NULL; 1391 struct mei_cl_cb *cb_pos = NULL; 1392 struct mei_cl_cb *cb_next = NULL; 1393 1394 struct mei_device *dev = container_of(work, 1395 struct mei_device, wd_work.work); 1396 1397 1398 mutex_lock(&dev->device_lock); 1399 if (dev->mei_state != MEI_ENABLED) { 1400 if (dev->mei_state == MEI_INIT_CLIENTS) { 1401 if (dev->init_clients_timer) { 1402 if (--dev->init_clients_timer == 0) { 1403 dev_dbg(&dev->pdev->dev, "IMEI reset due to init clients timeout ,init clients state = %d.\n", 1404 dev->init_clients_state); 1405 mei_reset(dev, 1); 1406 } 1407 } 1408 } 1409 goto out; 1410 } 1411 /*** connect/disconnect timeouts ***/ 1412 list_for_each_entry_safe(cl_pos, cl_next, &dev->file_list, link) { 1413 if (cl_pos->timer_count) { 1414 if (--cl_pos->timer_count == 0) { 1415 dev_dbg(&dev->pdev->dev, "HECI reset due to connect/disconnect timeout.\n"); 1416 mei_reset(dev, 1); 1417 goto out; 1418 } 1419 } 1420 } 1421 1422 if (dev->wd_cl.state != MEI_FILE_CONNECTED) 1423 goto out; 1424 1425 /* Watchdog */ 1426 if (dev->wd_due_counter && !dev->wd_bypass) { 1427 if (--dev->wd_due_counter == 0) { 1428 if (dev->mei_host_buffer_is_empty && 1429 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { 1430 dev->mei_host_buffer_is_empty = 0; 1431 dev_dbg(&dev->pdev->dev, "send watchdog.\n"); 1432 1433 if (mei_wd_send(dev)) 1434 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); 1435 else 1436 if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) 1437 goto out; 1438 1439 if (dev->wd_timeout) 1440 dev->wd_due_counter = 2; 1441 else 1442 dev->wd_due_counter = 0; 1443 1444 } else 1445 dev->wd_pending = 1; 1446 1447 } 1448 } 1449 if (dev->iamthif_stall_timer) { 1450 if (--dev->iamthif_stall_timer == 0) { 1451 dev_dbg(&dev->pdev->dev, "reseting because of hang to amthi.\n"); 1452 mei_reset(dev, 1); 1453 dev->iamthif_msg_buf_size = 0; 1454 dev->iamthif_msg_buf_index = 0; 1455 dev->iamthif_canceled = 0; 1456 dev->iamthif_ioctl = 1; 1457 dev->iamthif_state = MEI_IAMTHIF_IDLE; 1458 dev->iamthif_timer = 0; 1459 1460 if (dev->iamthif_current_cb) 1461 mei_free_cb_private(dev->iamthif_current_cb); 1462 1463 dev->iamthif_file_object = NULL; 1464 dev->iamthif_current_cb = NULL; 1465 run_next_iamthif_cmd(dev); 1466 } 1467 } 1468 1469 if (dev->iamthif_timer) { 1470 1471 timeout = dev->iamthif_timer + 1472 msecs_to_jiffies(IAMTHIF_READ_TIMER); 1473 1474 dev_dbg(&dev->pdev->dev, "dev->iamthif_timer = %ld\n", 1475 dev->iamthif_timer); 1476 dev_dbg(&dev->pdev->dev, "timeout = %ld\n", timeout); 1477 dev_dbg(&dev->pdev->dev, "jiffies = %ld\n", jiffies); 1478 if (time_after(jiffies, timeout)) { 1479 /* 1480 * User didn't read the AMTHI data on time (15sec) 1481 * freeing AMTHI for other requests 1482 */ 1483 1484 dev_dbg(&dev->pdev->dev, "freeing AMTHI for other requests\n"); 1485 1486 amthi_complete_list = &dev->amthi_read_complete_list. 1487 mei_cb.cb_list; 1488 1489 if (!list_empty(amthi_complete_list)) { 1490 1491 list_for_each_entry_safe(cb_pos, cb_next, 1492 amthi_complete_list, 1493 cb_list) { 1494 1495 cl_pos = cb_pos->file_object->private_data; 1496 1497 /* Finding the AMTHI entry. */ 1498 if (cl_pos == &dev->iamthif_cl) 1499 list_del(&cb_pos->cb_list); 1500 } 1501 } 1502 if (dev->iamthif_current_cb) 1503 mei_free_cb_private(dev->iamthif_current_cb); 1504 1505 dev->iamthif_file_object->private_data = NULL; 1506 dev->iamthif_file_object = NULL; 1507 dev->iamthif_current_cb = NULL; 1508 dev->iamthif_timer = 0; 1509 run_next_iamthif_cmd(dev); 1510 1511 } 1512 } 1513out: 1514 schedule_delayed_work(&dev->wd_work, 2 * HZ); 1515 mutex_unlock(&dev->device_lock); 1516} 1517 1518/** 1519 * mei_interrupt_thread_handler - function called after ISR to handle the interrupt 1520 * processing. 1521 * 1522 * @irq: The irq number 1523 * @dev_id: pointer to the device structure 1524 * 1525 * returns irqreturn_t 1526 * 1527 */ 1528irqreturn_t mei_interrupt_thread_handler(int irq, void *dev_id) 1529{ 1530 struct mei_device *dev = (struct mei_device *) dev_id; 1531 struct mei_io_list complete_list; 1532 struct mei_cl_cb *cb_pos = NULL, *cb_next = NULL; 1533 struct mei_cl *cl; 1534 s32 slots; 1535 int rets; 1536 bool bus_message_received; 1537 1538 1539 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); 1540 /* initialize our complete list */ 1541 mutex_lock(&dev->device_lock); 1542 mei_initialize_list(&complete_list, dev); 1543 dev->host_hw_state = mei_hcsr_read(dev); 1544 dev->me_hw_state = mei_mecsr_read(dev); 1545 1546 /* check if ME wants a reset */ 1547 if ((dev->me_hw_state & ME_RDY_HRA) == 0 && 1548 dev->mei_state != MEI_RESETING && 1549 dev->mei_state != MEI_INITIALIZING) { 1550 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 1551 mei_reset(dev, 1); 1552 mutex_unlock(&dev->device_lock); 1553 return IRQ_HANDLED; 1554 } 1555 1556 /* check if we need to start the dev */ 1557 if ((dev->host_hw_state & H_RDY) == 0) { 1558 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { 1559 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); 1560 dev->host_hw_state |= (H_IE | H_IG | H_RDY); 1561 mei_hcsr_set(dev); 1562 dev->mei_state = MEI_INIT_CLIENTS; 1563 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); 1564 /* link is established 1565 * start sending messages. 1566 */ 1567 host_start_message(dev); 1568 mutex_unlock(&dev->device_lock); 1569 return IRQ_HANDLED; 1570 } else { 1571 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 1572 mutex_unlock(&dev->device_lock); 1573 return IRQ_HANDLED; 1574 } 1575 } 1576 /* check slots avalable for reading */ 1577 slots = mei_count_full_read_slots(dev); 1578 dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n", 1579 slots, dev->extra_write_index); 1580 while (slots > 0 && !dev->extra_write_index) { 1581 dev_dbg(&dev->pdev->dev, "slots =%08x extra_write_index =%08x.\n", 1582 slots, dev->extra_write_index); 1583 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); 1584 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); 1585 if (rets) 1586 goto end; 1587 } 1588 rets = mei_irq_thread_write_handler(&complete_list, dev, &slots); 1589end: 1590 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); 1591 dev->host_hw_state = mei_hcsr_read(dev); 1592 dev->mei_host_buffer_is_empty = mei_host_buffer_is_empty(dev); 1593 1594 bus_message_received = false; 1595 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { 1596 dev_dbg(&dev->pdev->dev, "received waiting bus message\n"); 1597 bus_message_received = true; 1598 } 1599 mutex_unlock(&dev->device_lock); 1600 if (bus_message_received) { 1601 dev_dbg(&dev->pdev->dev, "wake up dev->wait_recvd_msg\n"); 1602 wake_up_interruptible(&dev->wait_recvd_msg); 1603 bus_message_received = false; 1604 } 1605 if (complete_list.status || list_empty(&complete_list.mei_cb.cb_list)) 1606 return IRQ_HANDLED; 1607 1608 1609 list_for_each_entry_safe(cb_pos, cb_next, 1610 &complete_list.mei_cb.cb_list, cb_list) { 1611 cl = (struct mei_cl *)cb_pos->file_private; 1612 list_del(&cb_pos->cb_list); 1613 if (cl) { 1614 if (cl != &dev->iamthif_cl) { 1615 dev_dbg(&dev->pdev->dev, "completing call back.\n"); 1616 _mei_cmpl(cl, cb_pos); 1617 cb_pos = NULL; 1618 } else if (cl == &dev->iamthif_cl) { 1619 _mei_cmpl_iamthif(dev, cb_pos); 1620 } 1621 } 1622 } 1623 return IRQ_HANDLED; 1624}