1/* 2 * Copyright (c) 2005-2009 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 <bfa.h> 19#include <bfa_fcpim.h> 20#include "bfa_fcpim_priv.h" 21 22BFA_TRC_FILE(HAL, ITNIM); 23 24#define BFA_ITNIM_FROM_TAG(_fcpim, _tag) \ 25 ((_fcpim)->itnim_arr + ((_tag) & ((_fcpim)->num_itnims - 1))) 26 27#define bfa_fcpim_additn(__itnim) \ 28 list_add_tail(&(__itnim)->qe, &(__itnim)->fcpim->itnim_q) 29#define bfa_fcpim_delitn(__itnim) do { \ 30 bfa_assert(bfa_q_is_on_q(&(__itnim)->fcpim->itnim_q, __itnim)); \ 31 list_del(&(__itnim)->qe); \ 32 bfa_assert(list_empty(&(__itnim)->io_q)); \ 33 bfa_assert(list_empty(&(__itnim)->io_cleanup_q)); \ 34 bfa_assert(list_empty(&(__itnim)->pending_q)); \ 35} while (0) 36 37#define bfa_itnim_online_cb(__itnim) do { \ 38 if ((__itnim)->bfa->fcs) \ 39 bfa_cb_itnim_online((__itnim)->ditn); \ 40 else { \ 41 bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \ 42 __bfa_cb_itnim_online, (__itnim)); \ 43 } \ 44} while (0) 45 46#define bfa_itnim_offline_cb(__itnim) do { \ 47 if ((__itnim)->bfa->fcs) \ 48 bfa_cb_itnim_offline((__itnim)->ditn); \ 49 else { \ 50 bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \ 51 __bfa_cb_itnim_offline, (__itnim)); \ 52 } \ 53} while (0) 54 55#define bfa_itnim_sler_cb(__itnim) do { \ 56 if ((__itnim)->bfa->fcs) \ 57 bfa_cb_itnim_sler((__itnim)->ditn); \ 58 else { \ 59 bfa_cb_queue((__itnim)->bfa, &(__itnim)->hcb_qe, \ 60 __bfa_cb_itnim_sler, (__itnim)); \ 61 } \ 62} while (0) 63 64/* 65 * forward declarations 66 */ 67static void bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim); 68static bfa_boolean_t bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim); 69static bfa_boolean_t bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim); 70static void bfa_itnim_cleanp_comp(void *itnim_cbarg); 71static void bfa_itnim_cleanup(struct bfa_itnim_s *itnim); 72static void __bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete); 73static void __bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete); 74static void __bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete); 75static void bfa_itnim_iotov_online(struct bfa_itnim_s *itnim); 76static void bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim); 77static void bfa_itnim_iotov(void *itnim_arg); 78static void bfa_itnim_iotov_start(struct bfa_itnim_s *itnim); 79static void bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim); 80static void bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim); 81 82/** 83 * bfa_itnim_sm BFA itnim state machine 84 */ 85 86 87enum bfa_itnim_event { 88 BFA_ITNIM_SM_CREATE = 1, /* itnim is created */ 89 BFA_ITNIM_SM_ONLINE = 2, /* itnim is online */ 90 BFA_ITNIM_SM_OFFLINE = 3, /* itnim is offline */ 91 BFA_ITNIM_SM_FWRSP = 4, /* firmware response */ 92 BFA_ITNIM_SM_DELETE = 5, /* deleting an existing itnim */ 93 BFA_ITNIM_SM_CLEANUP = 6, /* IO cleanup completion */ 94 BFA_ITNIM_SM_SLER = 7, /* second level error recovery */ 95 BFA_ITNIM_SM_HWFAIL = 8, /* IOC h/w failure event */ 96 BFA_ITNIM_SM_QRESUME = 9, /* queue space available */ 97}; 98 99static void bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, 100 enum bfa_itnim_event event); 101static void bfa_itnim_sm_created(struct bfa_itnim_s *itnim, 102 enum bfa_itnim_event event); 103static void bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, 104 enum bfa_itnim_event event); 105static void bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, 106 enum bfa_itnim_event event); 107static void bfa_itnim_sm_online(struct bfa_itnim_s *itnim, 108 enum bfa_itnim_event event); 109static void bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, 110 enum bfa_itnim_event event); 111static void bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, 112 enum bfa_itnim_event event); 113static void bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim, 114 enum bfa_itnim_event event); 115static void bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, 116 enum bfa_itnim_event event); 117static void bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, 118 enum bfa_itnim_event event); 119static void bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim, 120 enum bfa_itnim_event event); 121static void bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, 122 enum bfa_itnim_event event); 123static void bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim, 124 enum bfa_itnim_event event); 125static void bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim, 126 enum bfa_itnim_event event); 127static void bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, 128 enum bfa_itnim_event event); 129 130/** 131 * Beginning/unallocated state - no events expected. 132 */ 133static void 134bfa_itnim_sm_uninit(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 135{ 136 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 137 bfa_trc(itnim->bfa, event); 138 139 switch (event) { 140 case BFA_ITNIM_SM_CREATE: 141 bfa_sm_set_state(itnim, bfa_itnim_sm_created); 142 itnim->is_online = BFA_FALSE; 143 bfa_fcpim_additn(itnim); 144 break; 145 146 default: 147 bfa_sm_fault(itnim->bfa, event); 148 } 149} 150 151/** 152 * Beginning state, only online event expected. 153 */ 154static void 155bfa_itnim_sm_created(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 156{ 157 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 158 bfa_trc(itnim->bfa, event); 159 160 switch (event) { 161 case BFA_ITNIM_SM_ONLINE: 162 if (bfa_itnim_send_fwcreate(itnim)) 163 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); 164 else 165 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull); 166 break; 167 168 case BFA_ITNIM_SM_DELETE: 169 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 170 bfa_fcpim_delitn(itnim); 171 break; 172 173 case BFA_ITNIM_SM_HWFAIL: 174 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 175 break; 176 177 default: 178 bfa_sm_fault(itnim->bfa, event); 179 } 180} 181 182/** 183 * Waiting for itnim create response from firmware. 184 */ 185static void 186bfa_itnim_sm_fwcreate(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 187{ 188 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 189 bfa_trc(itnim->bfa, event); 190 191 switch (event) { 192 case BFA_ITNIM_SM_FWRSP: 193 bfa_sm_set_state(itnim, bfa_itnim_sm_online); 194 itnim->is_online = BFA_TRUE; 195 bfa_itnim_iotov_online(itnim); 196 bfa_itnim_online_cb(itnim); 197 break; 198 199 case BFA_ITNIM_SM_DELETE: 200 bfa_sm_set_state(itnim, bfa_itnim_sm_delete_pending); 201 break; 202 203 case BFA_ITNIM_SM_OFFLINE: 204 if (bfa_itnim_send_fwdelete(itnim)) 205 bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete); 206 else 207 bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull); 208 break; 209 210 case BFA_ITNIM_SM_HWFAIL: 211 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 212 break; 213 214 default: 215 bfa_sm_fault(itnim->bfa, event); 216 } 217} 218 219static void 220bfa_itnim_sm_fwcreate_qfull(struct bfa_itnim_s *itnim, 221 enum bfa_itnim_event event) 222{ 223 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 224 bfa_trc(itnim->bfa, event); 225 226 switch (event) { 227 case BFA_ITNIM_SM_QRESUME: 228 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); 229 bfa_itnim_send_fwcreate(itnim); 230 break; 231 232 case BFA_ITNIM_SM_DELETE: 233 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 234 bfa_reqq_wcancel(&itnim->reqq_wait); 235 bfa_fcpim_delitn(itnim); 236 break; 237 238 case BFA_ITNIM_SM_OFFLINE: 239 bfa_sm_set_state(itnim, bfa_itnim_sm_offline); 240 bfa_reqq_wcancel(&itnim->reqq_wait); 241 bfa_itnim_offline_cb(itnim); 242 break; 243 244 case BFA_ITNIM_SM_HWFAIL: 245 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 246 bfa_reqq_wcancel(&itnim->reqq_wait); 247 break; 248 249 default: 250 bfa_sm_fault(itnim->bfa, event); 251 } 252} 253 254/** 255 * Waiting for itnim create response from firmware, a delete is pending. 256 */ 257static void 258bfa_itnim_sm_delete_pending(struct bfa_itnim_s *itnim, 259 enum bfa_itnim_event event) 260{ 261 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 262 bfa_trc(itnim->bfa, event); 263 264 switch (event) { 265 case BFA_ITNIM_SM_FWRSP: 266 if (bfa_itnim_send_fwdelete(itnim)) 267 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); 268 else 269 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull); 270 break; 271 272 case BFA_ITNIM_SM_HWFAIL: 273 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 274 bfa_fcpim_delitn(itnim); 275 break; 276 277 default: 278 bfa_sm_fault(itnim->bfa, event); 279 } 280} 281 282/** 283 * Online state - normal parking state. 284 */ 285static void 286bfa_itnim_sm_online(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 287{ 288 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 289 bfa_trc(itnim->bfa, event); 290 291 switch (event) { 292 case BFA_ITNIM_SM_OFFLINE: 293 bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline); 294 itnim->is_online = BFA_FALSE; 295 bfa_itnim_iotov_start(itnim); 296 bfa_itnim_cleanup(itnim); 297 break; 298 299 case BFA_ITNIM_SM_DELETE: 300 bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete); 301 itnim->is_online = BFA_FALSE; 302 bfa_itnim_cleanup(itnim); 303 break; 304 305 case BFA_ITNIM_SM_SLER: 306 bfa_sm_set_state(itnim, bfa_itnim_sm_sler); 307 itnim->is_online = BFA_FALSE; 308 bfa_itnim_iotov_start(itnim); 309 bfa_itnim_sler_cb(itnim); 310 break; 311 312 case BFA_ITNIM_SM_HWFAIL: 313 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 314 itnim->is_online = BFA_FALSE; 315 bfa_itnim_iotov_start(itnim); 316 bfa_itnim_iocdisable_cleanup(itnim); 317 break; 318 319 default: 320 bfa_sm_fault(itnim->bfa, event); 321 } 322} 323 324/** 325 * Second level error recovery need. 326 */ 327static void 328bfa_itnim_sm_sler(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 329{ 330 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 331 bfa_trc(itnim->bfa, event); 332 333 switch (event) { 334 case BFA_ITNIM_SM_OFFLINE: 335 bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_offline); 336 bfa_itnim_cleanup(itnim); 337 break; 338 339 case BFA_ITNIM_SM_DELETE: 340 bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete); 341 bfa_itnim_cleanup(itnim); 342 bfa_itnim_iotov_delete(itnim); 343 break; 344 345 case BFA_ITNIM_SM_HWFAIL: 346 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 347 bfa_itnim_iocdisable_cleanup(itnim); 348 break; 349 350 default: 351 bfa_sm_fault(itnim->bfa, event); 352 } 353} 354 355/** 356 * Going offline. Waiting for active IO cleanup. 357 */ 358static void 359bfa_itnim_sm_cleanup_offline(struct bfa_itnim_s *itnim, 360 enum bfa_itnim_event event) 361{ 362 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 363 bfa_trc(itnim->bfa, event); 364 365 switch (event) { 366 case BFA_ITNIM_SM_CLEANUP: 367 if (bfa_itnim_send_fwdelete(itnim)) 368 bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete); 369 else 370 bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete_qfull); 371 break; 372 373 case BFA_ITNIM_SM_DELETE: 374 bfa_sm_set_state(itnim, bfa_itnim_sm_cleanup_delete); 375 bfa_itnim_iotov_delete(itnim); 376 break; 377 378 case BFA_ITNIM_SM_HWFAIL: 379 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 380 bfa_itnim_iocdisable_cleanup(itnim); 381 bfa_itnim_offline_cb(itnim); 382 break; 383 384 case BFA_ITNIM_SM_SLER: 385 break; 386 387 default: 388 bfa_sm_fault(itnim->bfa, event); 389 } 390} 391 392/** 393 * Deleting itnim. Waiting for active IO cleanup. 394 */ 395static void 396bfa_itnim_sm_cleanup_delete(struct bfa_itnim_s *itnim, 397 enum bfa_itnim_event event) 398{ 399 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 400 bfa_trc(itnim->bfa, event); 401 402 switch (event) { 403 case BFA_ITNIM_SM_CLEANUP: 404 if (bfa_itnim_send_fwdelete(itnim)) 405 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); 406 else 407 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull); 408 break; 409 410 case BFA_ITNIM_SM_HWFAIL: 411 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 412 bfa_itnim_iocdisable_cleanup(itnim); 413 break; 414 415 default: 416 bfa_sm_fault(itnim->bfa, event); 417 } 418} 419 420/** 421 * Rport offline. Fimrware itnim is being deleted - awaiting f/w response. 422 */ 423static void 424bfa_itnim_sm_fwdelete(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 425{ 426 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 427 bfa_trc(itnim->bfa, event); 428 429 switch (event) { 430 case BFA_ITNIM_SM_FWRSP: 431 bfa_sm_set_state(itnim, bfa_itnim_sm_offline); 432 bfa_itnim_offline_cb(itnim); 433 break; 434 435 case BFA_ITNIM_SM_DELETE: 436 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); 437 break; 438 439 case BFA_ITNIM_SM_HWFAIL: 440 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 441 bfa_itnim_offline_cb(itnim); 442 break; 443 444 default: 445 bfa_sm_fault(itnim->bfa, event); 446 } 447} 448 449static void 450bfa_itnim_sm_fwdelete_qfull(struct bfa_itnim_s *itnim, 451 enum bfa_itnim_event event) 452{ 453 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 454 bfa_trc(itnim->bfa, event); 455 456 switch (event) { 457 case BFA_ITNIM_SM_QRESUME: 458 bfa_sm_set_state(itnim, bfa_itnim_sm_fwdelete); 459 bfa_itnim_send_fwdelete(itnim); 460 break; 461 462 case BFA_ITNIM_SM_DELETE: 463 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting_qfull); 464 break; 465 466 case BFA_ITNIM_SM_HWFAIL: 467 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 468 bfa_reqq_wcancel(&itnim->reqq_wait); 469 bfa_itnim_offline_cb(itnim); 470 break; 471 472 default: 473 bfa_sm_fault(itnim->bfa, event); 474 } 475} 476 477/** 478 * Offline state. 479 */ 480static void 481bfa_itnim_sm_offline(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 482{ 483 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 484 bfa_trc(itnim->bfa, event); 485 486 switch (event) { 487 case BFA_ITNIM_SM_DELETE: 488 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 489 bfa_itnim_iotov_delete(itnim); 490 bfa_fcpim_delitn(itnim); 491 break; 492 493 case BFA_ITNIM_SM_ONLINE: 494 if (bfa_itnim_send_fwcreate(itnim)) 495 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); 496 else 497 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull); 498 break; 499 500 case BFA_ITNIM_SM_HWFAIL: 501 bfa_sm_set_state(itnim, bfa_itnim_sm_iocdisable); 502 break; 503 504 default: 505 bfa_sm_fault(itnim->bfa, event); 506 } 507} 508 509/** 510 * IOC h/w failed state. 511 */ 512static void 513bfa_itnim_sm_iocdisable(struct bfa_itnim_s *itnim, 514 enum bfa_itnim_event event) 515{ 516 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 517 bfa_trc(itnim->bfa, event); 518 519 switch (event) { 520 case BFA_ITNIM_SM_DELETE: 521 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 522 bfa_itnim_iotov_delete(itnim); 523 bfa_fcpim_delitn(itnim); 524 break; 525 526 case BFA_ITNIM_SM_OFFLINE: 527 bfa_itnim_offline_cb(itnim); 528 break; 529 530 case BFA_ITNIM_SM_ONLINE: 531 if (bfa_itnim_send_fwcreate(itnim)) 532 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate); 533 else 534 bfa_sm_set_state(itnim, bfa_itnim_sm_fwcreate_qfull); 535 break; 536 537 case BFA_ITNIM_SM_HWFAIL: 538 break; 539 540 default: 541 bfa_sm_fault(itnim->bfa, event); 542 } 543} 544 545/** 546 * Itnim is deleted, waiting for firmware response to delete. 547 */ 548static void 549bfa_itnim_sm_deleting(struct bfa_itnim_s *itnim, enum bfa_itnim_event event) 550{ 551 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 552 bfa_trc(itnim->bfa, event); 553 554 switch (event) { 555 case BFA_ITNIM_SM_FWRSP: 556 case BFA_ITNIM_SM_HWFAIL: 557 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 558 bfa_fcpim_delitn(itnim); 559 break; 560 561 default: 562 bfa_sm_fault(itnim->bfa, event); 563 } 564} 565 566static void 567bfa_itnim_sm_deleting_qfull(struct bfa_itnim_s *itnim, 568 enum bfa_itnim_event event) 569{ 570 bfa_trc(itnim->bfa, itnim->rport->rport_tag); 571 bfa_trc(itnim->bfa, event); 572 573 switch (event) { 574 case BFA_ITNIM_SM_QRESUME: 575 bfa_sm_set_state(itnim, bfa_itnim_sm_deleting); 576 bfa_itnim_send_fwdelete(itnim); 577 break; 578 579 case BFA_ITNIM_SM_HWFAIL: 580 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 581 bfa_reqq_wcancel(&itnim->reqq_wait); 582 bfa_fcpim_delitn(itnim); 583 break; 584 585 default: 586 bfa_sm_fault(itnim->bfa, event); 587 } 588} 589 590 591 592/** 593 * bfa_itnim_private 594 */ 595 596/** 597 * Initiate cleanup of all IOs on an IOC failure. 598 */ 599static void 600bfa_itnim_iocdisable_cleanup(struct bfa_itnim_s *itnim) 601{ 602 struct bfa_tskim_s *tskim; 603 struct bfa_ioim_s *ioim; 604 struct list_head *qe, *qen; 605 606 list_for_each_safe(qe, qen, &itnim->tsk_q) { 607 tskim = (struct bfa_tskim_s *) qe; 608 bfa_tskim_iocdisable(tskim); 609 } 610 611 list_for_each_safe(qe, qen, &itnim->io_q) { 612 ioim = (struct bfa_ioim_s *) qe; 613 bfa_ioim_iocdisable(ioim); 614 } 615 616 /** 617 * For IO request in pending queue, we pretend an early timeout. 618 */ 619 list_for_each_safe(qe, qen, &itnim->pending_q) { 620 ioim = (struct bfa_ioim_s *) qe; 621 bfa_ioim_tov(ioim); 622 } 623 624 list_for_each_safe(qe, qen, &itnim->io_cleanup_q) { 625 ioim = (struct bfa_ioim_s *) qe; 626 bfa_ioim_iocdisable(ioim); 627 } 628} 629 630/** 631 * IO cleanup completion 632 */ 633static void 634bfa_itnim_cleanp_comp(void *itnim_cbarg) 635{ 636 struct bfa_itnim_s *itnim = itnim_cbarg; 637 638 bfa_stats(itnim, cleanup_comps); 639 bfa_sm_send_event(itnim, BFA_ITNIM_SM_CLEANUP); 640} 641 642/** 643 * Initiate cleanup of all IOs. 644 */ 645static void 646bfa_itnim_cleanup(struct bfa_itnim_s *itnim) 647{ 648 struct bfa_ioim_s *ioim; 649 struct bfa_tskim_s *tskim; 650 struct list_head *qe, *qen; 651 652 bfa_wc_init(&itnim->wc, bfa_itnim_cleanp_comp, itnim); 653 654 list_for_each_safe(qe, qen, &itnim->io_q) { 655 ioim = (struct bfa_ioim_s *) qe; 656 657 /** 658 * Move IO to a cleanup queue from active queue so that a later 659 * TM will not pickup this IO. 660 */ 661 list_del(&ioim->qe); 662 list_add_tail(&ioim->qe, &itnim->io_cleanup_q); 663 664 bfa_wc_up(&itnim->wc); 665 bfa_ioim_cleanup(ioim); 666 } 667 668 list_for_each_safe(qe, qen, &itnim->tsk_q) { 669 tskim = (struct bfa_tskim_s *) qe; 670 bfa_wc_up(&itnim->wc); 671 bfa_tskim_cleanup(tskim); 672 } 673 674 bfa_wc_wait(&itnim->wc); 675} 676 677static void 678__bfa_cb_itnim_online(void *cbarg, bfa_boolean_t complete) 679{ 680 struct bfa_itnim_s *itnim = cbarg; 681 682 if (complete) 683 bfa_cb_itnim_online(itnim->ditn); 684} 685 686static void 687__bfa_cb_itnim_offline(void *cbarg, bfa_boolean_t complete) 688{ 689 struct bfa_itnim_s *itnim = cbarg; 690 691 if (complete) 692 bfa_cb_itnim_offline(itnim->ditn); 693} 694 695static void 696__bfa_cb_itnim_sler(void *cbarg, bfa_boolean_t complete) 697{ 698 struct bfa_itnim_s *itnim = cbarg; 699 700 if (complete) 701 bfa_cb_itnim_sler(itnim->ditn); 702} 703 704/** 705 * Call to resume any I/O requests waiting for room in request queue. 706 */ 707static void 708bfa_itnim_qresume(void *cbarg) 709{ 710 struct bfa_itnim_s *itnim = cbarg; 711 712 bfa_sm_send_event(itnim, BFA_ITNIM_SM_QRESUME); 713} 714 715 716 717 718/** 719 * bfa_itnim_public 720 */ 721 722void 723bfa_itnim_iodone(struct bfa_itnim_s *itnim) 724{ 725 bfa_wc_down(&itnim->wc); 726} 727 728void 729bfa_itnim_tskdone(struct bfa_itnim_s *itnim) 730{ 731 bfa_wc_down(&itnim->wc); 732} 733 734void 735bfa_itnim_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, 736 u32 *dm_len) 737{ 738 /** 739 * ITN memory 740 */ 741 *km_len += cfg->fwcfg.num_rports * sizeof(struct bfa_itnim_s); 742} 743 744void 745bfa_itnim_attach(struct bfa_fcpim_mod_s *fcpim, struct bfa_meminfo_s *minfo) 746{ 747 struct bfa_s *bfa = fcpim->bfa; 748 struct bfa_itnim_s *itnim; 749 int i; 750 751 INIT_LIST_HEAD(&fcpim->itnim_q); 752 753 itnim = (struct bfa_itnim_s *) bfa_meminfo_kva(minfo); 754 fcpim->itnim_arr = itnim; 755 756 for (i = 0; i < fcpim->num_itnims; i++, itnim++) { 757 bfa_os_memset(itnim, 0, sizeof(struct bfa_itnim_s)); 758 itnim->bfa = bfa; 759 itnim->fcpim = fcpim; 760 itnim->reqq = BFA_REQQ_QOS_LO; 761 itnim->rport = BFA_RPORT_FROM_TAG(bfa, i); 762 itnim->iotov_active = BFA_FALSE; 763 bfa_reqq_winit(&itnim->reqq_wait, bfa_itnim_qresume, itnim); 764 765 INIT_LIST_HEAD(&itnim->io_q); 766 INIT_LIST_HEAD(&itnim->io_cleanup_q); 767 INIT_LIST_HEAD(&itnim->pending_q); 768 INIT_LIST_HEAD(&itnim->tsk_q); 769 INIT_LIST_HEAD(&itnim->delay_comp_q); 770 bfa_sm_set_state(itnim, bfa_itnim_sm_uninit); 771 } 772 773 bfa_meminfo_kva(minfo) = (u8 *) itnim; 774} 775 776void 777bfa_itnim_iocdisable(struct bfa_itnim_s *itnim) 778{ 779 bfa_stats(itnim, ioc_disabled); 780 bfa_sm_send_event(itnim, BFA_ITNIM_SM_HWFAIL); 781} 782 783static bfa_boolean_t 784bfa_itnim_send_fwcreate(struct bfa_itnim_s *itnim) 785{ 786 struct bfi_itnim_create_req_s *m; 787 788 itnim->msg_no++; 789 790 /** 791 * check for room in queue to send request now 792 */ 793 m = bfa_reqq_next(itnim->bfa, itnim->reqq); 794 if (!m) { 795 bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait); 796 return BFA_FALSE; 797 } 798 799 bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_CREATE_REQ, 800 bfa_lpuid(itnim->bfa)); 801 m->fw_handle = itnim->rport->fw_handle; 802 m->class = FC_CLASS_3; 803 m->seq_rec = itnim->seq_rec; 804 m->msg_no = itnim->msg_no; 805 806 /** 807 * queue I/O message to firmware 808 */ 809 bfa_reqq_produce(itnim->bfa, itnim->reqq); 810 return BFA_TRUE; 811} 812 813static bfa_boolean_t 814bfa_itnim_send_fwdelete(struct bfa_itnim_s *itnim) 815{ 816 struct bfi_itnim_delete_req_s *m; 817 818 /** 819 * check for room in queue to send request now 820 */ 821 m = bfa_reqq_next(itnim->bfa, itnim->reqq); 822 if (!m) { 823 bfa_reqq_wait(itnim->bfa, itnim->reqq, &itnim->reqq_wait); 824 return BFA_FALSE; 825 } 826 827 bfi_h2i_set(m->mh, BFI_MC_ITNIM, BFI_ITNIM_H2I_DELETE_REQ, 828 bfa_lpuid(itnim->bfa)); 829 m->fw_handle = itnim->rport->fw_handle; 830 831 /** 832 * queue I/O message to firmware 833 */ 834 bfa_reqq_produce(itnim->bfa, itnim->reqq); 835 return BFA_TRUE; 836} 837 838/** 839 * Cleanup all pending failed inflight requests. 840 */ 841static void 842bfa_itnim_delayed_comp(struct bfa_itnim_s *itnim, bfa_boolean_t iotov) 843{ 844 struct bfa_ioim_s *ioim; 845 struct list_head *qe, *qen; 846 847 list_for_each_safe(qe, qen, &itnim->delay_comp_q) { 848 ioim = (struct bfa_ioim_s *)qe; 849 bfa_ioim_delayed_comp(ioim, iotov); 850 } 851} 852 853/** 854 * Start all pending IO requests. 855 */ 856static void 857bfa_itnim_iotov_online(struct bfa_itnim_s *itnim) 858{ 859 struct bfa_ioim_s *ioim; 860 861 bfa_itnim_iotov_stop(itnim); 862 863 /** 864 * Abort all inflight IO requests in the queue 865 */ 866 bfa_itnim_delayed_comp(itnim, BFA_FALSE); 867 868 /** 869 * Start all pending IO requests. 870 */ 871 while (!list_empty(&itnim->pending_q)) { 872 bfa_q_deq(&itnim->pending_q, &ioim); 873 list_add_tail(&ioim->qe, &itnim->io_q); 874 bfa_ioim_start(ioim); 875 } 876} 877 878/** 879 * Fail all pending IO requests 880 */ 881static void 882bfa_itnim_iotov_cleanup(struct bfa_itnim_s *itnim) 883{ 884 struct bfa_ioim_s *ioim; 885 886 /** 887 * Fail all inflight IO requests in the queue 888 */ 889 bfa_itnim_delayed_comp(itnim, BFA_TRUE); 890 891 /** 892 * Fail any pending IO requests. 893 */ 894 while (!list_empty(&itnim->pending_q)) { 895 bfa_q_deq(&itnim->pending_q, &ioim); 896 list_add_tail(&ioim->qe, &ioim->fcpim->ioim_comp_q); 897 bfa_ioim_tov(ioim); 898 } 899} 900 901/** 902 * IO TOV timer callback. Fail any pending IO requests. 903 */ 904static void 905bfa_itnim_iotov(void *itnim_arg) 906{ 907 struct bfa_itnim_s *itnim = itnim_arg; 908 909 itnim->iotov_active = BFA_FALSE; 910 911 bfa_cb_itnim_tov_begin(itnim->ditn); 912 bfa_itnim_iotov_cleanup(itnim); 913 bfa_cb_itnim_tov(itnim->ditn); 914} 915 916/** 917 * Start IO TOV timer for failing back pending IO requests in offline state. 918 */ 919static void 920bfa_itnim_iotov_start(struct bfa_itnim_s *itnim) 921{ 922 if (itnim->fcpim->path_tov > 0) { 923 924 itnim->iotov_active = BFA_TRUE; 925 bfa_assert(bfa_itnim_hold_io(itnim)); 926 bfa_timer_start(itnim->bfa, &itnim->timer, 927 bfa_itnim_iotov, itnim, itnim->fcpim->path_tov); 928 } 929} 930 931/** 932 * Stop IO TOV timer. 933 */ 934static void 935bfa_itnim_iotov_stop(struct bfa_itnim_s *itnim) 936{ 937 if (itnim->iotov_active) { 938 itnim->iotov_active = BFA_FALSE; 939 bfa_timer_stop(&itnim->timer); 940 } 941} 942 943/** 944 * Stop IO TOV timer. 945 */ 946static void 947bfa_itnim_iotov_delete(struct bfa_itnim_s *itnim) 948{ 949 bfa_boolean_t pathtov_active = BFA_FALSE; 950 951 if (itnim->iotov_active) 952 pathtov_active = BFA_TRUE; 953 954 bfa_itnim_iotov_stop(itnim); 955 if (pathtov_active) 956 bfa_cb_itnim_tov_begin(itnim->ditn); 957 bfa_itnim_iotov_cleanup(itnim); 958 if (pathtov_active) 959 bfa_cb_itnim_tov(itnim->ditn); 960} 961 962 963 964/** 965 * bfa_itnim_public 966 */ 967 968/** 969 * Itnim interrupt processing. 970 */ 971void 972bfa_itnim_isr(struct bfa_s *bfa, struct bfi_msg_s *m) 973{ 974 struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); 975 union bfi_itnim_i2h_msg_u msg; 976 struct bfa_itnim_s *itnim; 977 978 bfa_trc(bfa, m->mhdr.msg_id); 979 980 msg.msg = m; 981 982 switch (m->mhdr.msg_id) { 983 case BFI_ITNIM_I2H_CREATE_RSP: 984 itnim = BFA_ITNIM_FROM_TAG(fcpim, 985 msg.create_rsp->bfa_handle); 986 bfa_assert(msg.create_rsp->status == BFA_STATUS_OK); 987 bfa_stats(itnim, create_comps); 988 bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP); 989 break; 990 991 case BFI_ITNIM_I2H_DELETE_RSP: 992 itnim = BFA_ITNIM_FROM_TAG(fcpim, 993 msg.delete_rsp->bfa_handle); 994 bfa_assert(msg.delete_rsp->status == BFA_STATUS_OK); 995 bfa_stats(itnim, delete_comps); 996 bfa_sm_send_event(itnim, BFA_ITNIM_SM_FWRSP); 997 break; 998 999 case BFI_ITNIM_I2H_SLER_EVENT: 1000 itnim = BFA_ITNIM_FROM_TAG(fcpim, 1001 msg.sler_event->bfa_handle); 1002 bfa_stats(itnim, sler_events); 1003 bfa_sm_send_event(itnim, BFA_ITNIM_SM_SLER); 1004 break; 1005 1006 default: 1007 bfa_trc(bfa, m->mhdr.msg_id); 1008 bfa_assert(0); 1009 } 1010} 1011 1012 1013 1014/** 1015 * bfa_itnim_api 1016 */ 1017 1018struct bfa_itnim_s * 1019bfa_itnim_create(struct bfa_s *bfa, struct bfa_rport_s *rport, void *ditn) 1020{ 1021 struct bfa_fcpim_mod_s *fcpim = BFA_FCPIM_MOD(bfa); 1022 struct bfa_itnim_s *itnim; 1023 1024 itnim = BFA_ITNIM_FROM_TAG(fcpim, rport->rport_tag); 1025 bfa_assert(itnim->rport == rport); 1026 1027 itnim->ditn = ditn; 1028 1029 bfa_stats(itnim, creates); 1030 bfa_sm_send_event(itnim, BFA_ITNIM_SM_CREATE); 1031 1032 return itnim; 1033} 1034 1035void 1036bfa_itnim_delete(struct bfa_itnim_s *itnim) 1037{ 1038 bfa_stats(itnim, deletes); 1039 bfa_sm_send_event(itnim, BFA_ITNIM_SM_DELETE); 1040} 1041 1042void 1043bfa_itnim_online(struct bfa_itnim_s *itnim, bfa_boolean_t seq_rec) 1044{ 1045 itnim->seq_rec = seq_rec; 1046 bfa_stats(itnim, onlines); 1047 bfa_sm_send_event(itnim, BFA_ITNIM_SM_ONLINE); 1048} 1049 1050void 1051bfa_itnim_offline(struct bfa_itnim_s *itnim) 1052{ 1053 bfa_stats(itnim, offlines); 1054 bfa_sm_send_event(itnim, BFA_ITNIM_SM_OFFLINE); 1055} 1056 1057/** 1058 * Return true if itnim is considered offline for holding off IO request. 1059 * IO is not held if itnim is being deleted. 1060 */ 1061bfa_boolean_t 1062bfa_itnim_hold_io(struct bfa_itnim_s *itnim) 1063{ 1064 return 1065 itnim->fcpim->path_tov && itnim->iotov_active && 1066 (bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwcreate) || 1067 bfa_sm_cmp_state(itnim, bfa_itnim_sm_sler) || 1068 bfa_sm_cmp_state(itnim, bfa_itnim_sm_cleanup_offline) || 1069 bfa_sm_cmp_state(itnim, bfa_itnim_sm_fwdelete) || 1070 bfa_sm_cmp_state(itnim, bfa_itnim_sm_offline) || 1071 bfa_sm_cmp_state(itnim, bfa_itnim_sm_iocdisable)) 1072 ; 1073} 1074 1075void 1076bfa_itnim_get_stats(struct bfa_itnim_s *itnim, 1077 struct bfa_itnim_hal_stats_s *stats) 1078{ 1079 *stats = itnim->stats; 1080} 1081 1082void 1083bfa_itnim_clear_stats(struct bfa_itnim_s *itnim) 1084{ 1085 bfa_os_memset(&itnim->stats, 0, sizeof(itnim->stats)); 1086} 1087