1 /*- 2 * Copyright (c) 2017 Broadcom. All rights reserved. 3 * The term "Broadcom" refers to Broadcom Limited and/or its subsidiaries. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, 9 * this list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * 3. Neither the name of the copyright holder nor the names of its contributors 16 * may be used to endorse or promote products derived from this software 17 * without specific prior written permission. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 20 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 23 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 * 31 * $FreeBSD$ 32 */ 33 34 #define OCS_COPYRIGHT "Copyright (C) 2017 Broadcom. All rights reserved." 35 36 /** 37 * @file 38 * Implementation of required FreeBSD PCI interface functions 39 */ 40 41 #include "ocs.h" 42 #include "version.h" 43 #include <sys/sysctl.h> 44 #include <sys/malloc.h> 45 46 static MALLOC_DEFINE(M_OCS, "OCS", "OneCore Storage data"); 47 48 #include <dev/pci/pcireg.h> 49 #include <dev/pci/pcivar.h> 50 51 #include <machine/bus.h> 52 53 /** 54 * Tunable parameters for transport 55 */ 56 int logmask = 0; 57 int ctrlmask = 2; 58 int logdest = 1; 59 int loglevel = LOG_INFO; 60 int ramlog_size = 1*1024*1024; 61 int ddump_saved_size = 0; 62 static const char *queue_topology = "eq cq rq cq mq $nulp($nwq(cq wq:ulp=$rpt1)) cq wq:len=256:class=1"; 63 64 static void ocs_release_bus(struct ocs_softc *); 65 static int32_t ocs_intr_alloc(struct ocs_softc *); 66 static int32_t ocs_intr_setup(struct ocs_softc *); 67 static int32_t ocs_intr_teardown(struct ocs_softc *); 68 static int ocs_pci_intx_filter(void *); 69 static void ocs_pci_intr(void *); 70 static int32_t ocs_init_dma_tag(struct ocs_softc *ocs); 71 72 static int32_t ocs_setup_fcports(ocs_t *ocs); 73 74 ocs_t *ocs_devices[MAX_OCS_DEVICES]; 75 76 /** 77 * @brief Check support for the given device 78 * 79 * Determine support for a given device by examining the PCI vendor and 80 * device IDs 81 * 82 * @param dev device abstraction 83 * 84 * @return 0 if device is supported, ENXIO otherwise 85 */ 86 static int 87 ocs_pci_probe(device_t dev) 88 { 89 char *desc = NULL; 90 91 if (pci_get_vendor(dev) != PCI_VENDOR_EMULEX) { 92 return ENXIO; 93 } 94 95 switch (pci_get_device(dev)) { 96 case PCI_PRODUCT_EMULEX_OCE16001: 97 desc = "Emulex LightPulse FC Adapter"; 98 break; 99 case PCI_PRODUCT_EMULEX_LPE31004: 100 desc = "Emulex LightPulse FC Adapter"; 101 break; 102 case PCI_PRODUCT_EMULEX_OCE50102: 103 desc = "Emulex LightPulse 10GbE FCoE/NIC Adapter"; 104 break; 105 case PCI_PRODUCT_EMULEX_LANCER_G7: 106 desc = "Emulex LightPulse G7 FC Adapter"; 107 break; 108 default: 109 return ENXIO; 110 } 111 112 device_set_desc(dev, desc); 113 114 return BUS_PROBE_DEFAULT; 115 } 116 117 static int 118 ocs_map_g7_bars(device_t dev, struct ocs_softc *ocs) 119 { 120 int i, r; 121 uint32_t val = 0; 122 123 for (i = 0, r = 0; i < PCI_MAX_BAR; i++) { 124 val = pci_read_config(dev, PCIR_BAR(i), 4); 125 if (!PCI_BAR_MEM(val)) { 126 continue; 127 } 128 if (!(val & PCIM_BAR_MEM_BASE)) { 129 /* no address */ 130 continue; 131 } 132 ocs->reg[r].rid = PCIR_BAR(i); 133 ocs->reg[r].res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 134 &ocs->reg[r].rid, RF_ACTIVE); 135 if (ocs->reg[r].res) { 136 ocs->reg[r].btag = rman_get_bustag(ocs->reg[r].res); 137 ocs->reg[r].bhandle = rman_get_bushandle(ocs->reg[r].res); 138 r++; 139 } else { 140 device_printf(dev, "bus_alloc_resource failed rid=%#x\n", 141 ocs->reg[r].rid); 142 ocs_release_bus(ocs); 143 return ENXIO; 144 } 145 146 /* 147 * If the 64-bit attribute is set, both this BAR and the 148 * next form the complete address. Skip processing the 149 * next BAR. 150 */ 151 if (val & PCIM_BAR_MEM_64) { 152 i++; 153 } 154 } 155 156 return 0; 157 } 158 159 static int 160 ocs_map_bars(device_t dev, struct ocs_softc *ocs) 161 { 162 /* 163 * Map PCI BAR0 register into the CPU's space. 164 */ 165 166 ocs->reg[0].rid = PCIR_BAR(PCI_64BIT_BAR0); 167 ocs->reg[0].res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 168 &ocs->reg[0].rid, RF_ACTIVE); 169 170 if (ocs->reg[0].res == NULL) { 171 device_printf(dev, "bus_alloc_resource failed rid=%#x\n", 172 ocs->reg[0].rid); 173 return ENXIO; 174 } 175 176 ocs->reg[0].btag = rman_get_bustag(ocs->reg[0].res); 177 ocs->reg[0].bhandle = rman_get_bushandle(ocs->reg[0].res); 178 return 0; 179 } 180 181 static int 182 ocs_setup_params(struct ocs_softc *ocs) 183 { 184 int32_t i = 0; 185 const char *hw_war_version; 186 /* Setup tunable parameters */ 187 ocs->ctrlmask = ctrlmask; 188 ocs->speed = 0; 189 ocs->topology = 0; 190 ocs->ethernet_license = 0; 191 ocs->num_scsi_ios = 8192; 192 ocs->enable_hlm = 0; 193 ocs->hlm_group_size = 8; 194 ocs->logmask = logmask; 195 196 ocs->config_tgt = FALSE; 197 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 198 "target", &i)) { 199 if (1 == i) { 200 ocs->config_tgt = TRUE; 201 device_printf(ocs->dev, "Enabling target\n"); 202 } 203 } 204 205 ocs->config_ini = TRUE; 206 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 207 "initiator", &i)) { 208 if (0 == i) { 209 ocs->config_ini = FALSE; 210 device_printf(ocs->dev, "Disabling initiator\n"); 211 } 212 } 213 ocs->enable_ini = ocs->config_ini; 214 215 if (!ocs->config_ini && !ocs->config_tgt) { 216 device_printf(ocs->dev, "Unsupported, both initiator and target mode disabled.\n"); 217 return 1; 218 } 219 220 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 221 "logmask", &logmask)) { 222 device_printf(ocs->dev, "logmask = %#x\n", logmask); 223 } 224 225 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 226 "logdest", &logdest)) { 227 device_printf(ocs->dev, "logdest = %#x\n", logdest); 228 } 229 230 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 231 "loglevel", &loglevel)) { 232 device_printf(ocs->dev, "loglevel = %#x\n", loglevel); 233 } 234 235 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 236 "ramlog_size", &ramlog_size)) { 237 device_printf(ocs->dev, "ramlog_size = %#x\n", ramlog_size); 238 } 239 240 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 241 "ddump_saved_size", &ddump_saved_size)) { 242 device_printf(ocs->dev, "ddump_saved_size= %#x\n", ddump_saved_size); 243 } 244 245 /* If enabled, initailize a RAM logging buffer */ 246 if (logdest & 2) { 247 ocs->ramlog = ocs_ramlog_init(ocs, ramlog_size/OCS_RAMLOG_DEFAULT_BUFFERS, 248 OCS_RAMLOG_DEFAULT_BUFFERS); 249 /* If NULL was returned, then we'll simply skip using the ramlog but */ 250 /* set logdest to 1 to ensure that we at least get default logging. */ 251 if (ocs->ramlog == NULL) { 252 logdest = 1; 253 } 254 } 255 256 /* initialize a saved ddump */ 257 if (ddump_saved_size) { 258 if (ocs_textbuf_alloc(ocs, &ocs->ddump_saved, ddump_saved_size)) { 259 ocs_log_err(ocs, "failed to allocate memory for saved ddump\n"); 260 } 261 } 262 263 if (0 == resource_string_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 264 "hw_war_version", &hw_war_version)) { 265 device_printf(ocs->dev, "hw_war_version = %s\n", hw_war_version); 266 ocs->hw_war_version = strdup(hw_war_version, M_OCS); 267 } 268 269 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 270 "explicit_buffer_list", &i)) { 271 ocs->explicit_buffer_list = i; 272 } 273 274 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 275 "ethernet_license", &i)) { 276 ocs->ethernet_license = i; 277 } 278 279 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 280 "speed", &i)) { 281 device_printf(ocs->dev, "speed = %d Mbps\n", i); 282 ocs->speed = i; 283 } 284 ocs->desc = device_get_desc(ocs->dev); 285 286 ocs_device_lock_init(ocs); 287 ocs->driver_version = STR_BE_MAJOR "." STR_BE_MINOR "." STR_BE_BUILD "." STR_BE_BRANCH; 288 ocs->model = ocs_pci_model(ocs->pci_vendor, ocs->pci_device); 289 290 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 291 "enable_hlm", &i)) { 292 device_printf(ocs->dev, "enable_hlm = %d\n", i); 293 ocs->enable_hlm = i; 294 if (ocs->enable_hlm) { 295 ocs->hlm_group_size = 8; 296 297 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 298 "hlm_group_size", &i)) { 299 ocs->hlm_group_size = i; 300 } 301 device_printf(ocs->dev, "hlm_group_size = %d\n", i); 302 } 303 } 304 305 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 306 "num_scsi_ios", &i)) { 307 ocs->num_scsi_ios = i; 308 device_printf(ocs->dev, "num_scsi_ios = %d\n", ocs->num_scsi_ios); 309 } else { 310 ocs->num_scsi_ios = 8192; 311 } 312 313 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 314 "topology", &i)) { 315 ocs->topology = i; 316 device_printf(ocs->dev, "Setting topology=%#x\n", i); 317 } 318 319 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 320 "num_vports", &i)) { 321 if (i >= 0 && i <= 254) { 322 device_printf(ocs->dev, "num_vports = %d\n", i); 323 ocs->num_vports = i; 324 } else { 325 device_printf(ocs->dev, "num_vports: %d not supported \n", i); 326 } 327 } 328 329 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 330 "external_loopback", &i)) { 331 device_printf(ocs->dev, "external_loopback = %d\n", i); 332 ocs->external_loopback = i; 333 } 334 335 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 336 "tgt_rscn_delay", &i)) { 337 device_printf(ocs->dev, "tgt_rscn_delay = %d\n", i); 338 ocs->tgt_rscn_delay_msec = i * 1000; 339 } 340 341 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 342 "tgt_rscn_period", &i)) { 343 device_printf(ocs->dev, "tgt_rscn_period = %d\n", i); 344 ocs->tgt_rscn_period_msec = i * 1000; 345 } 346 347 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 348 "target_io_timer", &i)) { 349 device_printf(ocs->dev, "target_io_timer = %d\n", i); 350 ocs->target_io_timer_sec = i; 351 } 352 353 hw_global.queue_topology_string = queue_topology; 354 ocs->rq_selection_policy = 0; 355 ocs->rr_quanta = 1; 356 ocs->filter_def = "0,0,0,0"; 357 358 return 0; 359 } 360 361 static int32_t 362 ocs_setup_fcports(ocs_t *ocs) 363 { 364 uint32_t i = 0, role = 0; 365 uint64_t sli_wwpn, sli_wwnn; 366 size_t size; 367 ocs_xport_t *xport = ocs->xport; 368 ocs_vport_spec_t *vport; 369 ocs_fcport *fcp = NULL; 370 371 size = sizeof(ocs_fcport) * (ocs->num_vports + 1); 372 373 ocs->fcports = ocs_malloc(ocs, size, M_ZERO|M_NOWAIT); 374 if (ocs->fcports == NULL) { 375 device_printf(ocs->dev, "Can't allocate fcport \n"); 376 return 1; 377 } 378 379 role = (ocs->enable_ini)? KNOB_ROLE_INITIATOR: 0 | 380 (ocs->enable_tgt)? KNOB_ROLE_TARGET: 0; 381 382 fcp = FCPORT(ocs, i); 383 fcp->role = role; 384 i++; 385 386 ocs_list_foreach(&xport->vport_list, vport) { 387 fcp = FCPORT(ocs, i); 388 vport->tgt_data = fcp; 389 fcp->vport = vport; 390 fcp->role = role; 391 392 if (ocs_hw_get_def_wwn(ocs, i, &sli_wwpn, &sli_wwnn)) { 393 ocs_log_err(ocs, "Get default wwn failed \n"); 394 i++; 395 continue; 396 } 397 398 vport->wwpn = ocs_be64toh(sli_wwpn); 399 vport->wwnn = ocs_be64toh(sli_wwnn); 400 i++; 401 ocs_log_debug(ocs, "VPort wwpn: %lx wwnn: %lx \n", vport->wwpn, vport->wwnn); 402 } 403 404 return 0; 405 } 406 407 int32_t 408 ocs_device_attach(ocs_t *ocs) 409 { 410 int32_t i; 411 ocs_io_t *io = NULL; 412 413 if (ocs->attached) { 414 ocs_log_warn(ocs, "%s: Device is already attached\n", __func__); 415 return -1; 416 } 417 418 /* Allocate transport object and bring online */ 419 ocs->xport = ocs_xport_alloc(ocs); 420 if (ocs->xport == NULL) { 421 device_printf(ocs->dev, "failed to allocate transport object\n"); 422 return ENOMEM; 423 } else if (ocs_xport_attach(ocs->xport) != 0) { 424 device_printf(ocs->dev, "%s: failed to attach transport object\n", __func__); 425 goto fail_xport_attach; 426 } else if (ocs_xport_initialize(ocs->xport) != 0) { 427 device_printf(ocs->dev, "%s: failed to initialize transport object\n", __func__); 428 goto fail_xport_init; 429 } 430 431 if (ocs_init_dma_tag(ocs)) { 432 goto fail_intr_setup; 433 } 434 435 for (i = 0; (io = ocs_io_get_instance(ocs, i)); i++) { 436 if (bus_dmamap_create(ocs->buf_dmat, 0, &io->tgt_io.dmap)) { 437 device_printf(ocs->dev, "%s: bad dma map create\n", __func__); 438 } 439 440 io->tgt_io.state = OCS_CAM_IO_FREE; 441 } 442 443 if (ocs_setup_fcports(ocs)) { 444 device_printf(ocs->dev, "FCports creation failed\n"); 445 goto fail_intr_setup; 446 } 447 448 if (ocs_cam_attach(ocs)) { 449 device_printf(ocs->dev, "cam attach failed \n"); 450 goto fail_intr_setup; 451 } 452 453 if (ocs_intr_setup(ocs)) { 454 device_printf(ocs->dev, "Interrupt setup failed\n"); 455 goto fail_intr_setup; 456 } 457 458 if (ocs->enable_ini || ocs->enable_tgt) { 459 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE)) { 460 device_printf(ocs->dev, "Can't init port\n"); 461 goto fail_xport_online; 462 } 463 } 464 465 ocs->attached = true; 466 467 return 0; 468 469 fail_xport_online: 470 if (ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN)) { 471 device_printf(ocs->dev, "Transport Shutdown timed out\n"); 472 } 473 ocs_intr_teardown(ocs); 474 fail_intr_setup: 475 fail_xport_init: 476 ocs_xport_detach(ocs->xport); 477 if (ocs->config_tgt) 478 ocs_scsi_tgt_del_device(ocs); 479 480 ocs_xport_free(ocs->xport); 481 ocs->xport = NULL; 482 fail_xport_attach: 483 if (ocs->xport) 484 ocs_free(ocs, ocs->xport, sizeof(*(ocs->xport))); 485 ocs->xport = NULL; 486 return ENXIO; 487 } 488 489 /** 490 * @brief Connect the driver to the given device 491 * 492 * If the probe routine is successful, the OS will give the driver 493 * the opportunity to connect itself to the device. This routine 494 * maps PCI resources (memory BARs and interrupts) and initialize a 495 * hardware object. 496 * 497 * @param dev device abstraction 498 * 499 * @return 0 if the driver attaches to the device, ENXIO otherwise 500 */ 501 502 static int 503 ocs_pci_attach(device_t dev) 504 { 505 struct ocs_softc *ocs; 506 int instance; 507 508 instance = device_get_unit(dev); 509 510 ocs = (struct ocs_softc *)device_get_softc(dev); 511 if (NULL == ocs) { 512 device_printf(dev, "cannot allocate softc\n"); 513 return ENOMEM; 514 } 515 memset(ocs, 0, sizeof(struct ocs_softc)); 516 517 if (instance < ARRAY_SIZE(ocs_devices)) { 518 ocs_devices[instance] = ocs; 519 } else { 520 device_printf(dev, "got unexpected ocs instance number %d\n", instance); 521 } 522 523 ocs->instance_index = instance; 524 525 ocs->dev = dev; 526 527 pci_enable_io(dev, SYS_RES_MEMORY); 528 pci_enable_busmaster(dev); 529 530 ocs->pci_vendor = pci_get_vendor(dev); 531 ocs->pci_device = pci_get_device(dev); 532 ocs->pci_subsystem_vendor = pci_get_subvendor(dev); 533 ocs->pci_subsystem_device = pci_get_subdevice(dev); 534 535 snprintf(ocs->businfo, sizeof(ocs->businfo), "%02X:%02X:%02X", 536 pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)); 537 538 /* Map all memory BARs */ 539 if (ocs->pci_device == PCI_PRODUCT_EMULEX_LANCER_G7) { 540 if(ocs_map_g7_bars(dev,ocs)) { 541 device_printf(dev, "Failed to map pci bars\n"); 542 goto release_bus; 543 } 544 } else { 545 if (ocs_map_bars(dev, ocs)) { 546 device_printf(dev, "Failed to map pci bars\n"); 547 goto release_bus; 548 } 549 } 550 551 /* create a root DMA tag for the device */ 552 if (bus_dma_tag_create(bus_get_dma_tag(dev), 553 1, /* byte alignment */ 554 0, /* no boundary restrictions */ 555 BUS_SPACE_MAXADDR, /* no minimum low address */ 556 BUS_SPACE_MAXADDR, /* no maximum high address */ 557 NULL, /* no filter function */ 558 NULL, /* or arguments */ 559 BUS_SPACE_MAXSIZE, /* max size covered by tag */ 560 BUS_SPACE_UNRESTRICTED, /* no segment count restrictions */ 561 BUS_SPACE_MAXSIZE, /* no segment length restrictions */ 562 0, /* flags */ 563 NULL, /* no lock manipulation function */ 564 NULL, /* or arguments */ 565 &ocs->dmat)) { 566 device_printf(dev, "parent DMA tag allocation failed\n"); 567 goto release_bus; 568 } 569 570 if (ocs_intr_alloc(ocs)) { 571 device_printf(dev, "Interrupt allocation failed\n"); 572 goto release_bus; 573 } 574 575 if (PCIC_SERIALBUS == pci_get_class(dev) && 576 PCIS_SERIALBUS_FC == pci_get_subclass(dev)) 577 ocs->ocs_xport = OCS_XPORT_FC; 578 else { 579 device_printf(dev, "unsupported class (%#x : %#x)\n", 580 pci_get_class(dev), 581 pci_get_class(dev)); 582 goto release_bus; 583 } 584 585 /* Setup tunable parameters */ 586 if (ocs_setup_params(ocs)) { 587 device_printf(ocs->dev, "failed to setup params\n"); 588 goto release_bus; 589 } 590 591 if (ocs_device_attach(ocs)) { 592 device_printf(ocs->dev, "failed to attach device\n"); 593 goto release_params; 594 } 595 596 ocs->fc_type = FC_TYPE_FCP; 597 598 ocs_debug_attach(ocs); 599 600 return 0; 601 602 release_params: 603 ocs_ramlog_free(ocs, ocs->ramlog); 604 ocs_device_lock_free(ocs); 605 free(ocs->hw_war_version, M_OCS); 606 release_bus: 607 ocs_release_bus(ocs); 608 return ENXIO; 609 } 610 611 /** 612 * @brief free resources when pci device detach 613 * 614 * @param ocs pointer to ocs structure 615 * 616 * @return 0 for success, a negative error code value for failure. 617 */ 618 619 int32_t 620 ocs_device_detach(ocs_t *ocs) 621 { 622 int32_t rc = 0, i; 623 ocs_io_t *io = NULL; 624 625 if (ocs != NULL) { 626 if (!ocs->attached) { 627 ocs_log_warn(ocs, "%s: Device is not attached\n", __func__); 628 return -1; 629 } 630 631 ocs->attached = FALSE; 632 633 rc = ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN); 634 if (rc) { 635 ocs_log_err(ocs, "%s: Transport Shutdown timed out\n", __func__); 636 } 637 638 ocs_intr_teardown(ocs); 639 640 if (ocs_xport_detach(ocs->xport) != 0) { 641 ocs_log_err(ocs, "%s: Transport detach failed\n", __func__); 642 } 643 644 ocs_cam_detach(ocs); 645 ocs_free(ocs, ocs->fcports, sizeof(*(ocs->fcports))); 646 647 for (i = 0; (io = ocs_io_get_instance(ocs, i)); i++) { 648 if (bus_dmamap_destroy(ocs->buf_dmat, io->tgt_io.dmap)) { 649 device_printf(ocs->dev, "%s: bad dma map destroy\n", __func__); 650 } 651 } 652 bus_dma_tag_destroy(ocs->dmat); 653 ocs_xport_free(ocs->xport); 654 ocs->xport = NULL; 655 } 656 657 return 0; 658 } 659 660 /** 661 * @brief Detach the driver from the given device 662 * 663 * If the driver is a loadable module, this routine gets called at unload 664 * time. This routine will stop the device and free any allocated resources. 665 * 666 * @param dev device abstraction 667 * 668 * @return 0 if the driver detaches from the device, ENXIO otherwise 669 */ 670 static int 671 ocs_pci_detach(device_t dev) 672 { 673 struct ocs_softc *ocs; 674 675 ocs = (struct ocs_softc *)device_get_softc(dev); 676 if (!ocs) { 677 device_printf(dev, "no driver context?!?\n"); 678 return -1; 679 } 680 681 if (ocs->config_tgt && ocs->enable_tgt) { 682 device_printf(dev, "can't detach with target mode enabled\n"); 683 return EBUSY; 684 } 685 686 ocs_device_detach(ocs); 687 688 /* 689 * Workaround for OCS SCSI Transport quirk. 690 * 691 * CTL requires that target mode is disabled prior to unloading the 692 * driver (ie ocs->enable_tgt = FALSE), but once the target is disabled, 693 * the transport will not call ocs_scsi_tgt_del_device() which deallocates 694 * CAM resources. The workaround is to explicitly make the call here. 695 */ 696 if (ocs->config_tgt) 697 ocs_scsi_tgt_del_device(ocs); 698 699 /* free strdup created buffer.*/ 700 free(ocs->hw_war_version, M_OCS); 701 702 ocs_device_lock_free(ocs); 703 704 ocs_debug_detach(ocs); 705 706 ocs_ramlog_free(ocs, ocs->ramlog); 707 708 ocs_release_bus(ocs); 709 710 return 0; 711 } 712 713 /** 714 * @brief Notify driver of system shutdown 715 * 716 * @param dev device abstraction 717 * 718 * @return 0 if the driver attaches to the device, ENXIO otherwise 719 */ 720 static int 721 ocs_pci_shutdown(device_t dev) 722 { 723 device_printf(dev, "%s\n", __func__); 724 return 0; 725 } 726 727 /** 728 * @brief Release bus resources allocated within the soft context 729 * 730 * @param ocs Pointer to the driver's context 731 * 732 * @return none 733 */ 734 static void 735 ocs_release_bus(struct ocs_softc *ocs) 736 { 737 738 if (NULL != ocs) { 739 uint32_t i; 740 741 ocs_intr_teardown(ocs); 742 743 if (ocs->irq) { 744 bus_release_resource(ocs->dev, SYS_RES_IRQ, 745 rman_get_rid(ocs->irq), ocs->irq); 746 747 if (ocs->n_vec) { 748 pci_release_msi(ocs->dev); 749 ocs->n_vec = 0; 750 } 751 752 ocs->irq = NULL; 753 } 754 755 bus_dma_tag_destroy(ocs->dmat); 756 757 for (i = 0; i < PCI_MAX_BAR; i++) { 758 if (ocs->reg[i].res) { 759 bus_release_resource(ocs->dev, SYS_RES_MEMORY, 760 ocs->reg[i].rid, 761 ocs->reg[i].res); 762 } 763 } 764 } 765 } 766 767 /** 768 * @brief Allocate and initialize interrupts 769 * 770 * @param ocs Pointer to the driver's context 771 * 772 * @return none 773 */ 774 static int32_t 775 ocs_intr_alloc(struct ocs_softc *ocs) 776 { 777 778 ocs->n_vec = 1; 779 if (pci_alloc_msix(ocs->dev, &ocs->n_vec)) { 780 device_printf(ocs->dev, "MSI-X allocation failed\n"); 781 if (pci_alloc_msi(ocs->dev, &ocs->n_vec)) { 782 device_printf(ocs->dev, "MSI allocation failed \n"); 783 ocs->irqid = 0; 784 ocs->n_vec = 0; 785 } else 786 ocs->irqid = 1; 787 } else { 788 ocs->irqid = 1; 789 } 790 791 ocs->irq = bus_alloc_resource_any(ocs->dev, SYS_RES_IRQ, &ocs->irqid, 792 RF_ACTIVE | RF_SHAREABLE); 793 if (NULL == ocs->irq) { 794 device_printf(ocs->dev, "could not allocate interrupt\n"); 795 return -1; 796 } 797 798 ocs->intr_ctx.vec = 0; 799 ocs->intr_ctx.softc = ocs; 800 snprintf(ocs->intr_ctx.name, sizeof(ocs->intr_ctx.name), 801 "%s_intr_%d", 802 device_get_nameunit(ocs->dev), 803 ocs->intr_ctx.vec); 804 805 return 0; 806 } 807 808 /** 809 * @brief Create and attach an interrupt handler 810 * 811 * @param ocs Pointer to the driver's context 812 * 813 * @return 0 on success, non-zero otherwise 814 */ 815 static int32_t 816 ocs_intr_setup(struct ocs_softc *ocs) 817 { 818 driver_filter_t *filter = NULL; 819 820 if (0 == ocs->n_vec) { 821 filter = ocs_pci_intx_filter; 822 } 823 824 if (bus_setup_intr(ocs->dev, ocs->irq, INTR_MPSAFE | INTR_TYPE_CAM, 825 filter, ocs_pci_intr, &ocs->intr_ctx, 826 &ocs->tag)) { 827 device_printf(ocs->dev, "could not initialize interrupt\n"); 828 return -1; 829 } 830 831 return 0; 832 } 833 834 /** 835 * @brief Detach an interrupt handler 836 * 837 * @param ocs Pointer to the driver's context 838 * 839 * @return 0 on success, non-zero otherwise 840 */ 841 static int32_t 842 ocs_intr_teardown(struct ocs_softc *ocs) 843 { 844 845 if (!ocs) { 846 printf("%s: bad driver context?!?\n", __func__); 847 return -1; 848 } 849 850 if (ocs->tag) { 851 bus_teardown_intr(ocs->dev, ocs->irq, ocs->tag); 852 ocs->tag = NULL; 853 } 854 855 return 0; 856 } 857 858 /** 859 * @brief PCI interrupt handler 860 * 861 * @param arg pointer to the driver's software context 862 * 863 * @return FILTER_HANDLED if interrupt is processed, FILTER_STRAY otherwise 864 */ 865 static int 866 ocs_pci_intx_filter(void *arg) 867 { 868 ocs_intr_ctx_t *intr = arg; 869 struct ocs_softc *ocs = NULL; 870 uint16_t val = 0; 871 872 if (NULL == intr) { 873 return FILTER_STRAY; 874 } 875 876 ocs = intr->softc; 877 #ifndef PCIM_STATUS_INTR 878 #define PCIM_STATUS_INTR 0x0008 879 #endif 880 val = pci_read_config(ocs->dev, PCIR_STATUS, 2); 881 if (0xffff == val) { 882 device_printf(ocs->dev, "%s: pci_read_config(PCIR_STATUS) failed\n", __func__); 883 return FILTER_STRAY; 884 } 885 if (0 == (val & PCIM_STATUS_INTR)) { 886 return FILTER_STRAY; 887 } 888 889 val = pci_read_config(ocs->dev, PCIR_COMMAND, 2); 890 val |= PCIM_CMD_INTxDIS; 891 pci_write_config(ocs->dev, PCIR_COMMAND, val, 2); 892 893 return FILTER_SCHEDULE_THREAD; 894 } 895 896 /** 897 * @brief interrupt handler 898 * 899 * @param context pointer to the interrupt context 900 */ 901 static void 902 ocs_pci_intr(void *context) 903 { 904 ocs_intr_ctx_t *intr = context; 905 struct ocs_softc *ocs = intr->softc; 906 907 mtx_lock(&ocs->sim_lock); 908 ocs_hw_process(&ocs->hw, intr->vec, OCS_OS_MAX_ISR_TIME_MSEC); 909 mtx_unlock(&ocs->sim_lock); 910 } 911 912 /** 913 * @brief Initialize DMA tag 914 * 915 * @param ocs the driver instance's software context 916 * 917 * @return 0 on success, non-zero otherwise 918 */ 919 static int32_t 920 ocs_init_dma_tag(struct ocs_softc *ocs) 921 { 922 uint32_t max_sgl = 0; 923 uint32_t max_sge = 0; 924 925 /* 926 * IOs can't use the parent DMA tag and must create their 927 * own, based primarily on a restricted number of DMA segments. 928 * This is more of a BSD requirement than a SLI Port requirement 929 */ 930 ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &max_sgl); 931 ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &max_sge); 932 933 if (bus_dma_tag_create(ocs->dmat, 934 1, /* byte alignment */ 935 0, /* no boundary restrictions */ 936 BUS_SPACE_MAXADDR, /* no minimum low address */ 937 BUS_SPACE_MAXADDR, /* no maximum high address */ 938 NULL, /* no filter function */ 939 NULL, /* or arguments */ 940 BUS_SPACE_MAXSIZE, /* max size covered by tag */ 941 max_sgl, /* segment count restrictions */ 942 max_sge, /* segment length restrictions */ 943 0, /* flags */ 944 NULL, /* no lock manipulation function */ 945 NULL, /* or arguments */ 946 &ocs->buf_dmat)) { 947 device_printf(ocs->dev, "%s: bad bus_dma_tag_create(buf_dmat)\n", __func__); 948 return -1; 949 } 950 return 0; 951 } 952 953 int32_t 954 ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len) 955 { 956 return -1; 957 } 958 959 /** 960 * @brief return pointer to ocs structure given instance index 961 * 962 * A pointer to an ocs structure is returned given an instance index. 963 * 964 * @param index index to ocs_devices array 965 * 966 * @return ocs pointer 967 */ 968 969 ocs_t *ocs_get_instance(uint32_t index) 970 { 971 if (index < ARRAY_SIZE(ocs_devices)) { 972 return ocs_devices[index]; 973 } 974 return NULL; 975 } 976 977 /** 978 * @brief Return instance index of an opaque ocs structure 979 * 980 * Returns the ocs instance index 981 * 982 * @param os pointer to ocs instance 983 * 984 * @return pointer to ocs instance index 985 */ 986 uint32_t 987 ocs_instance(void *os) 988 { 989 ocs_t *ocs = os; 990 return ocs->instance_index; 991 } 992 993 static device_method_t ocs_methods[] = { 994 DEVMETHOD(device_probe, ocs_pci_probe), 995 DEVMETHOD(device_attach, ocs_pci_attach), 996 DEVMETHOD(device_detach, ocs_pci_detach), 997 DEVMETHOD(device_shutdown, ocs_pci_shutdown), 998 {0, 0} 999 }; 1000 1001 static driver_t ocs_driver = { 1002 "ocs_fc", 1003 ocs_methods, 1004 sizeof(struct ocs_softc) 1005 }; 1006 1007 DRIVER_MODULE(ocs_fc, pci, ocs_driver, 0, 0); 1008 MODULE_VERSION(ocs_fc, 1); 1009