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 <cs/bfa_debug.h> 19#include <bfa_priv.h> 20#include <log/bfa_log_hal.h> 21#include <bfi/bfi_boot.h> 22#include <bfi/bfi_cbreg.h> 23#include <aen/bfa_aen_ioc.h> 24#include <defs/bfa_defs_iocfc.h> 25#include <defs/bfa_defs_pci.h> 26#include "bfa_callback_priv.h" 27#include "bfad_drv.h" 28 29BFA_TRC_FILE(HAL, IOCFC); 30 31/** 32 * IOC local definitions 33 */ 34#define BFA_IOCFC_TOV 5000 /* msecs */ 35 36enum { 37 BFA_IOCFC_ACT_NONE = 0, 38 BFA_IOCFC_ACT_INIT = 1, 39 BFA_IOCFC_ACT_STOP = 2, 40 BFA_IOCFC_ACT_DISABLE = 3, 41}; 42 43/* 44 * forward declarations 45 */ 46static void bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status); 47static void bfa_iocfc_disable_cbfn(void *bfa_arg); 48static void bfa_iocfc_hbfail_cbfn(void *bfa_arg); 49static void bfa_iocfc_reset_cbfn(void *bfa_arg); 50static void bfa_iocfc_stats_clear(void *bfa_arg); 51static void bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, 52 struct bfa_fw_stats_s *s); 53static void bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete); 54static void bfa_iocfc_stats_clr_timeout(void *bfa_arg); 55static void bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete); 56static void bfa_iocfc_stats_timeout(void *bfa_arg); 57 58static struct bfa_ioc_cbfn_s bfa_iocfc_cbfn; 59 60/** 61 * bfa_ioc_pvt BFA IOC private functions 62 */ 63 64static void 65bfa_iocfc_cqs_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len) 66{ 67 int i, per_reqq_sz, per_rspq_sz; 68 69 per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), 70 BFA_DMA_ALIGN_SZ); 71 per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), 72 BFA_DMA_ALIGN_SZ); 73 74 /* 75 * Calculate CQ size 76 */ 77 for (i = 0; i < cfg->fwcfg.num_cqs; i++) { 78 *dm_len = *dm_len + per_reqq_sz; 79 *dm_len = *dm_len + per_rspq_sz; 80 } 81 82 /* 83 * Calculate Shadow CI/PI size 84 */ 85 for (i = 0; i < cfg->fwcfg.num_cqs; i++) 86 *dm_len += (2 * BFA_CACHELINE_SZ); 87} 88 89static void 90bfa_iocfc_fw_cfg_sz(struct bfa_iocfc_cfg_s *cfg, u32 *dm_len) 91{ 92 *dm_len += 93 BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); 94 *dm_len += 95 BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), 96 BFA_CACHELINE_SZ); 97 *dm_len += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ); 98} 99 100/** 101 * Use the Mailbox interface to send BFI_IOCFC_H2I_CFG_REQ 102 */ 103static void 104bfa_iocfc_send_cfg(void *bfa_arg) 105{ 106 struct bfa_s *bfa = bfa_arg; 107 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 108 struct bfi_iocfc_cfg_req_s cfg_req; 109 struct bfi_iocfc_cfg_s *cfg_info = iocfc->cfginfo; 110 struct bfa_iocfc_cfg_s *cfg = &iocfc->cfg; 111 int i; 112 113 bfa_assert(cfg->fwcfg.num_cqs <= BFI_IOC_MAX_CQS); 114 bfa_trc(bfa, cfg->fwcfg.num_cqs); 115 116 bfa_iocfc_reset_queues(bfa); 117 118 /** 119 * initialize IOC configuration info 120 */ 121 cfg_info->endian_sig = BFI_IOC_ENDIAN_SIG; 122 cfg_info->num_cqs = cfg->fwcfg.num_cqs; 123 124 bfa_dma_be_addr_set(cfg_info->cfgrsp_addr, iocfc->cfgrsp_dma.pa); 125 bfa_dma_be_addr_set(cfg_info->stats_addr, iocfc->stats_pa); 126 127 /** 128 * dma map REQ and RSP circular queues and shadow pointers 129 */ 130 for (i = 0; i < cfg->fwcfg.num_cqs; i++) { 131 bfa_dma_be_addr_set(cfg_info->req_cq_ba[i], 132 iocfc->req_cq_ba[i].pa); 133 bfa_dma_be_addr_set(cfg_info->req_shadow_ci[i], 134 iocfc->req_cq_shadow_ci[i].pa); 135 cfg_info->req_cq_elems[i] = 136 bfa_os_htons(cfg->drvcfg.num_reqq_elems); 137 138 bfa_dma_be_addr_set(cfg_info->rsp_cq_ba[i], 139 iocfc->rsp_cq_ba[i].pa); 140 bfa_dma_be_addr_set(cfg_info->rsp_shadow_pi[i], 141 iocfc->rsp_cq_shadow_pi[i].pa); 142 cfg_info->rsp_cq_elems[i] = 143 bfa_os_htons(cfg->drvcfg.num_rspq_elems); 144 } 145 146 /** 147 * Enable interrupt coalescing if it is driver init path 148 * and not ioc disable/enable path. 149 */ 150 if (!iocfc->cfgdone) 151 cfg_info->intr_attr.coalesce = BFA_TRUE; 152 153 iocfc->cfgdone = BFA_FALSE; 154 155 /** 156 * dma map IOC configuration itself 157 */ 158 bfi_h2i_set(cfg_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CFG_REQ, 159 bfa_lpuid(bfa)); 160 bfa_dma_be_addr_set(cfg_req.ioc_cfg_dma_addr, iocfc->cfg_info.pa); 161 162 bfa_ioc_mbox_send(&bfa->ioc, &cfg_req, 163 sizeof(struct bfi_iocfc_cfg_req_s)); 164} 165 166static void 167bfa_iocfc_init_mem(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, 168 struct bfa_pcidev_s *pcidev) 169{ 170 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 171 172 bfa->bfad = bfad; 173 iocfc->bfa = bfa; 174 iocfc->action = BFA_IOCFC_ACT_NONE; 175 176 bfa_os_assign(iocfc->cfg, *cfg); 177 178 /** 179 * Initialize chip specific handlers. 180 */ 181 if (bfa_asic_id_ct(bfa_ioc_devid(&bfa->ioc))) { 182 iocfc->hwif.hw_reginit = bfa_hwct_reginit; 183 iocfc->hwif.hw_reqq_ack = bfa_hwct_reqq_ack; 184 iocfc->hwif.hw_rspq_ack = bfa_hwct_rspq_ack; 185 iocfc->hwif.hw_msix_init = bfa_hwct_msix_init; 186 iocfc->hwif.hw_msix_install = bfa_hwct_msix_install; 187 iocfc->hwif.hw_msix_uninstall = bfa_hwct_msix_uninstall; 188 iocfc->hwif.hw_isr_mode_set = bfa_hwct_isr_mode_set; 189 iocfc->hwif.hw_msix_getvecs = bfa_hwct_msix_getvecs; 190 iocfc->hwif.hw_msix_get_rme_range = bfa_hwct_msix_get_rme_range; 191 } else { 192 iocfc->hwif.hw_reginit = bfa_hwcb_reginit; 193 iocfc->hwif.hw_reqq_ack = bfa_hwcb_reqq_ack; 194 iocfc->hwif.hw_rspq_ack = bfa_hwcb_rspq_ack; 195 iocfc->hwif.hw_msix_init = bfa_hwcb_msix_init; 196 iocfc->hwif.hw_msix_install = bfa_hwcb_msix_install; 197 iocfc->hwif.hw_msix_uninstall = bfa_hwcb_msix_uninstall; 198 iocfc->hwif.hw_isr_mode_set = bfa_hwcb_isr_mode_set; 199 iocfc->hwif.hw_msix_getvecs = bfa_hwcb_msix_getvecs; 200 iocfc->hwif.hw_msix_get_rme_range = bfa_hwcb_msix_get_rme_range; 201 } 202 203 iocfc->hwif.hw_reginit(bfa); 204 bfa->msix.nvecs = 0; 205} 206 207static void 208bfa_iocfc_mem_claim(struct bfa_s *bfa, struct bfa_iocfc_cfg_s *cfg, 209 struct bfa_meminfo_s *meminfo) 210{ 211 u8 *dm_kva; 212 u64 dm_pa; 213 int i, per_reqq_sz, per_rspq_sz; 214 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 215 int dbgsz; 216 217 dm_kva = bfa_meminfo_dma_virt(meminfo); 218 dm_pa = bfa_meminfo_dma_phys(meminfo); 219 220 /* 221 * First allocate dma memory for IOC. 222 */ 223 bfa_ioc_mem_claim(&bfa->ioc, dm_kva, dm_pa); 224 dm_kva += bfa_ioc_meminfo(); 225 dm_pa += bfa_ioc_meminfo(); 226 227 /* 228 * Claim DMA-able memory for the request/response queues and for shadow 229 * ci/pi registers 230 */ 231 per_reqq_sz = BFA_ROUNDUP((cfg->drvcfg.num_reqq_elems * BFI_LMSG_SZ), 232 BFA_DMA_ALIGN_SZ); 233 per_rspq_sz = BFA_ROUNDUP((cfg->drvcfg.num_rspq_elems * BFI_LMSG_SZ), 234 BFA_DMA_ALIGN_SZ); 235 236 for (i = 0; i < cfg->fwcfg.num_cqs; i++) { 237 iocfc->req_cq_ba[i].kva = dm_kva; 238 iocfc->req_cq_ba[i].pa = dm_pa; 239 bfa_os_memset(dm_kva, 0, per_reqq_sz); 240 dm_kva += per_reqq_sz; 241 dm_pa += per_reqq_sz; 242 243 iocfc->rsp_cq_ba[i].kva = dm_kva; 244 iocfc->rsp_cq_ba[i].pa = dm_pa; 245 bfa_os_memset(dm_kva, 0, per_rspq_sz); 246 dm_kva += per_rspq_sz; 247 dm_pa += per_rspq_sz; 248 } 249 250 for (i = 0; i < cfg->fwcfg.num_cqs; i++) { 251 iocfc->req_cq_shadow_ci[i].kva = dm_kva; 252 iocfc->req_cq_shadow_ci[i].pa = dm_pa; 253 dm_kva += BFA_CACHELINE_SZ; 254 dm_pa += BFA_CACHELINE_SZ; 255 256 iocfc->rsp_cq_shadow_pi[i].kva = dm_kva; 257 iocfc->rsp_cq_shadow_pi[i].pa = dm_pa; 258 dm_kva += BFA_CACHELINE_SZ; 259 dm_pa += BFA_CACHELINE_SZ; 260 } 261 262 /* 263 * Claim DMA-able memory for the config info page 264 */ 265 bfa->iocfc.cfg_info.kva = dm_kva; 266 bfa->iocfc.cfg_info.pa = dm_pa; 267 bfa->iocfc.cfginfo = (struct bfi_iocfc_cfg_s *) dm_kva; 268 dm_kva += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); 269 dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfg_s), BFA_CACHELINE_SZ); 270 271 /* 272 * Claim DMA-able memory for the config response 273 */ 274 bfa->iocfc.cfgrsp_dma.kva = dm_kva; 275 bfa->iocfc.cfgrsp_dma.pa = dm_pa; 276 bfa->iocfc.cfgrsp = (struct bfi_iocfc_cfgrsp_s *) dm_kva; 277 278 dm_kva += 279 BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), 280 BFA_CACHELINE_SZ); 281 dm_pa += BFA_ROUNDUP(sizeof(struct bfi_iocfc_cfgrsp_s), 282 BFA_CACHELINE_SZ); 283 284 /* 285 * Claim DMA-able memory for iocfc stats 286 */ 287 bfa->iocfc.stats_kva = dm_kva; 288 bfa->iocfc.stats_pa = dm_pa; 289 bfa->iocfc.fw_stats = (struct bfa_fw_stats_s *) dm_kva; 290 dm_kva += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ); 291 dm_pa += BFA_ROUNDUP(sizeof(struct bfa_fw_stats_s), BFA_CACHELINE_SZ); 292 293 bfa_meminfo_dma_virt(meminfo) = dm_kva; 294 bfa_meminfo_dma_phys(meminfo) = dm_pa; 295 296 dbgsz = bfa_ioc_debug_trcsz(bfa_auto_recover); 297 if (dbgsz > 0) { 298 bfa_ioc_debug_memclaim(&bfa->ioc, bfa_meminfo_kva(meminfo)); 299 bfa_meminfo_kva(meminfo) += dbgsz; 300 } 301} 302 303/** 304 * Start BFA submodules. 305 */ 306static void 307bfa_iocfc_start_submod(struct bfa_s *bfa) 308{ 309 int i; 310 311 bfa->rme_process = BFA_TRUE; 312 313 for (i = 0; hal_mods[i]; i++) 314 hal_mods[i]->start(bfa); 315} 316 317/** 318 * Disable BFA submodules. 319 */ 320static void 321bfa_iocfc_disable_submod(struct bfa_s *bfa) 322{ 323 int i; 324 325 for (i = 0; hal_mods[i]; i++) 326 hal_mods[i]->iocdisable(bfa); 327} 328 329static void 330bfa_iocfc_init_cb(void *bfa_arg, bfa_boolean_t complete) 331{ 332 struct bfa_s *bfa = bfa_arg; 333 334 if (complete) { 335 if (bfa->iocfc.cfgdone) 336 bfa_cb_init(bfa->bfad, BFA_STATUS_OK); 337 else 338 bfa_cb_init(bfa->bfad, BFA_STATUS_FAILED); 339 } else { 340 if (bfa->iocfc.cfgdone) 341 bfa->iocfc.action = BFA_IOCFC_ACT_NONE; 342 } 343} 344 345static void 346bfa_iocfc_stop_cb(void *bfa_arg, bfa_boolean_t compl) 347{ 348 struct bfa_s *bfa = bfa_arg; 349 struct bfad_s *bfad = bfa->bfad; 350 351 if (compl) 352 complete(&bfad->comp); 353 354 else 355 bfa->iocfc.action = BFA_IOCFC_ACT_NONE; 356} 357 358static void 359bfa_iocfc_disable_cb(void *bfa_arg, bfa_boolean_t compl) 360{ 361 struct bfa_s *bfa = bfa_arg; 362 struct bfad_s *bfad = bfa->bfad; 363 364 if (compl) 365 complete(&bfad->disable_comp); 366} 367 368/** 369 * Update BFA configuration from firmware configuration. 370 */ 371static void 372bfa_iocfc_cfgrsp(struct bfa_s *bfa) 373{ 374 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 375 struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; 376 struct bfa_iocfc_fwcfg_s *fwcfg = &cfgrsp->fwcfg; 377 378 fwcfg->num_cqs = fwcfg->num_cqs; 379 fwcfg->num_ioim_reqs = bfa_os_ntohs(fwcfg->num_ioim_reqs); 380 fwcfg->num_tskim_reqs = bfa_os_ntohs(fwcfg->num_tskim_reqs); 381 fwcfg->num_fcxp_reqs = bfa_os_ntohs(fwcfg->num_fcxp_reqs); 382 fwcfg->num_uf_bufs = bfa_os_ntohs(fwcfg->num_uf_bufs); 383 fwcfg->num_rports = bfa_os_ntohs(fwcfg->num_rports); 384 385 iocfc->cfgdone = BFA_TRUE; 386 387 /** 388 * Configuration is complete - initialize/start submodules 389 */ 390 bfa_fcport_init(bfa); 391 392 if (iocfc->action == BFA_IOCFC_ACT_INIT) 393 bfa_cb_queue(bfa, &iocfc->init_hcb_qe, bfa_iocfc_init_cb, bfa); 394 else 395 bfa_iocfc_start_submod(bfa); 396} 397 398static void 399bfa_iocfc_stats_clear(void *bfa_arg) 400{ 401 struct bfa_s *bfa = bfa_arg; 402 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 403 struct bfi_iocfc_stats_req_s stats_req; 404 405 bfa_timer_start(bfa, &iocfc->stats_timer, 406 bfa_iocfc_stats_clr_timeout, bfa, 407 BFA_IOCFC_TOV); 408 409 bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_CLEAR_STATS_REQ, 410 bfa_lpuid(bfa)); 411 bfa_ioc_mbox_send(&bfa->ioc, &stats_req, 412 sizeof(struct bfi_iocfc_stats_req_s)); 413} 414 415static void 416bfa_iocfc_stats_swap(struct bfa_fw_stats_s *d, struct bfa_fw_stats_s *s) 417{ 418 u32 *dip = (u32 *) d; 419 u32 *sip = (u32 *) s; 420 int i; 421 422 for (i = 0; i < (sizeof(struct bfa_fw_stats_s) / sizeof(u32)); i++) 423 dip[i] = bfa_os_ntohl(sip[i]); 424} 425 426static void 427bfa_iocfc_stats_clr_cb(void *bfa_arg, bfa_boolean_t complete) 428{ 429 struct bfa_s *bfa = bfa_arg; 430 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 431 432 if (complete) { 433 bfa_ioc_clr_stats(&bfa->ioc); 434 iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status); 435 } else { 436 iocfc->stats_busy = BFA_FALSE; 437 iocfc->stats_status = BFA_STATUS_OK; 438 } 439} 440 441static void 442bfa_iocfc_stats_clr_timeout(void *bfa_arg) 443{ 444 struct bfa_s *bfa = bfa_arg; 445 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 446 447 bfa_trc(bfa, 0); 448 449 iocfc->stats_status = BFA_STATUS_ETIMER; 450 bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_clr_cb, bfa); 451} 452 453static void 454bfa_iocfc_stats_cb(void *bfa_arg, bfa_boolean_t complete) 455{ 456 struct bfa_s *bfa = bfa_arg; 457 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 458 459 if (complete) { 460 if (iocfc->stats_status == BFA_STATUS_OK) { 461 bfa_os_memset(iocfc->stats_ret, 0, 462 sizeof(*iocfc->stats_ret)); 463 bfa_iocfc_stats_swap(&iocfc->stats_ret->fw_stats, 464 iocfc->fw_stats); 465 } 466 iocfc->stats_cbfn(iocfc->stats_cbarg, iocfc->stats_status); 467 } else { 468 iocfc->stats_busy = BFA_FALSE; 469 iocfc->stats_status = BFA_STATUS_OK; 470 } 471} 472 473static void 474bfa_iocfc_stats_timeout(void *bfa_arg) 475{ 476 struct bfa_s *bfa = bfa_arg; 477 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 478 479 bfa_trc(bfa, 0); 480 481 iocfc->stats_status = BFA_STATUS_ETIMER; 482 bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, bfa); 483} 484 485static void 486bfa_iocfc_stats_query(struct bfa_s *bfa) 487{ 488 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 489 struct bfi_iocfc_stats_req_s stats_req; 490 491 bfa_timer_start(bfa, &iocfc->stats_timer, 492 bfa_iocfc_stats_timeout, bfa, BFA_IOCFC_TOV); 493 494 bfi_h2i_set(stats_req.mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_GET_STATS_REQ, 495 bfa_lpuid(bfa)); 496 bfa_ioc_mbox_send(&bfa->ioc, &stats_req, 497 sizeof(struct bfi_iocfc_stats_req_s)); 498} 499 500void 501bfa_iocfc_reset_queues(struct bfa_s *bfa) 502{ 503 int q; 504 505 for (q = 0; q < BFI_IOC_MAX_CQS; q++) { 506 bfa_reqq_ci(bfa, q) = 0; 507 bfa_reqq_pi(bfa, q) = 0; 508 bfa_rspq_ci(bfa, q) = 0; 509 bfa_rspq_pi(bfa, q) = 0; 510 } 511} 512 513/** 514 * IOC enable request is complete 515 */ 516static void 517bfa_iocfc_enable_cbfn(void *bfa_arg, enum bfa_status status) 518{ 519 struct bfa_s *bfa = bfa_arg; 520 521 if (status != BFA_STATUS_OK) { 522 bfa_isr_disable(bfa); 523 if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) 524 bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, 525 bfa_iocfc_init_cb, bfa); 526 return; 527 } 528 529 bfa_iocfc_send_cfg(bfa); 530} 531 532/** 533 * IOC disable request is complete 534 */ 535static void 536bfa_iocfc_disable_cbfn(void *bfa_arg) 537{ 538 struct bfa_s *bfa = bfa_arg; 539 540 bfa_isr_disable(bfa); 541 bfa_iocfc_disable_submod(bfa); 542 543 if (bfa->iocfc.action == BFA_IOCFC_ACT_STOP) 544 bfa_cb_queue(bfa, &bfa->iocfc.stop_hcb_qe, bfa_iocfc_stop_cb, 545 bfa); 546 else { 547 bfa_assert(bfa->iocfc.action == BFA_IOCFC_ACT_DISABLE); 548 bfa_cb_queue(bfa, &bfa->iocfc.dis_hcb_qe, bfa_iocfc_disable_cb, 549 bfa); 550 } 551} 552 553/** 554 * Notify sub-modules of hardware failure. 555 */ 556static void 557bfa_iocfc_hbfail_cbfn(void *bfa_arg) 558{ 559 struct bfa_s *bfa = bfa_arg; 560 561 bfa->rme_process = BFA_FALSE; 562 563 bfa_isr_disable(bfa); 564 bfa_iocfc_disable_submod(bfa); 565 566 if (bfa->iocfc.action == BFA_IOCFC_ACT_INIT) 567 bfa_cb_queue(bfa, &bfa->iocfc.init_hcb_qe, bfa_iocfc_init_cb, 568 bfa); 569} 570 571/** 572 * Actions on chip-reset completion. 573 */ 574static void 575bfa_iocfc_reset_cbfn(void *bfa_arg) 576{ 577 struct bfa_s *bfa = bfa_arg; 578 579 bfa_iocfc_reset_queues(bfa); 580 bfa_isr_enable(bfa); 581} 582 583 584 585/** 586 * bfa_ioc_public 587 */ 588 589/** 590 * Query IOC memory requirement information. 591 */ 592void 593bfa_iocfc_meminfo(struct bfa_iocfc_cfg_s *cfg, u32 *km_len, 594 u32 *dm_len) 595{ 596 /* dma memory for IOC */ 597 *dm_len += bfa_ioc_meminfo(); 598 599 bfa_iocfc_fw_cfg_sz(cfg, dm_len); 600 bfa_iocfc_cqs_sz(cfg, dm_len); 601 *km_len += bfa_ioc_debug_trcsz(bfa_auto_recover); 602} 603 604/** 605 * Query IOC memory requirement information. 606 */ 607void 608bfa_iocfc_attach(struct bfa_s *bfa, void *bfad, struct bfa_iocfc_cfg_s *cfg, 609 struct bfa_meminfo_s *meminfo, struct bfa_pcidev_s *pcidev) 610{ 611 int i; 612 613 bfa_iocfc_cbfn.enable_cbfn = bfa_iocfc_enable_cbfn; 614 bfa_iocfc_cbfn.disable_cbfn = bfa_iocfc_disable_cbfn; 615 bfa_iocfc_cbfn.hbfail_cbfn = bfa_iocfc_hbfail_cbfn; 616 bfa_iocfc_cbfn.reset_cbfn = bfa_iocfc_reset_cbfn; 617 618 bfa_ioc_attach(&bfa->ioc, bfa, &bfa_iocfc_cbfn, &bfa->timer_mod, 619 bfa->trcmod, bfa->aen, bfa->logm); 620 621 /** 622 * Set FC mode for BFA_PCI_DEVICE_ID_CT_FC. 623 */ 624 if (pcidev->device_id == BFA_PCI_DEVICE_ID_CT_FC) 625 bfa_ioc_set_fcmode(&bfa->ioc); 626 627 bfa_ioc_pci_init(&bfa->ioc, pcidev, BFI_MC_IOCFC); 628 bfa_ioc_mbox_register(&bfa->ioc, bfa_mbox_isrs); 629 630 bfa_iocfc_init_mem(bfa, bfad, cfg, pcidev); 631 bfa_iocfc_mem_claim(bfa, cfg, meminfo); 632 bfa_timer_init(&bfa->timer_mod); 633 634 INIT_LIST_HEAD(&bfa->comp_q); 635 for (i = 0; i < BFI_IOC_MAX_CQS; i++) 636 INIT_LIST_HEAD(&bfa->reqq_waitq[i]); 637} 638 639/** 640 * Query IOC memory requirement information. 641 */ 642void 643bfa_iocfc_detach(struct bfa_s *bfa) 644{ 645 bfa_ioc_detach(&bfa->ioc); 646} 647 648/** 649 * Query IOC memory requirement information. 650 */ 651void 652bfa_iocfc_init(struct bfa_s *bfa) 653{ 654 bfa->iocfc.action = BFA_IOCFC_ACT_INIT; 655 bfa_ioc_enable(&bfa->ioc); 656} 657 658/** 659 * IOC start called from bfa_start(). Called to start IOC operations 660 * at driver instantiation for this instance. 661 */ 662void 663bfa_iocfc_start(struct bfa_s *bfa) 664{ 665 if (bfa->iocfc.cfgdone) 666 bfa_iocfc_start_submod(bfa); 667} 668 669/** 670 * IOC stop called from bfa_stop(). Called only when driver is unloaded 671 * for this instance. 672 */ 673void 674bfa_iocfc_stop(struct bfa_s *bfa) 675{ 676 bfa->iocfc.action = BFA_IOCFC_ACT_STOP; 677 678 bfa->rme_process = BFA_FALSE; 679 bfa_ioc_disable(&bfa->ioc); 680} 681 682void 683bfa_iocfc_isr(void *bfaarg, struct bfi_mbmsg_s *m) 684{ 685 struct bfa_s *bfa = bfaarg; 686 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 687 union bfi_iocfc_i2h_msg_u *msg; 688 689 msg = (union bfi_iocfc_i2h_msg_u *) m; 690 bfa_trc(bfa, msg->mh.msg_id); 691 692 switch (msg->mh.msg_id) { 693 case BFI_IOCFC_I2H_CFG_REPLY: 694 iocfc->cfg_reply = &msg->cfg_reply; 695 bfa_iocfc_cfgrsp(bfa); 696 break; 697 698 case BFI_IOCFC_I2H_GET_STATS_RSP: 699 if (iocfc->stats_busy == BFA_FALSE 700 || iocfc->stats_status == BFA_STATUS_ETIMER) 701 break; 702 703 bfa_timer_stop(&iocfc->stats_timer); 704 iocfc->stats_status = BFA_STATUS_OK; 705 bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, bfa_iocfc_stats_cb, 706 bfa); 707 break; 708 case BFI_IOCFC_I2H_CLEAR_STATS_RSP: 709 /* 710 * check for timer pop before processing the rsp 711 */ 712 if (iocfc->stats_busy == BFA_FALSE 713 || iocfc->stats_status == BFA_STATUS_ETIMER) 714 break; 715 716 bfa_timer_stop(&iocfc->stats_timer); 717 iocfc->stats_status = BFA_STATUS_OK; 718 bfa_cb_queue(bfa, &iocfc->stats_hcb_qe, 719 bfa_iocfc_stats_clr_cb, bfa); 720 break; 721 case BFI_IOCFC_I2H_UPDATEQ_RSP: 722 iocfc->updateq_cbfn(iocfc->updateq_cbarg, BFA_STATUS_OK); 723 break; 724 default: 725 bfa_assert(0); 726 } 727} 728 729#ifndef BFA_BIOS_BUILD 730void 731bfa_adapter_get_attr(struct bfa_s *bfa, struct bfa_adapter_attr_s *ad_attr) 732{ 733 bfa_ioc_get_adapter_attr(&bfa->ioc, ad_attr); 734} 735 736u64 737bfa_adapter_get_id(struct bfa_s *bfa) 738{ 739 return bfa_ioc_get_adid(&bfa->ioc); 740} 741 742void 743bfa_iocfc_get_attr(struct bfa_s *bfa, struct bfa_iocfc_attr_s *attr) 744{ 745 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 746 747 attr->intr_attr.coalesce = iocfc->cfginfo->intr_attr.coalesce; 748 749 attr->intr_attr.delay = iocfc->cfginfo->intr_attr.delay ? 750 bfa_os_ntohs(iocfc->cfginfo->intr_attr.delay) : 751 bfa_os_ntohs(iocfc->cfgrsp->intr_attr.delay); 752 753 attr->intr_attr.latency = iocfc->cfginfo->intr_attr.latency ? 754 bfa_os_ntohs(iocfc->cfginfo->intr_attr.latency) : 755 bfa_os_ntohs(iocfc->cfgrsp->intr_attr.latency); 756 757 attr->config = iocfc->cfg; 758 759} 760 761bfa_status_t 762bfa_iocfc_israttr_set(struct bfa_s *bfa, struct bfa_iocfc_intr_attr_s *attr) 763{ 764 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 765 struct bfi_iocfc_set_intr_req_s *m; 766 767 iocfc->cfginfo->intr_attr.coalesce = attr->coalesce; 768 iocfc->cfginfo->intr_attr.delay = bfa_os_htons(attr->delay); 769 iocfc->cfginfo->intr_attr.latency = bfa_os_htons(attr->latency); 770 771 if (!bfa_iocfc_is_operational(bfa)) 772 return BFA_STATUS_OK; 773 774 m = bfa_reqq_next(bfa, BFA_REQQ_IOC); 775 if (!m) 776 return BFA_STATUS_DEVBUSY; 777 778 bfi_h2i_set(m->mh, BFI_MC_IOCFC, BFI_IOCFC_H2I_SET_INTR_REQ, 779 bfa_lpuid(bfa)); 780 m->coalesce = iocfc->cfginfo->intr_attr.coalesce; 781 m->delay = iocfc->cfginfo->intr_attr.delay; 782 m->latency = iocfc->cfginfo->intr_attr.latency; 783 784 785 bfa_trc(bfa, attr->delay); 786 bfa_trc(bfa, attr->latency); 787 788 bfa_reqq_produce(bfa, BFA_REQQ_IOC); 789 return BFA_STATUS_OK; 790} 791 792void 793bfa_iocfc_set_snsbase(struct bfa_s *bfa, u64 snsbase_pa) 794{ 795 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 796 797 iocfc->cfginfo->sense_buf_len = (BFI_IOIM_SNSLEN - 1); 798 bfa_dma_be_addr_set(iocfc->cfginfo->ioim_snsbase, snsbase_pa); 799} 800 801bfa_status_t 802bfa_iocfc_get_stats(struct bfa_s *bfa, struct bfa_iocfc_stats_s *stats, 803 bfa_cb_ioc_t cbfn, void *cbarg) 804{ 805 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 806 807 if (iocfc->stats_busy) { 808 bfa_trc(bfa, iocfc->stats_busy); 809 return BFA_STATUS_DEVBUSY; 810 } 811 812 if (!bfa_iocfc_is_operational(bfa)) { 813 bfa_trc(bfa, 0); 814 return BFA_STATUS_IOC_NON_OP; 815 } 816 817 iocfc->stats_busy = BFA_TRUE; 818 iocfc->stats_ret = stats; 819 iocfc->stats_cbfn = cbfn; 820 iocfc->stats_cbarg = cbarg; 821 822 bfa_iocfc_stats_query(bfa); 823 824 return BFA_STATUS_OK; 825} 826 827bfa_status_t 828bfa_iocfc_clear_stats(struct bfa_s *bfa, bfa_cb_ioc_t cbfn, void *cbarg) 829{ 830 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 831 832 if (iocfc->stats_busy) { 833 bfa_trc(bfa, iocfc->stats_busy); 834 return BFA_STATUS_DEVBUSY; 835 } 836 837 if (!bfa_iocfc_is_operational(bfa)) { 838 bfa_trc(bfa, 0); 839 return BFA_STATUS_IOC_NON_OP; 840 } 841 842 iocfc->stats_busy = BFA_TRUE; 843 iocfc->stats_cbfn = cbfn; 844 iocfc->stats_cbarg = cbarg; 845 846 bfa_iocfc_stats_clear(bfa); 847 return BFA_STATUS_OK; 848} 849 850/** 851 * Enable IOC after it is disabled. 852 */ 853void 854bfa_iocfc_enable(struct bfa_s *bfa) 855{ 856 bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0, 857 "IOC Enable"); 858 bfa_ioc_enable(&bfa->ioc); 859} 860 861void 862bfa_iocfc_disable(struct bfa_s *bfa) 863{ 864 bfa_plog_str(bfa->plog, BFA_PL_MID_HAL, BFA_PL_EID_MISC, 0, 865 "IOC Disable"); 866 bfa->iocfc.action = BFA_IOCFC_ACT_DISABLE; 867 868 bfa->rme_process = BFA_FALSE; 869 bfa_ioc_disable(&bfa->ioc); 870} 871 872 873bfa_boolean_t 874bfa_iocfc_is_operational(struct bfa_s *bfa) 875{ 876 return bfa_ioc_is_operational(&bfa->ioc) && bfa->iocfc.cfgdone; 877} 878 879/** 880 * Return boot target port wwns -- read from boot information in flash. 881 */ 882void 883bfa_iocfc_get_bootwwns(struct bfa_s *bfa, u8 *nwwns, wwn_t *wwns) 884{ 885 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 886 struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; 887 int i; 888 889 if (cfgrsp->pbc_cfg.boot_enabled && cfgrsp->pbc_cfg.nbluns) { 890 bfa_trc(bfa, cfgrsp->pbc_cfg.nbluns); 891 *nwwns = cfgrsp->pbc_cfg.nbluns; 892 for (i = 0; i < cfgrsp->pbc_cfg.nbluns; i++) 893 wwns[i] = cfgrsp->pbc_cfg.blun[i].tgt_pwwn; 894 895 return; 896 } 897 898 *nwwns = cfgrsp->bootwwns.nwwns; 899 memcpy(wwns, cfgrsp->bootwwns.wwn, sizeof(cfgrsp->bootwwns.wwn)); 900} 901 902void 903bfa_iocfc_get_pbc_boot_cfg(struct bfa_s *bfa, struct bfa_boot_pbc_s *pbcfg) 904{ 905 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 906 struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; 907 908 pbcfg->enable = cfgrsp->pbc_cfg.boot_enabled; 909 pbcfg->nbluns = cfgrsp->pbc_cfg.nbluns; 910 pbcfg->speed = cfgrsp->pbc_cfg.port_speed; 911 memcpy(pbcfg->pblun, cfgrsp->pbc_cfg.blun, sizeof(pbcfg->pblun)); 912} 913 914int 915bfa_iocfc_get_pbc_vports(struct bfa_s *bfa, struct bfi_pbc_vport_s *pbc_vport) 916{ 917 struct bfa_iocfc_s *iocfc = &bfa->iocfc; 918 struct bfi_iocfc_cfgrsp_s *cfgrsp = iocfc->cfgrsp; 919 920 memcpy(pbc_vport, cfgrsp->pbc_cfg.vport, sizeof(cfgrsp->pbc_cfg.vport)); 921 return cfgrsp->pbc_cfg.nvports; 922} 923 924 925#endif 926