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