interrupt.c (de65d816aa44f9ddd79861ae21d75010cc1fd003) | interrupt.c (827eef51f8dd9a4ab62b4ad270c15472f46938f2) |
---|---|
1/* 2 * 3 * Intel Management Engine Interface (Intel MEI) Linux driver 4 * Copyright (c) 2003-2012, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. --- 7 unchanged lines hidden (view full) --- 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 | 1/* 2 * 3 * Intel Management Engine Interface (Intel MEI) Linux driver 4 * Copyright (c) 2003-2012, Intel Corporation. 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms and conditions of the GNU General Public License, 8 * version 2, as published by the Free Software Foundation. --- 7 unchanged lines hidden (view full) --- 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 <linux/mei.h> | 24#include <linux/mei.h> |
26#include "hw.h" 27#include "interface.h" | |
28 | 25 |
26#include "mei_dev.h" 27#include "hbm.h" 28#include "hw-me.h" 29#include "client.h" |
|
29 | 30 |
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 | 31 |
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{ --- 85 unchanged lines hidden (view full) --- 145 } 146 147 } 148 149quit: 150 dev_dbg(&dev->pdev->dev, "message read\n"); 151 if (!buffer) { 152 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); | 32/** 33 * _mei_cmpl - processes completed operation. 34 * 35 * @cl: private data of the file object. 36 * @cb_pos: callback block. 37 */ 38static void _mei_cmpl(struct mei_cl *cl, struct mei_cl_cb *cb_pos) 39{ --- 85 unchanged lines hidden (view full) --- 125 } 126 127 } 128 129quit: 130 dev_dbg(&dev->pdev->dev, "message read\n"); 131 if (!buffer) { 132 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); |
153 dev_dbg(&dev->pdev->dev, "discarding message, header =%08x.\n", 154 *(u32 *) dev->rd_msg_buf); | 133 dev_dbg(&dev->pdev->dev, "discarding message " MEI_HDR_FMT "\n", 134 MEI_HDR_PRM(mei_hdr)); |
155 } 156 157 return 0; 158} 159 160/** 161 * _mei_irq_thread_close - processes close related operation. 162 * --- 11 unchanged lines hidden (view full) --- 174 struct mei_cl_cb *cmpl_list) 175{ 176 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + 177 sizeof(struct hbm_client_connect_request))) 178 return -EBADMSG; 179 180 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); 181 | 135 } 136 137 return 0; 138} 139 140/** 141 * _mei_irq_thread_close - processes close related operation. 142 * --- 11 unchanged lines hidden (view full) --- 154 struct mei_cl_cb *cmpl_list) 155{ 156 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + 157 sizeof(struct hbm_client_connect_request))) 158 return -EBADMSG; 159 160 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); 161 |
182 if (mei_disconnect(dev, cl)) { | 162 if (mei_hbm_cl_disconnect_req(dev, cl)) { |
183 cl->status = 0; 184 cb_pos->buf_idx = 0; 185 list_move_tail(&cb_pos->list, &cmpl_list->list); 186 return -EMSGSIZE; 187 } else { 188 cl->state = MEI_FILE_DISCONNECTING; 189 cl->status = 0; 190 cb_pos->buf_idx = 0; 191 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); 192 cl->timer_count = MEI_CONNECT_TIMEOUT; 193 } 194 195 return 0; 196} 197 | 163 cl->status = 0; 164 cb_pos->buf_idx = 0; 165 list_move_tail(&cb_pos->list, &cmpl_list->list); 166 return -EMSGSIZE; 167 } else { 168 cl->state = MEI_FILE_DISCONNECTING; 169 cl->status = 0; 170 cb_pos->buf_idx = 0; 171 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); 172 cl->timer_count = MEI_CONNECT_TIMEOUT; 173 } 174 175 return 0; 176} 177 |
198/** 199 * is_treat_specially_client - checks if the message belongs 200 * to the file private data. 201 * 202 * @cl: private data of the file object 203 * @rs: connect response bus message 204 * 205 */ 206static bool is_treat_specially_client(struct mei_cl *cl, 207 struct hbm_client_connect_response *rs) 208{ | |
209 | 178 |
210 if (cl->host_client_id == rs->host_addr && 211 cl->me_client_id == rs->me_addr) { 212 if (!rs->status) { 213 cl->state = MEI_FILE_CONNECTED; 214 cl->status = 0; 215 216 } else { 217 cl->state = MEI_FILE_DISCONNECTED; 218 cl->status = -ENODEV; 219 } 220 cl->timer_count = 0; 221 222 return true; 223 } 224 return false; 225} 226 | |
227/** | 179/** |
228 * mei_client_connect_response - connects to response irq routine 229 * 230 * @dev: the device structure 231 * @rs: connect response bus message 232 */ 233static void mei_client_connect_response(struct mei_device *dev, 234 struct hbm_client_connect_response *rs) 235{ 236 237 struct mei_cl *cl; 238 struct mei_cl_cb *pos = NULL, *next = NULL; 239 240 dev_dbg(&dev->pdev->dev, 241 "connect_response:\n" 242 "ME Client = %d\n" 243 "Host Client = %d\n" 244 "Status = %d\n", 245 rs->me_addr, 246 rs->host_addr, 247 rs->status); 248 249 /* if WD or iamthif client treat specially */ 250 251 if (is_treat_specially_client(&(dev->wd_cl), rs)) { 252 dev_dbg(&dev->pdev->dev, "successfully connected to WD client.\n"); 253 mei_watchdog_register(dev); 254 255 return; 256 } 257 258 if (is_treat_specially_client(&(dev->iamthif_cl), rs)) { 259 dev->iamthif_state = MEI_IAMTHIF_IDLE; 260 return; 261 } 262 list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) { 263 264 cl = pos->cl; 265 if (!cl) { 266 list_del(&pos->list); 267 return; 268 } 269 if (pos->fop_type == MEI_FOP_IOCTL) { 270 if (is_treat_specially_client(cl, rs)) { 271 list_del(&pos->list); 272 cl->status = 0; 273 cl->timer_count = 0; 274 break; 275 } 276 } 277 } 278} 279 280/** 281 * mei_client_disconnect_response - disconnects from response irq routine 282 * 283 * @dev: the device structure 284 * @rs: disconnect response bus message 285 */ 286static void mei_client_disconnect_response(struct mei_device *dev, 287 struct hbm_client_connect_response *rs) 288{ 289 struct mei_cl *cl; 290 struct mei_cl_cb *pos = NULL, *next = NULL; 291 292 dev_dbg(&dev->pdev->dev, 293 "disconnect_response:\n" 294 "ME Client = %d\n" 295 "Host Client = %d\n" 296 "Status = %d\n", 297 rs->me_addr, 298 rs->host_addr, 299 rs->status); 300 301 list_for_each_entry_safe(pos, next, &dev->ctrl_rd_list.list, list) { 302 cl = pos->cl; 303 304 if (!cl) { 305 list_del(&pos->list); 306 return; 307 } 308 309 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in ctrl_rd_list.\n"); 310 if (cl->host_client_id == rs->host_addr && 311 cl->me_client_id == rs->me_addr) { 312 313 list_del(&pos->list); 314 if (!rs->status) 315 cl->state = MEI_FILE_DISCONNECTED; 316 317 cl->status = 0; 318 cl->timer_count = 0; 319 break; 320 } 321 } 322} 323 324/** 325 * same_flow_addr - tells if they have the same address. 326 * 327 * @file: private data of the file object. 328 * @flow: flow control. 329 * 330 * returns !=0, same; 0,not. 331 */ 332static int same_flow_addr(struct mei_cl *cl, struct hbm_flow_control *flow) 333{ 334 return (cl->host_client_id == flow->host_addr && 335 cl->me_client_id == flow->me_addr); 336} 337 338/** 339 * add_single_flow_creds - adds single buffer credentials. 340 * 341 * @file: private data ot the file object. 342 * @flow: flow control. 343 */ 344static void add_single_flow_creds(struct mei_device *dev, 345 struct hbm_flow_control *flow) 346{ 347 struct mei_me_client *client; 348 int i; 349 350 for (i = 0; i < dev->me_clients_num; i++) { 351 client = &dev->me_clients[i]; 352 if (client && flow->me_addr == client->client_id) { 353 if (client->props.single_recv_buf) { 354 client->mei_flow_ctrl_creds++; 355 dev_dbg(&dev->pdev->dev, "recv flow ctrl msg ME %d (single).\n", 356 flow->me_addr); 357 dev_dbg(&dev->pdev->dev, "flow control credentials =%d.\n", 358 client->mei_flow_ctrl_creds); 359 } else { 360 BUG(); /* error in flow control */ 361 } 362 } 363 } 364} 365 366/** 367 * mei_client_flow_control_response - flow control response irq routine 368 * 369 * @dev: the device structure 370 * @flow_control: flow control response bus message 371 */ 372static void mei_client_flow_control_response(struct mei_device *dev, 373 struct hbm_flow_control *flow_control) 374{ 375 struct mei_cl *cl_pos = NULL; 376 struct mei_cl *cl_next = NULL; 377 378 if (!flow_control->host_addr) { 379 /* single receive buffer */ 380 add_single_flow_creds(dev, flow_control); 381 } else { 382 /* normal connection */ 383 list_for_each_entry_safe(cl_pos, cl_next, 384 &dev->file_list, link) { 385 dev_dbg(&dev->pdev->dev, "list_for_each_entry_safe in file_list\n"); 386 387 dev_dbg(&dev->pdev->dev, "cl of host client %d ME client %d.\n", 388 cl_pos->host_client_id, 389 cl_pos->me_client_id); 390 dev_dbg(&dev->pdev->dev, "flow ctrl msg for host %d ME %d.\n", 391 flow_control->host_addr, 392 flow_control->me_addr); 393 if (same_flow_addr(cl_pos, flow_control)) { 394 dev_dbg(&dev->pdev->dev, "recv ctrl msg for host %d ME %d.\n", 395 flow_control->host_addr, 396 flow_control->me_addr); 397 cl_pos->mei_flow_ctrl_creds++; 398 dev_dbg(&dev->pdev->dev, "flow control credentials = %d.\n", 399 cl_pos->mei_flow_ctrl_creds); 400 break; 401 } 402 } 403 } 404} 405 406/** 407 * same_disconn_addr - tells if they have the same address 408 * 409 * @file: private data of the file object. 410 * @disconn: disconnection request. 411 * 412 * returns !=0, same; 0,not. 413 */ 414static int same_disconn_addr(struct mei_cl *cl, 415 struct hbm_client_connect_request *req) 416{ 417 return (cl->host_client_id == req->host_addr && 418 cl->me_client_id == req->me_addr); 419} 420 421/** 422 * mei_client_disconnect_request - disconnects from request irq routine 423 * 424 * @dev: the device structure. 425 * @disconnect_req: disconnect request bus message. 426 */ 427static void mei_client_disconnect_request(struct mei_device *dev, 428 struct hbm_client_connect_request *disconnect_req) 429{ 430 struct hbm_client_connect_response *disconnect_res; 431 struct mei_cl *pos, *next; 432 const size_t len = sizeof(struct hbm_client_connect_response); 433 434 list_for_each_entry_safe(pos, next, &dev->file_list, link) { 435 if (same_disconn_addr(pos, disconnect_req)) { 436 dev_dbg(&dev->pdev->dev, "disconnect request host client %d ME client %d.\n", 437 disconnect_req->host_addr, 438 disconnect_req->me_addr); 439 pos->state = MEI_FILE_DISCONNECTED; 440 pos->timer_count = 0; 441 if (pos == &dev->wd_cl) 442 dev->wd_pending = false; 443 else if (pos == &dev->iamthif_cl) 444 dev->iamthif_timer = 0; 445 446 /* prepare disconnect response */ 447 (void)mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len); 448 disconnect_res = 449 (struct hbm_client_connect_response *) 450 &dev->wr_ext_msg.data; 451 disconnect_res->hbm_cmd = CLIENT_DISCONNECT_RES_CMD; 452 disconnect_res->host_addr = pos->host_client_id; 453 disconnect_res->me_addr = pos->me_client_id; 454 disconnect_res->status = 0; 455 break; 456 } 457 } 458} 459 460/** 461 * mei_irq_thread_read_bus_message - bottom half read routine after ISR to 462 * handle the read bus message cmd processing. 463 * 464 * @dev: the device structure 465 * @mei_hdr: header of bus message 466 */ 467static void mei_irq_thread_read_bus_message(struct mei_device *dev, 468 struct mei_msg_hdr *mei_hdr) 469{ 470 struct mei_bus_message *mei_msg; 471 struct mei_me_client *me_client; 472 struct hbm_host_version_response *version_res; 473 struct hbm_client_connect_response *connect_res; 474 struct hbm_client_connect_response *disconnect_res; 475 struct hbm_client_connect_request *disconnect_req; 476 struct hbm_flow_control *flow_control; 477 struct hbm_props_response *props_res; 478 struct hbm_host_enum_response *enum_res; 479 struct hbm_host_stop_request *stop_req; 480 481 /* read the message to our buffer */ 482 BUG_ON(mei_hdr->length >= sizeof(dev->rd_msg_buf)); 483 mei_read_slots(dev, dev->rd_msg_buf, mei_hdr->length); 484 mei_msg = (struct mei_bus_message *)dev->rd_msg_buf; 485 486 switch (mei_msg->hbm_cmd) { 487 case HOST_START_RES_CMD: 488 version_res = (struct hbm_host_version_response *) mei_msg; 489 if (version_res->host_version_supported) { 490 dev->version.major_version = HBM_MAJOR_VERSION; 491 dev->version.minor_version = HBM_MINOR_VERSION; 492 if (dev->dev_state == MEI_DEV_INIT_CLIENTS && 493 dev->init_clients_state == MEI_START_MESSAGE) { 494 dev->init_clients_timer = 0; 495 mei_host_enum_clients_message(dev); 496 } else { 497 dev->recvd_msg = false; 498 dev_dbg(&dev->pdev->dev, "IMEI reset due to received host start response bus message.\n"); 499 mei_reset(dev, 1); 500 return; 501 } 502 } else { 503 u32 *buf = dev->wr_msg_buf; 504 const size_t len = sizeof(struct hbm_host_stop_request); 505 506 dev->version = version_res->me_max_version; 507 508 /* send stop message */ 509 mei_hdr = mei_hbm_hdr(&buf[0], len); 510 stop_req = (struct hbm_host_stop_request *)&buf[1]; 511 memset(stop_req, 0, len); 512 stop_req->hbm_cmd = HOST_STOP_REQ_CMD; 513 stop_req->reason = DRIVER_STOP_REQUEST; 514 515 mei_write_message(dev, mei_hdr, 516 (unsigned char *)stop_req, len); 517 dev_dbg(&dev->pdev->dev, "version mismatch.\n"); 518 return; 519 } 520 521 dev->recvd_msg = true; 522 dev_dbg(&dev->pdev->dev, "host start response message received.\n"); 523 break; 524 525 case CLIENT_CONNECT_RES_CMD: 526 connect_res = (struct hbm_client_connect_response *) mei_msg; 527 mei_client_connect_response(dev, connect_res); 528 dev_dbg(&dev->pdev->dev, "client connect response message received.\n"); 529 wake_up(&dev->wait_recvd_msg); 530 break; 531 532 case CLIENT_DISCONNECT_RES_CMD: 533 disconnect_res = (struct hbm_client_connect_response *) mei_msg; 534 mei_client_disconnect_response(dev, disconnect_res); 535 dev_dbg(&dev->pdev->dev, "client disconnect response message received.\n"); 536 wake_up(&dev->wait_recvd_msg); 537 break; 538 539 case MEI_FLOW_CONTROL_CMD: 540 flow_control = (struct hbm_flow_control *) mei_msg; 541 mei_client_flow_control_response(dev, flow_control); 542 dev_dbg(&dev->pdev->dev, "client flow control response message received.\n"); 543 break; 544 545 case HOST_CLIENT_PROPERTIES_RES_CMD: 546 props_res = (struct hbm_props_response *)mei_msg; 547 me_client = &dev->me_clients[dev->me_client_presentation_num]; 548 549 if (props_res->status || !dev->me_clients) { 550 dev_dbg(&dev->pdev->dev, "reset due to received host client properties response bus message wrong status.\n"); 551 mei_reset(dev, 1); 552 return; 553 } 554 555 if (me_client->client_id != props_res->address) { 556 dev_err(&dev->pdev->dev, 557 "Host client properties reply mismatch\n"); 558 mei_reset(dev, 1); 559 560 return; 561 } 562 563 if (dev->dev_state != MEI_DEV_INIT_CLIENTS || 564 dev->init_clients_state != MEI_CLIENT_PROPERTIES_MESSAGE) { 565 dev_err(&dev->pdev->dev, 566 "Unexpected client properties reply\n"); 567 mei_reset(dev, 1); 568 569 return; 570 } 571 572 me_client->props = props_res->client_properties; 573 dev->me_client_index++; 574 dev->me_client_presentation_num++; 575 576 mei_host_client_enumerate(dev); 577 578 break; 579 580 case HOST_ENUM_RES_CMD: 581 enum_res = (struct hbm_host_enum_response *) mei_msg; 582 memcpy(dev->me_clients_map, enum_res->valid_addresses, 32); 583 if (dev->dev_state == MEI_DEV_INIT_CLIENTS && 584 dev->init_clients_state == MEI_ENUM_CLIENTS_MESSAGE) { 585 dev->init_clients_timer = 0; 586 dev->me_client_presentation_num = 0; 587 dev->me_client_index = 0; 588 mei_allocate_me_clients_storage(dev); 589 dev->init_clients_state = 590 MEI_CLIENT_PROPERTIES_MESSAGE; 591 592 mei_host_client_enumerate(dev); 593 } else { 594 dev_dbg(&dev->pdev->dev, "reset due to received host enumeration clients response bus message.\n"); 595 mei_reset(dev, 1); 596 return; 597 } 598 break; 599 600 case HOST_STOP_RES_CMD: 601 dev->dev_state = MEI_DEV_DISABLED; 602 dev_dbg(&dev->pdev->dev, "resetting because of FW stop response.\n"); 603 mei_reset(dev, 1); 604 break; 605 606 case CLIENT_DISCONNECT_REQ_CMD: 607 /* search for client */ 608 disconnect_req = (struct hbm_client_connect_request *)mei_msg; 609 mei_client_disconnect_request(dev, disconnect_req); 610 break; 611 612 case ME_STOP_REQ_CMD: 613 { 614 /* prepare stop request: sent in next interrupt event */ 615 616 const size_t len = sizeof(struct hbm_host_stop_request); 617 618 mei_hdr = mei_hbm_hdr((u32 *)&dev->wr_ext_msg.hdr, len); 619 stop_req = (struct hbm_host_stop_request *)&dev->wr_ext_msg.data; 620 memset(stop_req, 0, len); 621 stop_req->hbm_cmd = HOST_STOP_REQ_CMD; 622 stop_req->reason = DRIVER_STOP_REQUEST; 623 break; 624 } 625 default: 626 BUG(); 627 break; 628 629 } 630} 631 632 633/** | |
634 * _mei_hb_read - processes read related operation. 635 * 636 * @dev: the device structure. 637 * @slots: free slots. 638 * @cb_pos: callback block. 639 * @cl: private data of the file object. 640 * @cmpl_list: complete list. 641 * --- 8 unchanged lines hidden (view full) --- 650 sizeof(struct hbm_flow_control))) { 651 /* return the cancel routine */ 652 list_del(&cb_pos->list); 653 return -EBADMSG; 654 } 655 656 *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); 657 | 180 * _mei_hb_read - processes read related operation. 181 * 182 * @dev: the device structure. 183 * @slots: free slots. 184 * @cb_pos: callback block. 185 * @cl: private data of the file object. 186 * @cmpl_list: complete list. 187 * --- 8 unchanged lines hidden (view full) --- 196 sizeof(struct hbm_flow_control))) { 197 /* return the cancel routine */ 198 list_del(&cb_pos->list); 199 return -EBADMSG; 200 } 201 202 *slots -= mei_data2slots(sizeof(struct hbm_flow_control)); 203 |
658 if (mei_send_flow_control(dev, cl)) { | 204 if (mei_hbm_cl_flow_control_req(dev, cl)) { |
659 cl->status = -ENODEV; 660 cb_pos->buf_idx = 0; 661 list_move_tail(&cb_pos->list, &cmpl_list->list); 662 return -ENODEV; 663 } 664 list_move_tail(&cb_pos->list, &dev->read_list.list); 665 666 return 0; --- 19 unchanged lines hidden (view full) --- 686 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + 687 sizeof(struct hbm_client_connect_request))) { 688 /* return the cancel routine */ 689 list_del(&cb_pos->list); 690 return -EBADMSG; 691 } 692 693 cl->state = MEI_FILE_CONNECTING; | 205 cl->status = -ENODEV; 206 cb_pos->buf_idx = 0; 207 list_move_tail(&cb_pos->list, &cmpl_list->list); 208 return -ENODEV; 209 } 210 list_move_tail(&cb_pos->list, &dev->read_list.list); 211 212 return 0; --- 19 unchanged lines hidden (view full) --- 232 if ((*slots * sizeof(u32)) < (sizeof(struct mei_msg_hdr) + 233 sizeof(struct hbm_client_connect_request))) { 234 /* return the cancel routine */ 235 list_del(&cb_pos->list); 236 return -EBADMSG; 237 } 238 239 cl->state = MEI_FILE_CONNECTING; |
694 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); 695 if (mei_connect(dev, cl)) { | 240 *slots -= mei_data2slots(sizeof(struct hbm_client_connect_request)); 241 if (mei_hbm_cl_connect_req(dev, cl)) { |
696 cl->status = -ENODEV; 697 cb_pos->buf_idx = 0; 698 list_del(&cb_pos->list); 699 return -ENODEV; 700 } else { 701 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); 702 cl->timer_count = MEI_CONNECT_TIMEOUT; 703 } --- 8 unchanged lines hidden (view full) --- 712 * @cb: callback block. 713 * @cmpl_list: complete list. 714 * 715 * returns 0, OK; otherwise, error. 716 */ 717static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots, 718 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) 719{ | 242 cl->status = -ENODEV; 243 cb_pos->buf_idx = 0; 244 list_del(&cb_pos->list); 245 return -ENODEV; 246 } else { 247 list_move_tail(&cb_pos->list, &dev->ctrl_rd_list.list); 248 cl->timer_count = MEI_CONNECT_TIMEOUT; 249 } --- 8 unchanged lines hidden (view full) --- 258 * @cb: callback block. 259 * @cmpl_list: complete list. 260 * 261 * returns 0, OK; otherwise, error. 262 */ 263static int mei_irq_thread_write_complete(struct mei_device *dev, s32 *slots, 264 struct mei_cl_cb *cb, struct mei_cl_cb *cmpl_list) 265{ |
720 struct mei_msg_hdr *mei_hdr; | 266 struct mei_msg_hdr mei_hdr; |
721 struct mei_cl *cl = cb->cl; 722 size_t len = cb->request_buffer.size - cb->buf_idx; 723 size_t msg_slots = mei_data2slots(len); 724 | 267 struct mei_cl *cl = cb->cl; 268 size_t len = cb->request_buffer.size - cb->buf_idx; 269 size_t msg_slots = mei_data2slots(len); 270 |
725 mei_hdr = (struct mei_msg_hdr *)&dev->wr_msg_buf[0]; 726 mei_hdr->host_addr = cl->host_client_id; 727 mei_hdr->me_addr = cl->me_client_id; 728 mei_hdr->reserved = 0; | 271 mei_hdr.host_addr = cl->host_client_id; 272 mei_hdr.me_addr = cl->me_client_id; 273 mei_hdr.reserved = 0; |
729 730 if (*slots >= msg_slots) { | 274 275 if (*slots >= msg_slots) { |
731 mei_hdr->length = len; 732 mei_hdr->msg_complete = 1; | 276 mei_hdr.length = len; 277 mei_hdr.msg_complete = 1; |
733 /* Split the message only if we can write the whole host buffer */ 734 } else if (*slots == dev->hbuf_depth) { 735 msg_slots = *slots; 736 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); | 278 /* Split the message only if we can write the whole host buffer */ 279 } else if (*slots == dev->hbuf_depth) { 280 msg_slots = *slots; 281 len = (*slots * sizeof(u32)) - sizeof(struct mei_msg_hdr); |
737 mei_hdr->length = len; 738 mei_hdr->msg_complete = 0; | 282 mei_hdr.length = len; 283 mei_hdr.msg_complete = 0; |
739 } else { 740 /* wait for next time the host buffer is empty */ 741 return 0; 742 } 743 744 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", 745 cb->request_buffer.size, cb->buf_idx); | 284 } else { 285 /* wait for next time the host buffer is empty */ 286 return 0; 287 } 288 289 dev_dbg(&dev->pdev->dev, "buf: size = %d idx = %lu\n", 290 cb->request_buffer.size, cb->buf_idx); |
746 dev_dbg(&dev->pdev->dev, "msg: len = %d complete = %d\n", 747 mei_hdr->length, mei_hdr->msg_complete); | 291 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(&mei_hdr)); |
748 749 *slots -= msg_slots; | 292 293 *slots -= msg_slots; |
750 if (mei_write_message(dev, mei_hdr, 751 cb->request_buffer.data + cb->buf_idx, len)) { | 294 if (mei_write_message(dev, &mei_hdr, 295 cb->request_buffer.data + cb->buf_idx)) { |
752 cl->status = -ENODEV; 753 list_move_tail(&cb->list, &cmpl_list->list); 754 return -ENODEV; 755 } 756 | 296 cl->status = -ENODEV; 297 list_move_tail(&cb->list, &cmpl_list->list); 298 return -ENODEV; 299 } 300 |
757 if (mei_flow_ctrl_reduce(dev, cl)) | 301 if (mei_cl_flow_ctrl_reduce(cl)) |
758 return -ENODEV; 759 760 cl->status = 0; | 302 return -ENODEV; 303 304 cl->status = 0; |
761 cb->buf_idx += mei_hdr->length; 762 if (mei_hdr->msg_complete) | 305 cb->buf_idx += mei_hdr.length; 306 if (mei_hdr.msg_complete) |
763 list_move_tail(&cb->list, &dev->write_waiting_list.list); 764 765 return 0; 766} 767 768/** 769 * mei_irq_thread_read_handler - bottom half read routine after ISR to 770 * handle the read processing. --- 9 unchanged lines hidden (view full) --- 780 s32 *slots) 781{ 782 struct mei_msg_hdr *mei_hdr; 783 struct mei_cl *cl_pos = NULL; 784 struct mei_cl *cl_next = NULL; 785 int ret = 0; 786 787 if (!dev->rd_msg_hdr) { | 307 list_move_tail(&cb->list, &dev->write_waiting_list.list); 308 309 return 0; 310} 311 312/** 313 * mei_irq_thread_read_handler - bottom half read routine after ISR to 314 * handle the read processing. --- 9 unchanged lines hidden (view full) --- 324 s32 *slots) 325{ 326 struct mei_msg_hdr *mei_hdr; 327 struct mei_cl *cl_pos = NULL; 328 struct mei_cl *cl_next = NULL; 329 int ret = 0; 330 331 if (!dev->rd_msg_hdr) { |
788 dev->rd_msg_hdr = mei_mecbrw_read(dev); | 332 dev->rd_msg_hdr = mei_read_hdr(dev); |
789 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 790 (*slots)--; 791 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 792 } 793 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr; | 333 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 334 (*slots)--; 335 dev_dbg(&dev->pdev->dev, "slots =%08x.\n", *slots); 336 } 337 mei_hdr = (struct mei_msg_hdr *) &dev->rd_msg_hdr; |
794 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", mei_hdr->length); | 338 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); |
795 796 if (mei_hdr->reserved || !dev->rd_msg_hdr) { 797 dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); 798 ret = -EBADMSG; 799 goto end; 800 } 801 802 if (mei_hdr->host_addr || mei_hdr->me_addr) { --- 22 unchanged lines hidden (view full) --- 825 /* we can't read the message */ 826 ret = -ERANGE; 827 goto end; 828 } 829 830 /* decide where to read the message too */ 831 if (!mei_hdr->host_addr) { 832 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n"); | 339 340 if (mei_hdr->reserved || !dev->rd_msg_hdr) { 341 dev_dbg(&dev->pdev->dev, "corrupted message header.\n"); 342 ret = -EBADMSG; 343 goto end; 344 } 345 346 if (mei_hdr->host_addr || mei_hdr->me_addr) { --- 22 unchanged lines hidden (view full) --- 369 /* we can't read the message */ 370 ret = -ERANGE; 371 goto end; 372 } 373 374 /* decide where to read the message too */ 375 if (!mei_hdr->host_addr) { 376 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_bus_message.\n"); |
833 mei_irq_thread_read_bus_message(dev, mei_hdr); | 377 mei_hbm_dispatch(dev, mei_hdr); |
834 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n"); 835 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 836 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && 837 (dev->iamthif_state == MEI_IAMTHIF_READING)) { 838 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); | 378 dev_dbg(&dev->pdev->dev, "end mei_irq_thread_read_bus_message.\n"); 379 } else if (mei_hdr->host_addr == dev->iamthif_cl.host_client_id && 380 (MEI_FILE_CONNECTED == dev->iamthif_cl.state) && 381 (dev->iamthif_state == MEI_IAMTHIF_READING)) { 382 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_iamthif_message.\n"); |
839 dev_dbg(&dev->pdev->dev, "mei_hdr->length =%d\n", 840 mei_hdr->length); | |
841 | 383 |
384 dev_dbg(&dev->pdev->dev, MEI_HDR_FMT, MEI_HDR_PRM(mei_hdr)); 385 |
|
842 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr); 843 if (ret) 844 goto end; | 386 ret = mei_amthif_irq_read_message(cmpl_list, dev, mei_hdr); 387 if (ret) 388 goto end; |
845 | |
846 } else { 847 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n"); 848 ret = mei_irq_thread_read_client_message(cmpl_list, 849 dev, mei_hdr); 850 if (ret) 851 goto end; 852 853 } --- 28 unchanged lines hidden (view full) --- 882{ 883 884 struct mei_cl *cl; 885 struct mei_cl_cb *pos = NULL, *next = NULL; 886 struct mei_cl_cb *list; 887 s32 slots; 888 int ret; 889 | 389 } else { 390 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_client_message.\n"); 391 ret = mei_irq_thread_read_client_message(cmpl_list, 392 dev, mei_hdr); 393 if (ret) 394 goto end; 395 396 } --- 28 unchanged lines hidden (view full) --- 425{ 426 427 struct mei_cl *cl; 428 struct mei_cl_cb *pos = NULL, *next = NULL; 429 struct mei_cl_cb *list; 430 s32 slots; 431 int ret; 432 |
890 if (!mei_hbuf_is_empty(dev)) { | 433 if (!mei_hbuf_is_ready(dev)) { |
891 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); 892 return 0; 893 } 894 slots = mei_hbuf_empty_slots(dev); 895 if (slots <= 0) 896 return -EMSGSIZE; 897 898 /* complete all waiting for write CB */ --- 26 unchanged lines hidden (view full) --- 925 926 if (dev->wd_state == MEI_WD_STOPPING) { 927 dev->wd_state = MEI_WD_IDLE; 928 wake_up_interruptible(&dev->wait_stop_wd); 929 } 930 931 if (dev->wr_ext_msg.hdr.length) { 932 mei_write_message(dev, &dev->wr_ext_msg.hdr, | 434 dev_dbg(&dev->pdev->dev, "host buffer is not empty.\n"); 435 return 0; 436 } 437 slots = mei_hbuf_empty_slots(dev); 438 if (slots <= 0) 439 return -EMSGSIZE; 440 441 /* complete all waiting for write CB */ --- 26 unchanged lines hidden (view full) --- 468 469 if (dev->wd_state == MEI_WD_STOPPING) { 470 dev->wd_state = MEI_WD_IDLE; 471 wake_up_interruptible(&dev->wait_stop_wd); 472 } 473 474 if (dev->wr_ext_msg.hdr.length) { 475 mei_write_message(dev, &dev->wr_ext_msg.hdr, |
933 dev->wr_ext_msg.data, dev->wr_ext_msg.hdr.length); | 476 dev->wr_ext_msg.data); |
934 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length); 935 dev->wr_ext_msg.hdr.length = 0; 936 } 937 if (dev->dev_state == MEI_DEV_ENABLED) { 938 if (dev->wd_pending && | 477 slots -= mei_data2slots(dev->wr_ext_msg.hdr.length); 478 dev->wr_ext_msg.hdr.length = 0; 479 } 480 if (dev->dev_state == MEI_DEV_ENABLED) { 481 if (dev->wd_pending && |
939 mei_flow_ctrl_creds(dev, &dev->wd_cl) > 0) { | 482 mei_cl_flow_ctrl_creds(&dev->wd_cl) > 0) { |
940 if (mei_wd_send(dev)) 941 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); | 483 if (mei_wd_send(dev)) 484 dev_dbg(&dev->pdev->dev, "wd send failed.\n"); |
942 else if (mei_flow_ctrl_reduce(dev, &dev->wd_cl)) | 485 else if (mei_cl_flow_ctrl_reduce(&dev->wd_cl)) |
943 return -ENODEV; 944 945 dev->wd_pending = false; 946 947 if (dev->wd_state == MEI_WD_RUNNING) 948 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); 949 else 950 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); --- 22 unchanged lines hidden (view full) --- 973 ret = _mei_irq_thread_read(dev, &slots, pos, 974 cl, cmpl_list); 975 if (ret) 976 return ret; 977 978 break; 979 case MEI_FOP_IOCTL: 980 /* connect message */ | 486 return -ENODEV; 487 488 dev->wd_pending = false; 489 490 if (dev->wd_state == MEI_WD_RUNNING) 491 slots -= mei_data2slots(MEI_WD_START_MSG_SIZE); 492 else 493 slots -= mei_data2slots(MEI_WD_STOP_MSG_SIZE); --- 22 unchanged lines hidden (view full) --- 516 ret = _mei_irq_thread_read(dev, &slots, pos, 517 cl, cmpl_list); 518 if (ret) 519 return ret; 520 521 break; 522 case MEI_FOP_IOCTL: 523 /* connect message */ |
981 if (mei_other_client_is_connecting(dev, cl)) | 524 if (mei_cl_is_other_connecting(cl)) |
982 continue; 983 ret = _mei_irq_thread_ioctl(dev, &slots, pos, 984 cl, cmpl_list); 985 if (ret) 986 return ret; 987 988 break; 989 990 default: 991 BUG(); 992 } 993 994 } 995 /* complete write list CB */ 996 dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); 997 list_for_each_entry_safe(pos, next, &dev->write_list.list, list) { 998 cl = pos->cl; 999 if (cl == NULL) 1000 continue; | 525 continue; 526 ret = _mei_irq_thread_ioctl(dev, &slots, pos, 527 cl, cmpl_list); 528 if (ret) 529 return ret; 530 531 break; 532 533 default: 534 BUG(); 535 } 536 537 } 538 /* complete write list CB */ 539 dev_dbg(&dev->pdev->dev, "complete write list cb.\n"); 540 list_for_each_entry_safe(pos, next, &dev->write_list.list, list) { 541 cl = pos->cl; 542 if (cl == NULL) 543 continue; |
1001 if (mei_flow_ctrl_creds(dev, cl) <= 0) { | 544 if (mei_cl_flow_ctrl_creds(cl) <= 0) { |
1002 dev_dbg(&dev->pdev->dev, 1003 "No flow control credentials for client %d, not sending.\n", 1004 cl->host_client_id); 1005 continue; 1006 } 1007 1008 if (cl == &dev->iamthif_cl) 1009 ret = mei_amthif_irq_write_complete(dev, &slots, --- 133 unchanged lines hidden (view full) --- 1143 int rets; 1144 bool bus_message_received; 1145 1146 1147 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); 1148 /* initialize our complete list */ 1149 mutex_lock(&dev->device_lock); 1150 mei_io_list_init(&complete_list); | 545 dev_dbg(&dev->pdev->dev, 546 "No flow control credentials for client %d, not sending.\n", 547 cl->host_client_id); 548 continue; 549 } 550 551 if (cl == &dev->iamthif_cl) 552 ret = mei_amthif_irq_write_complete(dev, &slots, --- 133 unchanged lines hidden (view full) --- 686 int rets; 687 bool bus_message_received; 688 689 690 dev_dbg(&dev->pdev->dev, "function called after ISR to handle the interrupt processing.\n"); 691 /* initialize our complete list */ 692 mutex_lock(&dev->device_lock); 693 mei_io_list_init(&complete_list); |
1151 dev->host_hw_state = mei_hcsr_read(dev); | |
1152 1153 /* Ack the interrupt here 1154 * In case of MSI we don't go through the quick handler */ 1155 if (pci_dev_msi_enabled(dev->pdev)) | 694 695 /* Ack the interrupt here 696 * In case of MSI we don't go through the quick handler */ 697 if (pci_dev_msi_enabled(dev->pdev)) |
1156 mei_reg_write(dev, H_CSR, dev->host_hw_state); | 698 mei_clear_interrupts(dev); |
1157 | 699 |
1158 dev->me_hw_state = mei_mecsr_read(dev); 1159 | |
1160 /* check if ME wants a reset */ | 700 /* check if ME wants a reset */ |
1161 if ((dev->me_hw_state & ME_RDY_HRA) == 0 && | 701 if (!mei_hw_is_ready(dev) && |
1162 dev->dev_state != MEI_DEV_RESETING && 1163 dev->dev_state != MEI_DEV_INITIALIZING) { 1164 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 1165 mei_reset(dev, 1); 1166 mutex_unlock(&dev->device_lock); 1167 return IRQ_HANDLED; 1168 } 1169 1170 /* check if we need to start the dev */ | 702 dev->dev_state != MEI_DEV_RESETING && 703 dev->dev_state != MEI_DEV_INITIALIZING) { 704 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 705 mei_reset(dev, 1); 706 mutex_unlock(&dev->device_lock); 707 return IRQ_HANDLED; 708 } 709 710 /* check if we need to start the dev */ |
1171 if ((dev->host_hw_state & H_RDY) == 0) { 1172 if ((dev->me_hw_state & ME_RDY_HRA) == ME_RDY_HRA) { | 711 if (!mei_host_is_ready(dev)) { 712 if (mei_hw_is_ready(dev)) { |
1173 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); | 713 dev_dbg(&dev->pdev->dev, "we need to start the dev.\n"); |
1174 dev->host_hw_state |= (H_IE | H_IG | H_RDY); 1175 mei_hcsr_set(dev); 1176 dev->dev_state = MEI_DEV_INIT_CLIENTS; | 714 715 mei_host_set_ready(dev); 716 |
1177 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); | 717 dev_dbg(&dev->pdev->dev, "link is established start sending messages.\n"); |
1178 /* link is established 1179 * start sending messages. 1180 */ 1181 mei_host_start_message(dev); | 718 /* link is established * start sending messages. */ 719 720 dev->dev_state = MEI_DEV_INIT_CLIENTS; 721 722 mei_hbm_start_req(dev); |
1182 mutex_unlock(&dev->device_lock); 1183 return IRQ_HANDLED; 1184 } else { 1185 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 1186 mutex_unlock(&dev->device_lock); 1187 return IRQ_HANDLED; 1188 } 1189 } --- 7 unchanged lines hidden (view full) --- 1197 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); 1198 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); 1199 if (rets) 1200 goto end; 1201 } 1202 rets = mei_irq_thread_write_handler(dev, &complete_list); 1203end: 1204 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); | 723 mutex_unlock(&dev->device_lock); 724 return IRQ_HANDLED; 725 } else { 726 dev_dbg(&dev->pdev->dev, "FW not ready.\n"); 727 mutex_unlock(&dev->device_lock); 728 return IRQ_HANDLED; 729 } 730 } --- 7 unchanged lines hidden (view full) --- 738 dev_dbg(&dev->pdev->dev, "call mei_irq_thread_read_handler.\n"); 739 rets = mei_irq_thread_read_handler(&complete_list, dev, &slots); 740 if (rets) 741 goto end; 742 } 743 rets = mei_irq_thread_write_handler(dev, &complete_list); 744end: 745 dev_dbg(&dev->pdev->dev, "end of bottom half function.\n"); |
1205 dev->host_hw_state = mei_hcsr_read(dev); 1206 dev->mei_host_buffer_is_empty = mei_hbuf_is_empty(dev); | 746 dev->mei_host_buffer_is_empty = mei_hbuf_is_ready(dev); |
1207 1208 bus_message_received = false; 1209 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { 1210 dev_dbg(&dev->pdev->dev, "received waiting bus message\n"); 1211 bus_message_received = true; 1212 } 1213 mutex_unlock(&dev->device_lock); 1214 if (bus_message_received) { --- 23 unchanged lines hidden --- | 747 748 bus_message_received = false; 749 if (dev->recvd_msg && waitqueue_active(&dev->wait_recvd_msg)) { 750 dev_dbg(&dev->pdev->dev, "received waiting bus message\n"); 751 bus_message_received = true; 752 } 753 mutex_unlock(&dev->device_lock); 754 if (bus_message_received) { --- 23 unchanged lines hidden --- |