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 default: 106 return ENXIO; 107 } 108 109 device_set_desc(dev, desc); 110 111 return BUS_PROBE_DEFAULT; 112 } 113 114 static int 115 ocs_map_bars(device_t dev, struct ocs_softc *ocs) 116 { 117 118 /* 119 * Map PCI BAR0 register into the CPU's space. 120 */ 121 122 ocs->reg[0].rid = PCIR_BAR(PCI_64BIT_BAR0); 123 ocs->reg[0].res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, 124 &ocs->reg[0].rid, RF_ACTIVE); 125 126 if (ocs->reg[0].res == NULL) { 127 device_printf(dev, "bus_alloc_resource failed rid=%#x\n", 128 ocs->reg[0].rid); 129 return ENXIO; 130 } 131 132 ocs->reg[0].btag = rman_get_bustag(ocs->reg[0].res); 133 ocs->reg[0].bhandle = rman_get_bushandle(ocs->reg[0].res); 134 return 0; 135 } 136 137 static int 138 ocs_setup_params(struct ocs_softc *ocs) 139 { 140 int32_t i = 0; 141 const char *hw_war_version; 142 /* Setup tunable parameters */ 143 ocs->ctrlmask = ctrlmask; 144 ocs->speed = 0; 145 ocs->topology = 0; 146 ocs->ethernet_license = 0; 147 ocs->num_scsi_ios = 8192; 148 ocs->enable_hlm = 0; 149 ocs->hlm_group_size = 8; 150 ocs->logmask = logmask; 151 152 ocs->config_tgt = FALSE; 153 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 154 "target", &i)) { 155 if (1 == i) { 156 ocs->config_tgt = TRUE; 157 device_printf(ocs->dev, "Enabling target\n"); 158 } 159 } 160 161 ocs->config_ini = TRUE; 162 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 163 "initiator", &i)) { 164 if (0 == i) { 165 ocs->config_ini = FALSE; 166 device_printf(ocs->dev, "Disabling initiator\n"); 167 } 168 } 169 ocs->enable_ini = ocs->config_ini; 170 171 if (!ocs->config_ini && !ocs->config_tgt) { 172 device_printf(ocs->dev, "Unsupported, both initiator and target mode disabled.\n"); 173 return 1; 174 } 175 176 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 177 "logmask", &logmask)) { 178 device_printf(ocs->dev, "logmask = %#x\n", logmask); 179 } 180 181 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 182 "logdest", &logdest)) { 183 device_printf(ocs->dev, "logdest = %#x\n", logdest); 184 } 185 186 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 187 "loglevel", &loglevel)) { 188 device_printf(ocs->dev, "loglevel = %#x\n", loglevel); 189 } 190 191 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 192 "ramlog_size", &ramlog_size)) { 193 device_printf(ocs->dev, "ramlog_size = %#x\n", ramlog_size); 194 } 195 196 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 197 "ddump_saved_size", &ddump_saved_size)) { 198 device_printf(ocs->dev, "ddump_saved_size= %#x\n", ddump_saved_size); 199 } 200 201 /* If enabled, initailize a RAM logging buffer */ 202 if (logdest & 2) { 203 ocs->ramlog = ocs_ramlog_init(ocs, ramlog_size/OCS_RAMLOG_DEFAULT_BUFFERS, 204 OCS_RAMLOG_DEFAULT_BUFFERS); 205 /* If NULL was returned, then we'll simply skip using the ramlog but */ 206 /* set logdest to 1 to ensure that we at least get default logging. */ 207 if (ocs->ramlog == NULL) { 208 logdest = 1; 209 } 210 } 211 212 /* initialize a saved ddump */ 213 if (ddump_saved_size) { 214 if (ocs_textbuf_alloc(ocs, &ocs->ddump_saved, ddump_saved_size)) { 215 ocs_log_err(ocs, "failed to allocate memory for saved ddump\n"); 216 } 217 } 218 219 if (0 == resource_string_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 220 "hw_war_version", &hw_war_version)) { 221 device_printf(ocs->dev, "hw_war_version = %s\n", hw_war_version); 222 ocs->hw_war_version = strdup(hw_war_version, M_OCS); 223 } 224 225 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 226 "explicit_buffer_list", &i)) { 227 ocs->explicit_buffer_list = i; 228 } 229 230 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 231 "ethernet_license", &i)) { 232 ocs->ethernet_license = i; 233 } 234 235 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 236 "speed", &i)) { 237 device_printf(ocs->dev, "speed = %d Mbps\n", i); 238 ocs->speed = i; 239 } 240 ocs->desc = device_get_desc(ocs->dev); 241 242 ocs_device_lock_init(ocs); 243 ocs->driver_version = STR_BE_MAJOR "." STR_BE_MINOR "." STR_BE_BUILD "." STR_BE_BRANCH; 244 ocs->model = ocs_pci_model(ocs->pci_vendor, ocs->pci_device); 245 246 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 247 "enable_hlm", &i)) { 248 device_printf(ocs->dev, "enable_hlm = %d\n", i); 249 ocs->enable_hlm = i; 250 if (ocs->enable_hlm) { 251 ocs->hlm_group_size = 8; 252 253 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 254 "hlm_group_size", &i)) { 255 ocs->hlm_group_size = i; 256 } 257 device_printf(ocs->dev, "hlm_group_size = %d\n", i); 258 } 259 } 260 261 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 262 "num_scsi_ios", &i)) { 263 ocs->num_scsi_ios = i; 264 device_printf(ocs->dev, "num_scsi_ios = %d\n", ocs->num_scsi_ios); 265 } else { 266 ocs->num_scsi_ios = 8192; 267 } 268 269 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 270 "topology", &i)) { 271 ocs->topology = i; 272 device_printf(ocs->dev, "Setting topology=%#x\n", i); 273 } 274 275 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 276 "num_vports", &i)) { 277 if (i >= 0 && i <= 254) { 278 device_printf(ocs->dev, "num_vports = %d\n", i); 279 ocs->num_vports = i; 280 } else { 281 device_printf(ocs->dev, "num_vports: %d not supported \n", i); 282 } 283 } 284 285 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 286 "external_loopback", &i)) { 287 device_printf(ocs->dev, "external_loopback = %d\n", i); 288 ocs->external_loopback = i; 289 } 290 291 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 292 "tgt_rscn_delay", &i)) { 293 device_printf(ocs->dev, "tgt_rscn_delay = %d\n", i); 294 ocs->tgt_rscn_delay_msec = i * 1000; 295 } 296 297 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 298 "tgt_rscn_period", &i)) { 299 device_printf(ocs->dev, "tgt_rscn_period = %d\n", i); 300 ocs->tgt_rscn_period_msec = i * 1000; 301 } 302 303 if (0 == resource_int_value(device_get_name(ocs->dev), device_get_unit(ocs->dev), 304 "target_io_timer", &i)) { 305 device_printf(ocs->dev, "target_io_timer = %d\n", i); 306 ocs->target_io_timer_sec = i; 307 } 308 309 hw_global.queue_topology_string = queue_topology; 310 ocs->rq_selection_policy = 0; 311 ocs->rr_quanta = 1; 312 ocs->filter_def = "0,0,0,0"; 313 314 return 0; 315 } 316 317 static int32_t 318 ocs_setup_fcports(ocs_t *ocs) 319 { 320 uint32_t i = 0, role = 0; 321 uint64_t sli_wwpn, sli_wwnn; 322 size_t size; 323 ocs_xport_t *xport = ocs->xport; 324 ocs_vport_spec_t *vport; 325 ocs_fcport *fcp = NULL; 326 327 size = sizeof(ocs_fcport) * (ocs->num_vports + 1); 328 329 ocs->fcports = ocs_malloc(ocs, size, M_ZERO|M_NOWAIT); 330 if (ocs->fcports == NULL) { 331 device_printf(ocs->dev, "Can't allocate fcport \n"); 332 return 1; 333 } 334 335 role = (ocs->enable_ini)? KNOB_ROLE_INITIATOR: 0 | 336 (ocs->enable_tgt)? KNOB_ROLE_TARGET: 0; 337 338 fcp = FCPORT(ocs, i); 339 fcp->role = role; 340 i++; 341 342 ocs_list_foreach(&xport->vport_list, vport) { 343 fcp = FCPORT(ocs, i); 344 vport->tgt_data = fcp; 345 fcp->vport = vport; 346 fcp->role = role; 347 348 if (ocs_hw_get_def_wwn(ocs, i, &sli_wwpn, &sli_wwnn)) { 349 ocs_log_err(ocs, "Get default wwn failed \n"); 350 i++; 351 continue; 352 } 353 354 vport->wwpn = ocs_be64toh(sli_wwpn); 355 vport->wwnn = ocs_be64toh(sli_wwnn); 356 i++; 357 ocs_log_debug(ocs, "VPort wwpn: %lx wwnn: %lx \n", vport->wwpn, vport->wwnn); 358 } 359 360 return 0; 361 } 362 363 int32_t 364 ocs_device_attach(ocs_t *ocs) 365 { 366 int32_t i; 367 ocs_io_t *io = NULL; 368 369 if (ocs->attached) { 370 ocs_log_warn(ocs, "%s: Device is already attached\n", __func__); 371 return -1; 372 } 373 374 /* Allocate transport object and bring online */ 375 ocs->xport = ocs_xport_alloc(ocs); 376 if (ocs->xport == NULL) { 377 device_printf(ocs->dev, "failed to allocate transport object\n"); 378 return ENOMEM; 379 } else if (ocs_xport_attach(ocs->xport) != 0) { 380 device_printf(ocs->dev, "%s: failed to attach transport object\n", __func__); 381 goto fail_xport_attach; 382 } else if (ocs_xport_initialize(ocs->xport) != 0) { 383 device_printf(ocs->dev, "%s: failed to initialize transport object\n", __func__); 384 goto fail_xport_init; 385 } 386 387 if (ocs_init_dma_tag(ocs)) { 388 goto fail_intr_setup; 389 } 390 391 for (i = 0; (io = ocs_io_get_instance(ocs, i)); i++) { 392 if (bus_dmamap_create(ocs->buf_dmat, 0, &io->tgt_io.dmap)) { 393 device_printf(ocs->dev, "%s: bad dma map create\n", __func__); 394 } 395 396 io->tgt_io.state = OCS_CAM_IO_FREE; 397 } 398 399 if (ocs_setup_fcports(ocs)) { 400 device_printf(ocs->dev, "FCports creation failed\n"); 401 goto fail_intr_setup; 402 } 403 404 if(ocs_cam_attach(ocs)) { 405 device_printf(ocs->dev, "cam attach failed \n"); 406 goto fail_intr_setup; 407 } 408 409 if (ocs_intr_setup(ocs)) { 410 device_printf(ocs->dev, "Interrupt setup failed\n"); 411 goto fail_intr_setup; 412 } 413 414 if (ocs->enable_ini || ocs->enable_tgt) { 415 if (ocs_xport_control(ocs->xport, OCS_XPORT_PORT_ONLINE)) { 416 device_printf(ocs->dev, "Can't init port\n"); 417 goto fail_xport_online; 418 } 419 } 420 421 ocs->attached = true; 422 423 return 0; 424 425 fail_xport_online: 426 if (ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN)) { 427 device_printf(ocs->dev, "Transport Shutdown timed out\n"); 428 } 429 ocs_intr_teardown(ocs); 430 fail_intr_setup: 431 fail_xport_init: 432 ocs_xport_detach(ocs->xport); 433 if (ocs->config_tgt) 434 ocs_scsi_tgt_del_device(ocs); 435 436 ocs_xport_free(ocs->xport); 437 ocs->xport = NULL; 438 fail_xport_attach: 439 if (ocs->xport) 440 ocs_free(ocs, ocs->xport, sizeof(*(ocs->xport))); 441 ocs->xport = NULL; 442 return ENXIO; 443 } 444 445 /** 446 * @brief Connect the driver to the given device 447 * 448 * If the probe routine is successful, the OS will give the driver 449 * the opportunity to connect itself to the device. This routine 450 * maps PCI resources (memory BARs and interrupts) and initialize a 451 * hardware object. 452 * 453 * @param dev device abstraction 454 * 455 * @return 0 if the driver attaches to the device, ENXIO otherwise 456 */ 457 458 static int 459 ocs_pci_attach(device_t dev) 460 { 461 struct ocs_softc *ocs; 462 int instance; 463 464 instance = device_get_unit(dev); 465 466 ocs = (struct ocs_softc *)device_get_softc(dev); 467 if (NULL == ocs) { 468 device_printf(dev, "cannot allocate softc\n"); 469 return ENOMEM; 470 } 471 memset(ocs, 0, sizeof(struct ocs_softc)); 472 473 if (instance < ARRAY_SIZE(ocs_devices)) { 474 ocs_devices[instance] = ocs; 475 } else { 476 device_printf(dev, "got unexpected ocs instance number %d\n", instance); 477 } 478 479 ocs->instance_index = instance; 480 481 ocs->dev = dev; 482 483 pci_enable_io(dev, SYS_RES_MEMORY); 484 pci_enable_busmaster(dev); 485 486 ocs->pci_vendor = pci_get_vendor(dev); 487 ocs->pci_device = pci_get_device(dev); 488 snprintf(ocs->businfo, sizeof(ocs->businfo), "%02X:%02X:%02X", 489 pci_get_bus(dev), pci_get_slot(dev), pci_get_function(dev)); 490 491 /* Map all memory BARs */ 492 if (ocs_map_bars(dev, ocs)) { 493 device_printf(dev, "Failed to map pci bars\n"); 494 goto release_bus; 495 } 496 497 /* create a root DMA tag for the device */ 498 if (bus_dma_tag_create(bus_get_dma_tag(dev), 499 1, /* byte alignment */ 500 0, /* no boundary restrictions */ 501 BUS_SPACE_MAXADDR, /* no minimum low address */ 502 BUS_SPACE_MAXADDR, /* no maximum high address */ 503 NULL, /* no filter function */ 504 NULL, /* or arguments */ 505 BUS_SPACE_MAXSIZE, /* max size covered by tag */ 506 BUS_SPACE_UNRESTRICTED, /* no segment count restrictions */ 507 BUS_SPACE_MAXSIZE, /* no segment length restrictions */ 508 0, /* flags */ 509 NULL, /* no lock manipulation function */ 510 NULL, /* or arguments */ 511 &ocs->dmat)) { 512 device_printf(dev, "parent DMA tag allocation failed\n"); 513 goto release_bus; 514 } 515 516 if (ocs_intr_alloc(ocs)) { 517 device_printf(dev, "Interrupt allocation failed\n"); 518 goto release_bus; 519 } 520 521 if (PCIC_SERIALBUS == pci_get_class(dev) && 522 PCIS_SERIALBUS_FC == pci_get_subclass(dev)) 523 ocs->ocs_xport = OCS_XPORT_FC; 524 else { 525 device_printf(dev, "unsupported class (%#x : %#x)\n", 526 pci_get_class(dev), 527 pci_get_class(dev)); 528 goto release_bus; 529 } 530 531 /* Setup tunable parameters */ 532 if (ocs_setup_params(ocs)) { 533 device_printf(ocs->dev, "failed to setup params\n"); 534 goto release_bus; 535 } 536 537 if (ocs_device_attach(ocs)) { 538 device_printf(ocs->dev, "failed to attach device\n"); 539 goto release_params; 540 } 541 542 ocs->fc_type = FC_TYPE_FCP; 543 544 ocs_debug_attach(ocs); 545 546 return 0; 547 548 release_params: 549 ocs_ramlog_free(ocs, ocs->ramlog); 550 ocs_device_lock_free(ocs); 551 free(ocs->hw_war_version, M_OCS); 552 release_bus: 553 ocs_release_bus(ocs); 554 return ENXIO; 555 } 556 557 /** 558 * @brief free resources when pci device detach 559 * 560 * @param ocs pointer to ocs structure 561 * 562 * @return 0 for success, a negative error code value for failure. 563 */ 564 565 int32_t 566 ocs_device_detach(ocs_t *ocs) 567 { 568 int32_t rc = 0, i; 569 ocs_io_t *io = NULL; 570 571 if (ocs != NULL) { 572 if (!ocs->attached) { 573 ocs_log_warn(ocs, "%s: Device is not attached\n", __func__); 574 return -1; 575 } 576 577 ocs->attached = FALSE; 578 579 rc = ocs_xport_control(ocs->xport, OCS_XPORT_SHUTDOWN); 580 if (rc) { 581 ocs_log_err(ocs, "%s: Transport Shutdown timed out\n", __func__); 582 } 583 584 ocs_intr_teardown(ocs); 585 586 if (ocs_xport_detach(ocs->xport) != 0) { 587 ocs_log_err(ocs, "%s: Transport detach failed\n", __func__); 588 } 589 590 ocs_cam_detach(ocs); 591 ocs_free(ocs, ocs->fcports, sizeof(*(ocs->fcports))); 592 593 for (i = 0; (io = ocs_io_get_instance(ocs, i)); i++) { 594 if (bus_dmamap_destroy(ocs->buf_dmat, io->tgt_io.dmap)) { 595 device_printf(ocs->dev, "%s: bad dma map destroy\n", __func__); 596 } 597 } 598 bus_dma_tag_destroy(ocs->dmat); 599 ocs_xport_free(ocs->xport); 600 ocs->xport = NULL; 601 } 602 603 return 0; 604 } 605 606 /** 607 * @brief Detach the driver from the given device 608 * 609 * If the driver is a loadable module, this routine gets called at unload 610 * time. This routine will stop the device and free any allocated resources. 611 * 612 * @param dev device abstraction 613 * 614 * @return 0 if the driver detaches from the device, ENXIO otherwise 615 */ 616 static int 617 ocs_pci_detach(device_t dev) 618 { 619 struct ocs_softc *ocs; 620 621 ocs = (struct ocs_softc *)device_get_softc(dev); 622 if (!ocs) { 623 device_printf(dev, "no driver context?!?\n"); 624 return -1; 625 } 626 627 if (ocs->config_tgt && ocs->enable_tgt) { 628 device_printf(dev, "can't detach with target mode enabled\n"); 629 return EBUSY; 630 } 631 632 ocs_device_detach(ocs); 633 634 /* 635 * Workaround for OCS SCSI Transport quirk. 636 * 637 * CTL requires that target mode is disabled prior to unloading the 638 * driver (ie ocs->enable_tgt = FALSE), but once the target is disabled, 639 * the transport will not call ocs_scsi_tgt_del_device() which deallocates 640 * CAM resources. The workaround is to explicitly make the call here. 641 */ 642 if (ocs->config_tgt) 643 ocs_scsi_tgt_del_device(ocs); 644 645 /* free strdup created buffer.*/ 646 free(ocs->hw_war_version, M_OCS); 647 648 ocs_device_lock_free(ocs); 649 650 ocs_debug_detach(ocs); 651 652 ocs_ramlog_free(ocs, ocs->ramlog); 653 654 ocs_release_bus(ocs); 655 656 return 0; 657 } 658 659 /** 660 * @brief Notify driver of system shutdown 661 * 662 * @param dev device abstraction 663 * 664 * @return 0 if the driver attaches to the device, ENXIO otherwise 665 */ 666 static int 667 ocs_pci_shutdown(device_t dev) 668 { 669 device_printf(dev, "%s\n", __func__); 670 return 0; 671 } 672 673 /** 674 * @brief Release bus resources allocated within the soft context 675 * 676 * @param ocs Pointer to the driver's context 677 * 678 * @return none 679 */ 680 static void 681 ocs_release_bus(struct ocs_softc *ocs) 682 { 683 684 if (NULL != ocs) { 685 uint32_t i; 686 687 ocs_intr_teardown(ocs); 688 689 if (ocs->irq) { 690 bus_release_resource(ocs->dev, SYS_RES_IRQ, 691 rman_get_rid(ocs->irq), ocs->irq); 692 693 if (ocs->n_vec) { 694 pci_release_msi(ocs->dev); 695 ocs->n_vec = 0; 696 } 697 698 ocs->irq = NULL; 699 } 700 701 bus_dma_tag_destroy(ocs->dmat); 702 703 for (i = 0; i < PCI_MAX_BAR; i++) { 704 if (ocs->reg[i].res) { 705 bus_release_resource(ocs->dev, SYS_RES_MEMORY, 706 ocs->reg[i].rid, 707 ocs->reg[i].res); 708 } 709 } 710 } 711 } 712 713 /** 714 * @brief Allocate and initialize interrupts 715 * 716 * @param ocs Pointer to the driver's context 717 * 718 * @return none 719 */ 720 static int32_t 721 ocs_intr_alloc(struct ocs_softc *ocs) 722 { 723 724 ocs->n_vec = 1; 725 if (pci_alloc_msix(ocs->dev, &ocs->n_vec)) { 726 device_printf(ocs->dev, "MSI-X allocation failed\n"); 727 if (pci_alloc_msi(ocs->dev, &ocs->n_vec)) { 728 device_printf(ocs->dev, "MSI allocation failed \n"); 729 ocs->irqid = 0; 730 ocs->n_vec = 0; 731 } else 732 ocs->irqid = 1; 733 } else { 734 ocs->irqid = 1; 735 } 736 737 ocs->irq = bus_alloc_resource_any(ocs->dev, SYS_RES_IRQ, &ocs->irqid, 738 RF_ACTIVE | RF_SHAREABLE); 739 if (NULL == ocs->irq) { 740 device_printf(ocs->dev, "could not allocate interrupt\n"); 741 return -1; 742 } 743 744 ocs->intr_ctx.vec = 0; 745 ocs->intr_ctx.softc = ocs; 746 snprintf(ocs->intr_ctx.name, sizeof(ocs->intr_ctx.name), 747 "%s_intr_%d", 748 device_get_nameunit(ocs->dev), 749 ocs->intr_ctx.vec); 750 751 return 0; 752 } 753 754 /** 755 * @brief Create and attach an interrupt handler 756 * 757 * @param ocs Pointer to the driver's context 758 * 759 * @return 0 on success, non-zero otherwise 760 */ 761 static int32_t 762 ocs_intr_setup(struct ocs_softc *ocs) 763 { 764 driver_filter_t *filter = NULL; 765 766 if (0 == ocs->n_vec) { 767 filter = ocs_pci_intx_filter; 768 } 769 770 if (bus_setup_intr(ocs->dev, ocs->irq, INTR_MPSAFE | INTR_TYPE_CAM, 771 filter, ocs_pci_intr, &ocs->intr_ctx, 772 &ocs->tag)) { 773 device_printf(ocs->dev, "could not initialize interrupt\n"); 774 return -1; 775 } 776 777 return 0; 778 } 779 780 /** 781 * @brief Detach an interrupt handler 782 * 783 * @param ocs Pointer to the driver's context 784 * 785 * @return 0 on success, non-zero otherwise 786 */ 787 static int32_t 788 ocs_intr_teardown(struct ocs_softc *ocs) 789 { 790 791 if (!ocs) { 792 printf("%s: bad driver context?!?\n", __func__); 793 return -1; 794 } 795 796 if (ocs->tag) { 797 bus_teardown_intr(ocs->dev, ocs->irq, ocs->tag); 798 ocs->tag = NULL; 799 } 800 801 return 0; 802 } 803 804 /** 805 * @brief PCI interrupt handler 806 * 807 * @param arg pointer to the driver's software context 808 * 809 * @return FILTER_HANDLED if interrupt is processed, FILTER_STRAY otherwise 810 */ 811 static int 812 ocs_pci_intx_filter(void *arg) 813 { 814 ocs_intr_ctx_t *intr = arg; 815 struct ocs_softc *ocs = NULL; 816 uint16_t val = 0; 817 818 if (NULL == intr) { 819 return FILTER_STRAY; 820 } 821 822 ocs = intr->softc; 823 #ifndef PCIM_STATUS_INTR 824 #define PCIM_STATUS_INTR 0x0008 825 #endif 826 val = pci_read_config(ocs->dev, PCIR_STATUS, 2); 827 if (0xffff == val) { 828 device_printf(ocs->dev, "%s: pci_read_config(PCIR_STATUS) failed\n", __func__); 829 return FILTER_STRAY; 830 } 831 if (0 == (val & PCIM_STATUS_INTR)) { 832 return FILTER_STRAY; 833 } 834 835 val = pci_read_config(ocs->dev, PCIR_COMMAND, 2); 836 val |= PCIM_CMD_INTxDIS; 837 pci_write_config(ocs->dev, PCIR_COMMAND, val, 2); 838 839 return FILTER_SCHEDULE_THREAD; 840 } 841 842 /** 843 * @brief interrupt handler 844 * 845 * @param context pointer to the interrupt context 846 */ 847 static void 848 ocs_pci_intr(void *context) 849 { 850 ocs_intr_ctx_t *intr = context; 851 struct ocs_softc *ocs = intr->softc; 852 853 mtx_lock(&ocs->sim_lock); 854 ocs_hw_process(&ocs->hw, intr->vec, OCS_OS_MAX_ISR_TIME_MSEC); 855 mtx_unlock(&ocs->sim_lock); 856 } 857 858 /** 859 * @brief Initialize DMA tag 860 * 861 * @param ocs the driver instance's software context 862 * 863 * @return 0 on success, non-zero otherwise 864 */ 865 static int32_t 866 ocs_init_dma_tag(struct ocs_softc *ocs) 867 { 868 uint32_t max_sgl = 0; 869 uint32_t max_sge = 0; 870 871 /* 872 * IOs can't use the parent DMA tag and must create their 873 * own, based primarily on a restricted number of DMA segments. 874 * This is more of a BSD requirement than a SLI Port requirement 875 */ 876 ocs_hw_get(&ocs->hw, OCS_HW_N_SGL, &max_sgl); 877 ocs_hw_get(&ocs->hw, OCS_HW_MAX_SGE, &max_sge); 878 879 if (bus_dma_tag_create(ocs->dmat, 880 1, /* byte alignment */ 881 0, /* no boundary restrictions */ 882 BUS_SPACE_MAXADDR, /* no minimum low address */ 883 BUS_SPACE_MAXADDR, /* no maximum high address */ 884 NULL, /* no filter function */ 885 NULL, /* or arguments */ 886 BUS_SPACE_MAXSIZE, /* max size covered by tag */ 887 max_sgl, /* segment count restrictions */ 888 max_sge, /* segment length restrictions */ 889 0, /* flags */ 890 NULL, /* no lock manipulation function */ 891 NULL, /* or arguments */ 892 &ocs->buf_dmat)) { 893 device_printf(ocs->dev, "%s: bad bus_dma_tag_create(buf_dmat)\n", __func__); 894 return -1; 895 } 896 return 0; 897 } 898 899 int32_t 900 ocs_get_property(const char *prop_name, char *buffer, uint32_t buffer_len) 901 { 902 return -1; 903 } 904 905 /** 906 * @brief return pointer to ocs structure given instance index 907 * 908 * A pointer to an ocs structure is returned given an instance index. 909 * 910 * @param index index to ocs_devices array 911 * 912 * @return ocs pointer 913 */ 914 915 ocs_t *ocs_get_instance(uint32_t index) 916 { 917 if (index < ARRAY_SIZE(ocs_devices)) { 918 return ocs_devices[index]; 919 } 920 return NULL; 921 } 922 923 /** 924 * @brief Return instance index of an opaque ocs structure 925 * 926 * Returns the ocs instance index 927 * 928 * @param os pointer to ocs instance 929 * 930 * @return pointer to ocs instance index 931 */ 932 uint32_t 933 ocs_instance(void *os) 934 { 935 ocs_t *ocs = os; 936 return ocs->instance_index; 937 } 938 939 static device_method_t ocs_methods[] = { 940 DEVMETHOD(device_probe, ocs_pci_probe), 941 DEVMETHOD(device_attach, ocs_pci_attach), 942 DEVMETHOD(device_detach, ocs_pci_detach), 943 DEVMETHOD(device_shutdown, ocs_pci_shutdown), 944 {0, 0} 945 }; 946 947 static driver_t ocs_driver = { 948 "ocs_fc", 949 ocs_methods, 950 sizeof(struct ocs_softc) 951 }; 952 953 static devclass_t ocs_devclass; 954 955 DRIVER_MODULE(ocs_fc, pci, ocs_driver, ocs_devclass, 0, 0); 956 MODULE_VERSION(ocs_fc, 1); 957