1 /* 2 * Copyright (c) 2005-2010 Brocade Communications Systems, Inc. 3 * All rights reserved 4 * www.brocade.com 5 * 6 * Linux driver for Brocade Fibre Channel Host Bus Adapter. 7 * 8 * This program is free software; you can redistribute it and/or modify it 9 * under the terms of the GNU General Public License (GPL) Version 2 as 10 * published by the Free Software Foundation 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 */ 17 18 #include "bfad_drv.h" 19 #include "bfa_defs_svc.h" 20 #include "bfa_port.h" 21 #include "bfi.h" 22 #include "bfa_ioc.h" 23 24 25 BFA_TRC_FILE(CNA, PORT); 26 27 static void 28 bfa_port_stats_swap(struct bfa_port_s *port, union bfa_port_stats_u *stats) 29 { 30 u32 *dip = (u32 *) stats; 31 __be32 t0, t1; 32 int i; 33 34 for (i = 0; i < sizeof(union bfa_port_stats_u)/sizeof(u32); 35 i += 2) { 36 t0 = dip[i]; 37 t1 = dip[i + 1]; 38 #ifdef __BIG_ENDIAN 39 dip[i] = be32_to_cpu(t0); 40 dip[i + 1] = be32_to_cpu(t1); 41 #else 42 dip[i] = be32_to_cpu(t1); 43 dip[i + 1] = be32_to_cpu(t0); 44 #endif 45 } 46 } 47 48 /* 49 * bfa_port_enable_isr() 50 * 51 * 52 * @param[in] port - Pointer to the port module 53 * status - Return status from the f/w 54 * 55 * @return void 56 */ 57 static void 58 bfa_port_enable_isr(struct bfa_port_s *port, bfa_status_t status) 59 { 60 bfa_trc(port, status); 61 port->endis_pending = BFA_FALSE; 62 port->endis_cbfn(port->endis_cbarg, status); 63 } 64 65 /* 66 * bfa_port_disable_isr() 67 * 68 * 69 * @param[in] port - Pointer to the port module 70 * status - Return status from the f/w 71 * 72 * @return void 73 */ 74 static void 75 bfa_port_disable_isr(struct bfa_port_s *port, bfa_status_t status) 76 { 77 bfa_trc(port, status); 78 port->endis_pending = BFA_FALSE; 79 port->endis_cbfn(port->endis_cbarg, status); 80 } 81 82 /* 83 * bfa_port_get_stats_isr() 84 * 85 * 86 * @param[in] port - Pointer to the Port module 87 * status - Return status from the f/w 88 * 89 * @return void 90 */ 91 static void 92 bfa_port_get_stats_isr(struct bfa_port_s *port, bfa_status_t status) 93 { 94 port->stats_status = status; 95 port->stats_busy = BFA_FALSE; 96 97 if (status == BFA_STATUS_OK) { 98 struct timeval tv; 99 100 memcpy(port->stats, port->stats_dma.kva, 101 sizeof(union bfa_port_stats_u)); 102 bfa_port_stats_swap(port, port->stats); 103 104 do_gettimeofday(&tv); 105 port->stats->fc.secs_reset = tv.tv_sec - port->stats_reset_time; 106 } 107 108 if (port->stats_cbfn) { 109 port->stats_cbfn(port->stats_cbarg, status); 110 port->stats_cbfn = NULL; 111 } 112 } 113 114 /* 115 * bfa_port_clear_stats_isr() 116 * 117 * 118 * @param[in] port - Pointer to the Port module 119 * status - Return status from the f/w 120 * 121 * @return void 122 */ 123 static void 124 bfa_port_clear_stats_isr(struct bfa_port_s *port, bfa_status_t status) 125 { 126 struct timeval tv; 127 128 port->stats_status = status; 129 port->stats_busy = BFA_FALSE; 130 131 /* 132 * re-initialize time stamp for stats reset 133 */ 134 do_gettimeofday(&tv); 135 port->stats_reset_time = tv.tv_sec; 136 137 if (port->stats_cbfn) { 138 port->stats_cbfn(port->stats_cbarg, status); 139 port->stats_cbfn = NULL; 140 } 141 } 142 143 /* 144 * bfa_port_isr() 145 * 146 * 147 * @param[in] Pointer to the Port module data structure. 148 * 149 * @return void 150 */ 151 static void 152 bfa_port_isr(void *cbarg, struct bfi_mbmsg_s *m) 153 { 154 struct bfa_port_s *port = (struct bfa_port_s *) cbarg; 155 union bfi_port_i2h_msg_u *i2hmsg; 156 157 i2hmsg = (union bfi_port_i2h_msg_u *) m; 158 bfa_trc(port, m->mh.msg_id); 159 160 switch (m->mh.msg_id) { 161 case BFI_PORT_I2H_ENABLE_RSP: 162 if (port->endis_pending == BFA_FALSE) 163 break; 164 bfa_port_enable_isr(port, i2hmsg->enable_rsp.status); 165 break; 166 167 case BFI_PORT_I2H_DISABLE_RSP: 168 if (port->endis_pending == BFA_FALSE) 169 break; 170 bfa_port_disable_isr(port, i2hmsg->disable_rsp.status); 171 break; 172 173 case BFI_PORT_I2H_GET_STATS_RSP: 174 /* Stats busy flag is still set? (may be cmd timed out) */ 175 if (port->stats_busy == BFA_FALSE) 176 break; 177 bfa_port_get_stats_isr(port, i2hmsg->getstats_rsp.status); 178 break; 179 180 case BFI_PORT_I2H_CLEAR_STATS_RSP: 181 if (port->stats_busy == BFA_FALSE) 182 break; 183 bfa_port_clear_stats_isr(port, i2hmsg->clearstats_rsp.status); 184 break; 185 186 default: 187 WARN_ON(1); 188 } 189 } 190 191 /* 192 * bfa_port_meminfo() 193 * 194 * 195 * @param[in] void 196 * 197 * @return Size of DMA region 198 */ 199 u32 200 bfa_port_meminfo(void) 201 { 202 return BFA_ROUNDUP(sizeof(union bfa_port_stats_u), BFA_DMA_ALIGN_SZ); 203 } 204 205 /* 206 * bfa_port_mem_claim() 207 * 208 * 209 * @param[in] port Port module pointer 210 * dma_kva Kernel Virtual Address of Port DMA Memory 211 * dma_pa Physical Address of Port DMA Memory 212 * 213 * @return void 214 */ 215 void 216 bfa_port_mem_claim(struct bfa_port_s *port, u8 *dma_kva, u64 dma_pa) 217 { 218 port->stats_dma.kva = dma_kva; 219 port->stats_dma.pa = dma_pa; 220 } 221 222 /* 223 * bfa_port_enable() 224 * 225 * Send the Port enable request to the f/w 226 * 227 * @param[in] Pointer to the Port module data structure. 228 * 229 * @return Status 230 */ 231 bfa_status_t 232 bfa_port_enable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn, 233 void *cbarg) 234 { 235 struct bfi_port_generic_req_s *m; 236 237 /* If port is PBC disabled, return error */ 238 if (port->pbc_disabled) { 239 bfa_trc(port, BFA_STATUS_PBC); 240 return BFA_STATUS_PBC; 241 } 242 243 if (bfa_ioc_is_disabled(port->ioc)) { 244 bfa_trc(port, BFA_STATUS_IOC_DISABLED); 245 return BFA_STATUS_IOC_DISABLED; 246 } 247 248 if (!bfa_ioc_is_operational(port->ioc)) { 249 bfa_trc(port, BFA_STATUS_IOC_FAILURE); 250 return BFA_STATUS_IOC_FAILURE; 251 } 252 253 if (port->endis_pending) { 254 bfa_trc(port, BFA_STATUS_DEVBUSY); 255 return BFA_STATUS_DEVBUSY; 256 } 257 258 m = (struct bfi_port_generic_req_s *) port->endis_mb.msg; 259 260 port->msgtag++; 261 port->endis_cbfn = cbfn; 262 port->endis_cbarg = cbarg; 263 port->endis_pending = BFA_TRUE; 264 265 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_ENABLE_REQ, 266 bfa_ioc_portid(port->ioc)); 267 bfa_ioc_mbox_queue(port->ioc, &port->endis_mb); 268 269 return BFA_STATUS_OK; 270 } 271 272 /* 273 * bfa_port_disable() 274 * 275 * Send the Port disable request to the f/w 276 * 277 * @param[in] Pointer to the Port module data structure. 278 * 279 * @return Status 280 */ 281 bfa_status_t 282 bfa_port_disable(struct bfa_port_s *port, bfa_port_endis_cbfn_t cbfn, 283 void *cbarg) 284 { 285 struct bfi_port_generic_req_s *m; 286 287 /* If port is PBC disabled, return error */ 288 if (port->pbc_disabled) { 289 bfa_trc(port, BFA_STATUS_PBC); 290 return BFA_STATUS_PBC; 291 } 292 293 if (bfa_ioc_is_disabled(port->ioc)) { 294 bfa_trc(port, BFA_STATUS_IOC_DISABLED); 295 return BFA_STATUS_IOC_DISABLED; 296 } 297 298 if (!bfa_ioc_is_operational(port->ioc)) { 299 bfa_trc(port, BFA_STATUS_IOC_FAILURE); 300 return BFA_STATUS_IOC_FAILURE; 301 } 302 303 if (port->endis_pending) { 304 bfa_trc(port, BFA_STATUS_DEVBUSY); 305 return BFA_STATUS_DEVBUSY; 306 } 307 308 m = (struct bfi_port_generic_req_s *) port->endis_mb.msg; 309 310 port->msgtag++; 311 port->endis_cbfn = cbfn; 312 port->endis_cbarg = cbarg; 313 port->endis_pending = BFA_TRUE; 314 315 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_DISABLE_REQ, 316 bfa_ioc_portid(port->ioc)); 317 bfa_ioc_mbox_queue(port->ioc, &port->endis_mb); 318 319 return BFA_STATUS_OK; 320 } 321 322 /* 323 * bfa_port_get_stats() 324 * 325 * Send the request to the f/w to fetch Port statistics. 326 * 327 * @param[in] Pointer to the Port module data structure. 328 * 329 * @return Status 330 */ 331 bfa_status_t 332 bfa_port_get_stats(struct bfa_port_s *port, union bfa_port_stats_u *stats, 333 bfa_port_stats_cbfn_t cbfn, void *cbarg) 334 { 335 struct bfi_port_get_stats_req_s *m; 336 337 if (!bfa_ioc_is_operational(port->ioc)) { 338 bfa_trc(port, BFA_STATUS_IOC_FAILURE); 339 return BFA_STATUS_IOC_FAILURE; 340 } 341 342 if (port->stats_busy) { 343 bfa_trc(port, BFA_STATUS_DEVBUSY); 344 return BFA_STATUS_DEVBUSY; 345 } 346 347 m = (struct bfi_port_get_stats_req_s *) port->stats_mb.msg; 348 349 port->stats = stats; 350 port->stats_cbfn = cbfn; 351 port->stats_cbarg = cbarg; 352 port->stats_busy = BFA_TRUE; 353 bfa_dma_be_addr_set(m->dma_addr, port->stats_dma.pa); 354 355 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_GET_STATS_REQ, 356 bfa_ioc_portid(port->ioc)); 357 bfa_ioc_mbox_queue(port->ioc, &port->stats_mb); 358 359 return BFA_STATUS_OK; 360 } 361 362 /* 363 * bfa_port_clear_stats() 364 * 365 * 366 * @param[in] Pointer to the Port module data structure. 367 * 368 * @return Status 369 */ 370 bfa_status_t 371 bfa_port_clear_stats(struct bfa_port_s *port, bfa_port_stats_cbfn_t cbfn, 372 void *cbarg) 373 { 374 struct bfi_port_generic_req_s *m; 375 376 if (!bfa_ioc_is_operational(port->ioc)) { 377 bfa_trc(port, BFA_STATUS_IOC_FAILURE); 378 return BFA_STATUS_IOC_FAILURE; 379 } 380 381 if (port->stats_busy) { 382 bfa_trc(port, BFA_STATUS_DEVBUSY); 383 return BFA_STATUS_DEVBUSY; 384 } 385 386 m = (struct bfi_port_generic_req_s *) port->stats_mb.msg; 387 388 port->stats_cbfn = cbfn; 389 port->stats_cbarg = cbarg; 390 port->stats_busy = BFA_TRUE; 391 392 bfi_h2i_set(m->mh, BFI_MC_PORT, BFI_PORT_H2I_CLEAR_STATS_REQ, 393 bfa_ioc_portid(port->ioc)); 394 bfa_ioc_mbox_queue(port->ioc, &port->stats_mb); 395 396 return BFA_STATUS_OK; 397 } 398 399 /* 400 * bfa_port_notify() 401 * 402 * Port module IOC event handler 403 * 404 * @param[in] Pointer to the Port module data structure. 405 * @param[in] IOC event structure 406 * 407 * @return void 408 */ 409 void 410 bfa_port_notify(void *arg, enum bfa_ioc_event_e event) 411 { 412 struct bfa_port_s *port = (struct bfa_port_s *) arg; 413 414 switch (event) { 415 case BFA_IOC_E_DISABLED: 416 case BFA_IOC_E_FAILED: 417 /* Fail any pending get_stats/clear_stats requests */ 418 if (port->stats_busy) { 419 if (port->stats_cbfn) 420 port->stats_cbfn(port->stats_cbarg, 421 BFA_STATUS_FAILED); 422 port->stats_cbfn = NULL; 423 port->stats_busy = BFA_FALSE; 424 } 425 426 /* Clear any enable/disable is pending */ 427 if (port->endis_pending) { 428 if (port->endis_cbfn) 429 port->endis_cbfn(port->endis_cbarg, 430 BFA_STATUS_FAILED); 431 port->endis_cbfn = NULL; 432 port->endis_pending = BFA_FALSE; 433 } 434 break; 435 default: 436 break; 437 } 438 } 439 440 /* 441 * bfa_port_attach() 442 * 443 * 444 * @param[in] port - Pointer to the Port module data structure 445 * ioc - Pointer to the ioc module data structure 446 * dev - Pointer to the device driver module data structure 447 * The device driver specific mbox ISR functions have 448 * this pointer as one of the parameters. 449 * trcmod - 450 * 451 * @return void 452 */ 453 void 454 bfa_port_attach(struct bfa_port_s *port, struct bfa_ioc_s *ioc, 455 void *dev, struct bfa_trc_mod_s *trcmod) 456 { 457 struct timeval tv; 458 459 WARN_ON(!port); 460 461 port->dev = dev; 462 port->ioc = ioc; 463 port->trcmod = trcmod; 464 465 port->stats_busy = BFA_FALSE; 466 port->endis_pending = BFA_FALSE; 467 port->stats_cbfn = NULL; 468 port->endis_cbfn = NULL; 469 port->pbc_disabled = BFA_FALSE; 470 471 bfa_ioc_mbox_regisr(port->ioc, BFI_MC_PORT, bfa_port_isr, port); 472 bfa_q_qe_init(&port->ioc_notify); 473 bfa_ioc_notify_init(&port->ioc_notify, bfa_port_notify, port); 474 list_add_tail(&port->ioc_notify.qe, &port->ioc->notify_q); 475 476 /* 477 * initialize time stamp for stats reset 478 */ 479 do_gettimeofday(&tv); 480 port->stats_reset_time = tv.tv_sec; 481 482 bfa_trc(port, 0); 483 } 484 485 /* 486 * CEE module specific definitions 487 */ 488 489 /* 490 * bfa_cee_get_attr_isr() 491 * 492 * @brief CEE ISR for get-attributes responses from f/w 493 * 494 * @param[in] cee - Pointer to the CEE module 495 * status - Return status from the f/w 496 * 497 * @return void 498 */ 499 static void 500 bfa_cee_get_attr_isr(struct bfa_cee_s *cee, bfa_status_t status) 501 { 502 struct bfa_cee_lldp_cfg_s *lldp_cfg = &cee->attr->lldp_remote; 503 504 cee->get_attr_status = status; 505 bfa_trc(cee, 0); 506 if (status == BFA_STATUS_OK) { 507 bfa_trc(cee, 0); 508 memcpy(cee->attr, cee->attr_dma.kva, 509 sizeof(struct bfa_cee_attr_s)); 510 lldp_cfg->time_to_live = be16_to_cpu(lldp_cfg->time_to_live); 511 lldp_cfg->enabled_system_cap = 512 be16_to_cpu(lldp_cfg->enabled_system_cap); 513 } 514 cee->get_attr_pending = BFA_FALSE; 515 if (cee->cbfn.get_attr_cbfn) { 516 bfa_trc(cee, 0); 517 cee->cbfn.get_attr_cbfn(cee->cbfn.get_attr_cbarg, status); 518 } 519 } 520 521 /* 522 * bfa_cee_get_stats_isr() 523 * 524 * @brief CEE ISR for get-stats responses from f/w 525 * 526 * @param[in] cee - Pointer to the CEE module 527 * status - Return status from the f/w 528 * 529 * @return void 530 */ 531 static void 532 bfa_cee_get_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) 533 { 534 u32 *buffer; 535 int i; 536 537 cee->get_stats_status = status; 538 bfa_trc(cee, 0); 539 if (status == BFA_STATUS_OK) { 540 bfa_trc(cee, 0); 541 memcpy(cee->stats, cee->stats_dma.kva, 542 sizeof(struct bfa_cee_stats_s)); 543 /* swap the cee stats */ 544 buffer = (u32 *)cee->stats; 545 for (i = 0; i < (sizeof(struct bfa_cee_stats_s) / 546 sizeof(u32)); i++) 547 buffer[i] = cpu_to_be32(buffer[i]); 548 } 549 cee->get_stats_pending = BFA_FALSE; 550 bfa_trc(cee, 0); 551 if (cee->cbfn.get_stats_cbfn) { 552 bfa_trc(cee, 0); 553 cee->cbfn.get_stats_cbfn(cee->cbfn.get_stats_cbarg, status); 554 } 555 } 556 557 /* 558 * bfa_cee_reset_stats_isr() 559 * 560 * @brief CEE ISR for reset-stats responses from f/w 561 * 562 * @param[in] cee - Pointer to the CEE module 563 * status - Return status from the f/w 564 * 565 * @return void 566 */ 567 static void 568 bfa_cee_reset_stats_isr(struct bfa_cee_s *cee, bfa_status_t status) 569 { 570 cee->reset_stats_status = status; 571 cee->reset_stats_pending = BFA_FALSE; 572 if (cee->cbfn.reset_stats_cbfn) 573 cee->cbfn.reset_stats_cbfn(cee->cbfn.reset_stats_cbarg, status); 574 } 575 576 /* 577 * bfa_cee_meminfo() 578 * 579 * @brief Returns the size of the DMA memory needed by CEE module 580 * 581 * @param[in] void 582 * 583 * @return Size of DMA region 584 */ 585 u32 586 bfa_cee_meminfo(void) 587 { 588 return BFA_ROUNDUP(sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ) + 589 BFA_ROUNDUP(sizeof(struct bfa_cee_stats_s), BFA_DMA_ALIGN_SZ); 590 } 591 592 /* 593 * bfa_cee_mem_claim() 594 * 595 * @brief Initialized CEE DMA Memory 596 * 597 * @param[in] cee CEE module pointer 598 * dma_kva Kernel Virtual Address of CEE DMA Memory 599 * dma_pa Physical Address of CEE DMA Memory 600 * 601 * @return void 602 */ 603 void 604 bfa_cee_mem_claim(struct bfa_cee_s *cee, u8 *dma_kva, u64 dma_pa) 605 { 606 cee->attr_dma.kva = dma_kva; 607 cee->attr_dma.pa = dma_pa; 608 cee->stats_dma.kva = dma_kva + BFA_ROUNDUP( 609 sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); 610 cee->stats_dma.pa = dma_pa + BFA_ROUNDUP( 611 sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ); 612 cee->attr = (struct bfa_cee_attr_s *) dma_kva; 613 cee->stats = (struct bfa_cee_stats_s *) (dma_kva + BFA_ROUNDUP( 614 sizeof(struct bfa_cee_attr_s), BFA_DMA_ALIGN_SZ)); 615 } 616 617 /* 618 * bfa_cee_get_attr() 619 * 620 * @brief 621 * Send the request to the f/w to fetch CEE attributes. 622 * 623 * @param[in] Pointer to the CEE module data structure. 624 * 625 * @return Status 626 */ 627 628 bfa_status_t 629 bfa_cee_get_attr(struct bfa_cee_s *cee, struct bfa_cee_attr_s *attr, 630 bfa_cee_get_attr_cbfn_t cbfn, void *cbarg) 631 { 632 struct bfi_cee_get_req_s *cmd; 633 634 WARN_ON((cee == NULL) || (cee->ioc == NULL)); 635 bfa_trc(cee, 0); 636 if (!bfa_ioc_is_operational(cee->ioc)) { 637 bfa_trc(cee, 0); 638 return BFA_STATUS_IOC_FAILURE; 639 } 640 if (cee->get_attr_pending == BFA_TRUE) { 641 bfa_trc(cee, 0); 642 return BFA_STATUS_DEVBUSY; 643 } 644 cee->get_attr_pending = BFA_TRUE; 645 cmd = (struct bfi_cee_get_req_s *) cee->get_cfg_mb.msg; 646 cee->attr = attr; 647 cee->cbfn.get_attr_cbfn = cbfn; 648 cee->cbfn.get_attr_cbarg = cbarg; 649 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_CFG_REQ, 650 bfa_ioc_portid(cee->ioc)); 651 bfa_dma_be_addr_set(cmd->dma_addr, cee->attr_dma.pa); 652 bfa_ioc_mbox_queue(cee->ioc, &cee->get_cfg_mb); 653 654 return BFA_STATUS_OK; 655 } 656 657 /* 658 * bfa_cee_get_stats() 659 * 660 * @brief 661 * Send the request to the f/w to fetch CEE statistics. 662 * 663 * @param[in] Pointer to the CEE module data structure. 664 * 665 * @return Status 666 */ 667 668 bfa_status_t 669 bfa_cee_get_stats(struct bfa_cee_s *cee, struct bfa_cee_stats_s *stats, 670 bfa_cee_get_stats_cbfn_t cbfn, void *cbarg) 671 { 672 struct bfi_cee_get_req_s *cmd; 673 674 WARN_ON((cee == NULL) || (cee->ioc == NULL)); 675 676 if (!bfa_ioc_is_operational(cee->ioc)) { 677 bfa_trc(cee, 0); 678 return BFA_STATUS_IOC_FAILURE; 679 } 680 if (cee->get_stats_pending == BFA_TRUE) { 681 bfa_trc(cee, 0); 682 return BFA_STATUS_DEVBUSY; 683 } 684 cee->get_stats_pending = BFA_TRUE; 685 cmd = (struct bfi_cee_get_req_s *) cee->get_stats_mb.msg; 686 cee->stats = stats; 687 cee->cbfn.get_stats_cbfn = cbfn; 688 cee->cbfn.get_stats_cbarg = cbarg; 689 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_GET_STATS_REQ, 690 bfa_ioc_portid(cee->ioc)); 691 bfa_dma_be_addr_set(cmd->dma_addr, cee->stats_dma.pa); 692 bfa_ioc_mbox_queue(cee->ioc, &cee->get_stats_mb); 693 694 return BFA_STATUS_OK; 695 } 696 697 /* 698 * bfa_cee_reset_stats() 699 * 700 * @brief Clears CEE Stats in the f/w. 701 * 702 * @param[in] Pointer to the CEE module data structure. 703 * 704 * @return Status 705 */ 706 707 bfa_status_t 708 bfa_cee_reset_stats(struct bfa_cee_s *cee, 709 bfa_cee_reset_stats_cbfn_t cbfn, void *cbarg) 710 { 711 struct bfi_cee_reset_stats_s *cmd; 712 713 WARN_ON((cee == NULL) || (cee->ioc == NULL)); 714 if (!bfa_ioc_is_operational(cee->ioc)) { 715 bfa_trc(cee, 0); 716 return BFA_STATUS_IOC_FAILURE; 717 } 718 if (cee->reset_stats_pending == BFA_TRUE) { 719 bfa_trc(cee, 0); 720 return BFA_STATUS_DEVBUSY; 721 } 722 cee->reset_stats_pending = BFA_TRUE; 723 cmd = (struct bfi_cee_reset_stats_s *) cee->reset_stats_mb.msg; 724 cee->cbfn.reset_stats_cbfn = cbfn; 725 cee->cbfn.reset_stats_cbarg = cbarg; 726 bfi_h2i_set(cmd->mh, BFI_MC_CEE, BFI_CEE_H2I_RESET_STATS, 727 bfa_ioc_portid(cee->ioc)); 728 bfa_ioc_mbox_queue(cee->ioc, &cee->reset_stats_mb); 729 730 return BFA_STATUS_OK; 731 } 732 733 /* 734 * bfa_cee_isrs() 735 * 736 * @brief Handles Mail-box interrupts for CEE module. 737 * 738 * @param[in] Pointer to the CEE module data structure. 739 * 740 * @return void 741 */ 742 743 void 744 bfa_cee_isr(void *cbarg, struct bfi_mbmsg_s *m) 745 { 746 union bfi_cee_i2h_msg_u *msg; 747 struct bfi_cee_get_rsp_s *get_rsp; 748 struct bfa_cee_s *cee = (struct bfa_cee_s *) cbarg; 749 msg = (union bfi_cee_i2h_msg_u *) m; 750 get_rsp = (struct bfi_cee_get_rsp_s *) m; 751 bfa_trc(cee, msg->mh.msg_id); 752 switch (msg->mh.msg_id) { 753 case BFI_CEE_I2H_GET_CFG_RSP: 754 bfa_trc(cee, get_rsp->cmd_status); 755 bfa_cee_get_attr_isr(cee, get_rsp->cmd_status); 756 break; 757 case BFI_CEE_I2H_GET_STATS_RSP: 758 bfa_cee_get_stats_isr(cee, get_rsp->cmd_status); 759 break; 760 case BFI_CEE_I2H_RESET_STATS_RSP: 761 bfa_cee_reset_stats_isr(cee, get_rsp->cmd_status); 762 break; 763 default: 764 WARN_ON(1); 765 } 766 } 767 768 /* 769 * bfa_cee_notify() 770 * 771 * @brief CEE module IOC event handler. 772 * 773 * @param[in] Pointer to the CEE module data structure. 774 * @param[in] IOC event type 775 * 776 * @return void 777 */ 778 779 void 780 bfa_cee_notify(void *arg, enum bfa_ioc_event_e event) 781 { 782 struct bfa_cee_s *cee = (struct bfa_cee_s *) arg; 783 784 bfa_trc(cee, event); 785 786 switch (event) { 787 case BFA_IOC_E_DISABLED: 788 case BFA_IOC_E_FAILED: 789 if (cee->get_attr_pending == BFA_TRUE) { 790 cee->get_attr_status = BFA_STATUS_FAILED; 791 cee->get_attr_pending = BFA_FALSE; 792 if (cee->cbfn.get_attr_cbfn) { 793 cee->cbfn.get_attr_cbfn( 794 cee->cbfn.get_attr_cbarg, 795 BFA_STATUS_FAILED); 796 } 797 } 798 if (cee->get_stats_pending == BFA_TRUE) { 799 cee->get_stats_status = BFA_STATUS_FAILED; 800 cee->get_stats_pending = BFA_FALSE; 801 if (cee->cbfn.get_stats_cbfn) { 802 cee->cbfn.get_stats_cbfn( 803 cee->cbfn.get_stats_cbarg, 804 BFA_STATUS_FAILED); 805 } 806 } 807 if (cee->reset_stats_pending == BFA_TRUE) { 808 cee->reset_stats_status = BFA_STATUS_FAILED; 809 cee->reset_stats_pending = BFA_FALSE; 810 if (cee->cbfn.reset_stats_cbfn) { 811 cee->cbfn.reset_stats_cbfn( 812 cee->cbfn.reset_stats_cbarg, 813 BFA_STATUS_FAILED); 814 } 815 } 816 break; 817 818 default: 819 break; 820 } 821 } 822 823 /* 824 * bfa_cee_attach() 825 * 826 * @brief CEE module-attach API 827 * 828 * @param[in] cee - Pointer to the CEE module data structure 829 * ioc - Pointer to the ioc module data structure 830 * dev - Pointer to the device driver module data structure 831 * The device driver specific mbox ISR functions have 832 * this pointer as one of the parameters. 833 * 834 * @return void 835 */ 836 void 837 bfa_cee_attach(struct bfa_cee_s *cee, struct bfa_ioc_s *ioc, 838 void *dev) 839 { 840 WARN_ON(cee == NULL); 841 cee->dev = dev; 842 cee->ioc = ioc; 843 844 bfa_ioc_mbox_regisr(cee->ioc, BFI_MC_CEE, bfa_cee_isr, cee); 845 bfa_q_qe_init(&cee->ioc_notify); 846 bfa_ioc_notify_init(&cee->ioc_notify, bfa_cee_notify, cee); 847 list_add_tail(&cee->ioc_notify.qe, &cee->ioc->notify_q); 848 } 849