1 /*- 2 * Copyright 2016-2021 Microchip Technology, Inc. and/or its subsidiaries. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23 * SUCH DAMAGE. 24 */ 25 26 /* $FreeBSD$ */ 27 /* 28 * CAM interface for smartpqi driver 29 */ 30 31 #include "smartpqi_includes.h" 32 33 /* 34 * Set cam sim properties of the smartpqi adapter. 35 */ 36 static void 37 update_sim_properties(struct cam_sim *sim, struct ccb_pathinq *cpi) 38 { 39 40 pqisrc_softstate_t *softs = (struct pqisrc_softstate *) 41 cam_sim_softc(sim); 42 43 device_t dev = softs->os_specific.pqi_dev; 44 45 DBG_FUNC("IN\n"); 46 47 cpi->version_num = 1; 48 cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; 49 cpi->target_sprt = 0; 50 cpi->hba_misc = PIM_NOBUSRESET | PIM_UNMAPPED; 51 cpi->hba_eng_cnt = 0; 52 cpi->max_lun = PQI_MAX_MULTILUN; 53 cpi->max_target = 1088; 54 cpi->maxio = (softs->pqi_cap.max_sg_elem - 1) * PAGE_SIZE; 55 cpi->initiator_id = 255; 56 strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); 57 strlcpy(cpi->hba_vid, "Microsemi", HBA_IDLEN); 58 strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); 59 cpi->unit_number = cam_sim_unit(sim); 60 cpi->bus_id = cam_sim_bus(sim); 61 cpi->base_transfer_speed = 1200000; /* Base bus speed in KB/sec */ 62 cpi->protocol = PROTO_SCSI; 63 cpi->protocol_version = SCSI_REV_SPC4; 64 cpi->transport = XPORT_SPI; 65 cpi->transport_version = 2; 66 cpi->ccb_h.status = CAM_REQ_CMP; 67 cpi->hba_vendor = pci_get_vendor(dev); 68 cpi->hba_device = pci_get_device(dev); 69 cpi->hba_subvendor = pci_get_subvendor(dev); 70 cpi->hba_subdevice = pci_get_subdevice(dev); 71 72 73 DBG_FUNC("OUT\n"); 74 } 75 76 /* 77 * Get transport settings of the smartpqi adapter 78 */ 79 static void 80 get_transport_settings(struct pqisrc_softstate *softs, 81 struct ccb_trans_settings *cts) 82 { 83 struct ccb_trans_settings_scsi *scsi = &cts->proto_specific.scsi; 84 struct ccb_trans_settings_sas *sas = &cts->xport_specific.sas; 85 struct ccb_trans_settings_spi *spi = &cts->xport_specific.spi; 86 87 DBG_FUNC("IN\n"); 88 89 cts->protocol = PROTO_SCSI; 90 cts->protocol_version = SCSI_REV_SPC4; 91 cts->transport = XPORT_SPI; 92 cts->transport_version = 2; 93 spi->valid = CTS_SPI_VALID_DISC; 94 spi->flags = CTS_SPI_FLAGS_DISC_ENB; 95 scsi->valid = CTS_SCSI_VALID_TQ; 96 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 97 sas->valid = CTS_SAS_VALID_SPEED; 98 cts->ccb_h.status = CAM_REQ_CMP; 99 100 DBG_FUNC("OUT\n"); 101 } 102 103 /* 104 * Add the target to CAM layer and rescan, when a new device is found 105 */ 106 void 107 os_add_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 108 { 109 union ccb *ccb; 110 111 DBG_FUNC("IN\n"); 112 113 if(softs->os_specific.sim_registered) { 114 if ((ccb = xpt_alloc_ccb_nowait()) == NULL) { 115 DBG_ERR("rescan failed (can't allocate CCB)\n"); 116 return; 117 } 118 119 if (xpt_create_path(&ccb->ccb_h.path, NULL, 120 cam_sim_path(softs->os_specific.sim), 121 device->target, device->lun) != CAM_REQ_CMP) { 122 DBG_ERR("rescan failed (can't create path)\n"); 123 xpt_free_ccb(ccb); 124 return; 125 } 126 xpt_rescan(ccb); 127 } 128 129 DBG_FUNC("OUT\n"); 130 } 131 132 /* 133 * Remove the device from CAM layer when deleted or hot removed 134 */ 135 void 136 os_remove_device(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 137 { 138 struct cam_path *tmppath; 139 140 DBG_FUNC("IN\n"); 141 142 if(softs->os_specific.sim_registered) { 143 if (xpt_create_path(&tmppath, NULL, 144 cam_sim_path(softs->os_specific.sim), 145 device->target, device->lun) != CAM_REQ_CMP) { 146 DBG_ERR("unable to create path for async event"); 147 return; 148 } 149 xpt_async(AC_LOST_DEVICE, tmppath, NULL); 150 xpt_free_path(tmppath); 151 softs->device_list[device->target][device->lun] = NULL; 152 pqisrc_free_device(softs, device); 153 } 154 155 DBG_FUNC("OUT\n"); 156 157 } 158 159 /* 160 * Function to release the frozen simq 161 */ 162 static void 163 pqi_release_camq(rcb_t *rcb) 164 { 165 pqisrc_softstate_t *softs; 166 struct ccb_scsiio *csio; 167 168 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio; 169 softs = rcb->softs; 170 171 DBG_FUNC("IN\n"); 172 173 if (softs->os_specific.pqi_flags & PQI_FLAG_BUSY) { 174 softs->os_specific.pqi_flags &= ~PQI_FLAG_BUSY; 175 if (csio->ccb_h.status & CAM_RELEASE_SIMQ) 176 xpt_release_simq(xpt_path_sim(csio->ccb_h.path), 0); 177 else 178 csio->ccb_h.status |= CAM_RELEASE_SIMQ; 179 } 180 181 DBG_FUNC("OUT\n"); 182 } 183 184 static void 185 pqi_synch_request(rcb_t *rcb) 186 { 187 pqisrc_softstate_t *softs = rcb->softs; 188 189 DBG_IO("IN rcb = %p\n", rcb); 190 191 if (!(rcb->cm_flags & PQI_CMD_MAPPED)) 192 return; 193 194 if (rcb->bcount != 0 ) { 195 if (rcb->data_dir == SOP_DATA_DIR_FROM_DEVICE) 196 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat, 197 rcb->cm_datamap, 198 BUS_DMASYNC_POSTREAD); 199 if (rcb->data_dir == SOP_DATA_DIR_TO_DEVICE) 200 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat, 201 rcb->cm_datamap, 202 BUS_DMASYNC_POSTWRITE); 203 bus_dmamap_unload(softs->os_specific.pqi_buffer_dmat, 204 rcb->cm_datamap); 205 } 206 rcb->cm_flags &= ~PQI_CMD_MAPPED; 207 208 if(rcb->sgt && rcb->nseg) 209 os_mem_free(rcb->softs, (void*)rcb->sgt, 210 rcb->nseg*sizeof(sgt_t)); 211 212 DBG_IO("OUT\n"); 213 } 214 215 /* 216 * Function to dma-unmap the completed request 217 */ 218 static inline void 219 pqi_unmap_request(rcb_t *rcb) 220 { 221 DBG_IO("IN rcb = %p\n", rcb); 222 223 pqi_synch_request(rcb); 224 pqisrc_put_tag(&rcb->softs->taglist, rcb->tag); 225 226 DBG_IO("OUT\n"); 227 } 228 229 /* 230 * Construct meaningful LD name for volume here. 231 */ 232 static void 233 smartpqi_fix_ld_inquiry(pqisrc_softstate_t *softs, struct ccb_scsiio *csio) 234 { 235 struct scsi_inquiry_data *inq = NULL; 236 uint8_t *cdb = NULL; 237 pqi_scsi_dev_t *device = NULL; 238 239 DBG_FUNC("IN\n"); 240 241 if (pqisrc_ctrl_offline(softs)) 242 return; 243 244 cdb = (csio->ccb_h.flags & CAM_CDB_POINTER) ? 245 (uint8_t *)csio->cdb_io.cdb_ptr : csio->cdb_io.cdb_bytes; 246 if(cdb[0] == INQUIRY && 247 (cdb[1] & SI_EVPD) == 0 && 248 (csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN && 249 csio->dxfer_len >= SHORT_INQUIRY_LENGTH) { 250 251 inq = (struct scsi_inquiry_data *)csio->data_ptr; 252 253 device = softs->device_list[csio->ccb_h.target_id][csio->ccb_h.target_lun]; 254 255 /* Let the disks be probed and dealt with via CAM. Only for LD 256 let it fall through and inquiry be tweaked */ 257 if (!device || !pqisrc_is_logical_device(device) || 258 (device->devtype != DISK_DEVICE) || 259 pqisrc_is_external_raid_device(device)) { 260 return; 261 } 262 263 strncpy(inq->vendor, device->vendor, 264 SID_VENDOR_SIZE); 265 strncpy(inq->product, 266 pqisrc_raidlevel_to_string(device->raid_level), 267 SID_PRODUCT_SIZE); 268 strncpy(inq->revision, device->volume_offline?"OFF":"OK", 269 SID_REVISION_SIZE); 270 } 271 272 DBG_FUNC("OUT\n"); 273 } 274 275 static void 276 pqi_complete_scsi_io(struct ccb_scsiio *csio, rcb_t *rcb) 277 { 278 uint32_t release_tag; 279 pqisrc_softstate_t *softs = rcb->softs; 280 281 DBG_IO("IN scsi io = %p\n", csio); 282 283 pqi_synch_request(rcb); 284 smartpqi_fix_ld_inquiry(rcb->softs, csio); 285 pqi_release_camq(rcb); 286 release_tag = rcb->tag; 287 os_reset_rcb(rcb); 288 pqisrc_put_tag(&softs->taglist, release_tag); 289 xpt_done((union ccb *)csio); 290 291 DBG_FUNC("OUT\n"); 292 } 293 294 /* 295 * Handle completion of a command - pass results back through the CCB 296 */ 297 void 298 os_io_response_success(rcb_t *rcb) 299 { 300 struct ccb_scsiio *csio; 301 302 DBG_IO("IN rcb = %p\n", rcb); 303 304 if (rcb == NULL) 305 panic("rcb is null"); 306 307 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio; 308 309 if (csio == NULL) 310 panic("csio is null"); 311 312 rcb->status = REQUEST_SUCCESS; 313 csio->ccb_h.status = CAM_REQ_CMP; 314 315 pqi_complete_scsi_io(csio, rcb); 316 317 DBG_IO("OUT\n"); 318 } 319 320 static void 321 copy_sense_data_to_csio(struct ccb_scsiio *csio, 322 uint8_t *sense_data, uint16_t sense_data_len) 323 { 324 DBG_IO("IN csio = %p\n", csio); 325 326 memset(&csio->sense_data, 0, csio->sense_len); 327 328 sense_data_len = (sense_data_len > csio->sense_len) ? 329 csio->sense_len : sense_data_len; 330 331 if (sense_data) 332 memcpy(&csio->sense_data, sense_data, sense_data_len); 333 334 if (csio->sense_len > sense_data_len) 335 csio->sense_resid = csio->sense_len - sense_data_len; 336 else 337 csio->sense_resid = 0; 338 339 DBG_IO("OUT\n"); 340 } 341 342 /* 343 * Error response handling for raid IO 344 */ 345 void 346 os_raid_response_error(rcb_t *rcb, raid_path_error_info_elem_t *err_info) 347 { 348 struct ccb_scsiio *csio; 349 pqisrc_softstate_t *softs; 350 351 DBG_IO("IN\n"); 352 353 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio; 354 355 if (csio == NULL) 356 panic("csio is null"); 357 358 softs = rcb->softs; 359 360 csio->ccb_h.status = CAM_REQ_CMP_ERR; 361 362 if (!err_info || !rcb->dvp) { 363 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n", 364 err_info, rcb->dvp); 365 goto error_out; 366 } 367 368 csio->scsi_status = err_info->status; 369 370 if (csio->ccb_h.func_code == XPT_SCSI_IO) { 371 /* 372 * Handle specific SCSI status values. 373 */ 374 switch(csio->scsi_status) { 375 case PQI_RAID_STATUS_QUEUE_FULL: 376 csio->ccb_h.status = CAM_REQ_CMP; 377 DBG_ERR("Queue Full error\n"); 378 break; 379 /* check condition, sense data included */ 380 case PQI_RAID_STATUS_CHECK_CONDITION: 381 { 382 uint16_t sense_data_len = 383 LE_16(err_info->sense_data_len); 384 uint8_t *sense_data = NULL; 385 if (sense_data_len) 386 sense_data = err_info->data; 387 copy_sense_data_to_csio(csio, sense_data, sense_data_len); 388 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR 389 | CAM_AUTOSNS_VALID 390 | CAM_REQ_CMP_ERR; 391 392 } 393 break; 394 395 case PQI_RAID_DATA_IN_OUT_UNDERFLOW: 396 { 397 uint32_t resid = 0; 398 resid = rcb->bcount-err_info->data_out_transferred; 399 csio->resid = resid; 400 csio->ccb_h.status = CAM_REQ_CMP; 401 } 402 break; 403 default: 404 csio->ccb_h.status = CAM_REQ_CMP; 405 break; 406 } 407 } 408 409 error_out: 410 pqi_complete_scsi_io(csio, rcb); 411 412 DBG_IO("OUT\n"); 413 } 414 415 /* 416 * Error response handling for aio. 417 */ 418 void 419 os_aio_response_error(rcb_t *rcb, aio_path_error_info_elem_t *err_info) 420 { 421 struct ccb_scsiio *csio; 422 pqisrc_softstate_t *softs; 423 424 DBG_IO("IN\n"); 425 426 if (rcb == NULL) 427 panic("rcb is null"); 428 429 rcb->status = REQUEST_SUCCESS; 430 csio = (struct ccb_scsiio *)&rcb->cm_ccb->csio; 431 if (csio == NULL) 432 panic("csio is null"); 433 434 softs = rcb->softs; 435 436 if (!err_info || !rcb->dvp) { 437 csio->ccb_h.status = CAM_REQ_CMP_ERR; 438 DBG_ERR("couldn't be accessed! error info = %p, rcb->dvp = %p\n", 439 err_info, rcb->dvp); 440 goto error_out; 441 } 442 443 switch (err_info->service_resp) { 444 case PQI_AIO_SERV_RESPONSE_COMPLETE: 445 csio->ccb_h.status = err_info->status; 446 break; 447 case PQI_AIO_SERV_RESPONSE_FAILURE: 448 switch(err_info->status) { 449 case PQI_AIO_STATUS_IO_ABORTED: 450 csio->ccb_h.status = CAM_REQ_ABORTED; 451 DBG_WARN_BTL(rcb->dvp, "IO aborted\n"); 452 break; 453 case PQI_AIO_STATUS_UNDERRUN: 454 csio->ccb_h.status = CAM_REQ_CMP; 455 csio->resid = 456 LE_32(err_info->resd_count); 457 break; 458 case PQI_AIO_STATUS_OVERRUN: 459 csio->ccb_h.status = CAM_REQ_CMP; 460 break; 461 case PQI_AIO_STATUS_AIO_PATH_DISABLED: 462 DBG_WARN_BTL(rcb->dvp,"AIO Path Disabled\n"); 463 /* Timed out TMF response comes here */ 464 if (rcb->tm_req) { 465 rcb->req_pending = false; 466 rcb->status = REQUEST_SUCCESS; 467 DBG_ERR("AIO Disabled for TMF\n"); 468 return; 469 } 470 rcb->dvp->aio_enabled = false; 471 rcb->dvp->offload_enabled = false; 472 csio->ccb_h.status |= CAM_REQUEUE_REQ; 473 break; 474 case PQI_AIO_STATUS_IO_ERROR: 475 case PQI_AIO_STATUS_IO_NO_DEVICE: 476 case PQI_AIO_STATUS_INVALID_DEVICE: 477 default: 478 DBG_WARN_BTL(rcb->dvp,"IO Error/Invalid/No device\n"); 479 csio->ccb_h.status |= 480 CAM_SCSI_STATUS_ERROR; 481 break; 482 } 483 break; 484 case PQI_AIO_SERV_RESPONSE_TMF_COMPLETE: 485 case PQI_AIO_SERV_RESPONSE_TMF_SUCCEEDED: 486 DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n", 487 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_COMPLETE) ? "COMPLETE" : "SUCCEEDED"); 488 rcb->status = REQUEST_SUCCESS; 489 rcb->req_pending = false; 490 return; 491 case PQI_AIO_SERV_RESPONSE_TMF_REJECTED: 492 case PQI_AIO_SERV_RESPONSE_TMF_INCORRECT_LUN: 493 DBG_ERR("PQI_AIO_SERV_RESPONSE_TMF %s\n", 494 (err_info->service_resp == PQI_AIO_SERV_RESPONSE_TMF_REJECTED) ? "REJECTED" : "INCORRECT LUN"); 495 rcb->status = REQUEST_FAILED; 496 rcb->req_pending = false; 497 return; 498 default: 499 DBG_WARN_BTL(rcb->dvp,"Scsi Status Error\n"); 500 csio->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 501 break; 502 } 503 504 if(err_info->data_pres == DATA_PRESENT_SENSE_DATA ) { 505 csio->scsi_status = PQI_AIO_STATUS_CHECK_CONDITION; 506 uint8_t *sense_data = NULL; 507 unsigned sense_data_len = LE_16(err_info->data_len); 508 if (sense_data_len) 509 sense_data = err_info->data; 510 DBG_ERR_BTL(rcb->dvp, "SCSI_STATUS_CHECK_COND sense size %u\n", 511 sense_data_len); 512 copy_sense_data_to_csio(csio, sense_data, sense_data_len); 513 csio->ccb_h.status = CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 514 } 515 516 error_out: 517 pqi_complete_scsi_io(csio, rcb); 518 DBG_IO("OUT\n"); 519 } 520 521 static void 522 pqi_freeze_ccb(union ccb *ccb) 523 { 524 if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) { 525 ccb->ccb_h.status |= CAM_DEV_QFRZN; 526 xpt_freeze_devq(ccb->ccb_h.path, 1); 527 } 528 } 529 530 /* 531 * Command-mapping helper function - populate this command's s/g table. 532 */ 533 static void 534 pqi_request_map_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) 535 { 536 rcb_t *rcb = (rcb_t *)arg; 537 pqisrc_softstate_t *softs = rcb->softs; 538 union ccb *ccb; 539 540 if (error || nseg > softs->pqi_cap.max_sg_elem) { 541 DBG_ERR_BTL(rcb->dvp, "map failed err = %d or nseg(%d) > sgelem(%d)\n", 542 error, nseg, softs->pqi_cap.max_sg_elem); 543 goto error_io; 544 } 545 546 rcb->sgt = os_mem_alloc(softs, nseg * sizeof(sgt_t)); 547 548 if (!rcb->sgt) { 549 DBG_ERR_BTL(rcb->dvp, "os_mem_alloc() failed; nseg = %d\n", nseg); 550 goto error_io; 551 } 552 553 rcb->nseg = nseg; 554 for (int i = 0; i < nseg; i++) { 555 rcb->sgt[i].addr = segs[i].ds_addr; 556 rcb->sgt[i].len = segs[i].ds_len; 557 rcb->sgt[i].flags = 0; 558 } 559 560 if (rcb->data_dir == SOP_DATA_DIR_FROM_DEVICE) 561 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat, 562 rcb->cm_datamap, BUS_DMASYNC_PREREAD); 563 if (rcb->data_dir == SOP_DATA_DIR_TO_DEVICE) 564 bus_dmamap_sync(softs->os_specific.pqi_buffer_dmat, 565 rcb->cm_datamap, BUS_DMASYNC_PREWRITE); 566 567 /* Call IO functions depending on pd or ld */ 568 rcb->status = REQUEST_PENDING; 569 570 error = pqisrc_build_send_io(softs, rcb); 571 572 if (error) { 573 rcb->req_pending = false; 574 DBG_ERR_BTL(rcb->dvp, "Build IO failed, error = %d\n", error); 575 } else { 576 /* Successfully IO was submitted to the device. */ 577 return; 578 } 579 580 error_io: 581 ccb = rcb->cm_ccb; 582 ccb->ccb_h.status = CAM_RESRC_UNAVAIL; 583 pqi_freeze_ccb(ccb); 584 pqi_unmap_request(rcb); 585 xpt_done(ccb); 586 return; 587 } 588 589 /* 590 * Function to dma-map the request buffer 591 */ 592 static int 593 pqi_map_request(rcb_t *rcb) 594 { 595 pqisrc_softstate_t *softs = rcb->softs; 596 int bsd_status = BSD_SUCCESS; 597 union ccb *ccb = rcb->cm_ccb; 598 599 DBG_FUNC("IN\n"); 600 601 /* check that mapping is necessary */ 602 if (rcb->cm_flags & PQI_CMD_MAPPED) 603 return BSD_SUCCESS; 604 605 rcb->cm_flags |= PQI_CMD_MAPPED; 606 607 if (rcb->bcount) { 608 bsd_status = bus_dmamap_load_ccb(softs->os_specific.pqi_buffer_dmat, 609 rcb->cm_datamap, ccb, pqi_request_map_helper, rcb, 0); 610 if (bsd_status != BSD_SUCCESS && bsd_status != EINPROGRESS) { 611 DBG_ERR_BTL(rcb->dvp, "bus_dmamap_load_ccb failed, return status = %d transfer length = %d\n", 612 bsd_status, rcb->bcount); 613 return bsd_status; 614 } 615 } else { 616 /* 617 * Set up the command to go to the controller. If there are no 618 * data buffers associated with the command then it can bypass 619 * busdma. 620 */ 621 /* Call IO functions depending on pd or ld */ 622 rcb->status = REQUEST_PENDING; 623 624 if (pqisrc_build_send_io(softs, rcb) != PQI_STATUS_SUCCESS) { 625 bsd_status = EIO; 626 } 627 } 628 629 DBG_FUNC("OUT error = %d\n", bsd_status); 630 631 return bsd_status; 632 } 633 634 /* 635 * Function to clear the request control block 636 */ 637 void 638 os_reset_rcb(rcb_t *rcb) 639 { 640 rcb->error_info = NULL; 641 rcb->req = NULL; 642 rcb->status = -1; 643 rcb->tag = INVALID_ELEM; 644 rcb->dvp = NULL; 645 rcb->cdbp = NULL; 646 rcb->softs = NULL; 647 rcb->cm_flags = 0; 648 rcb->cm_data = NULL; 649 rcb->bcount = 0; 650 rcb->nseg = 0; 651 rcb->sgt = NULL; 652 rcb->cm_ccb = NULL; 653 rcb->encrypt_enable = false; 654 rcb->ioaccel_handle = 0; 655 rcb->resp_qid = 0; 656 rcb->req_pending = false; 657 rcb->tm_req = false; 658 } 659 660 /* 661 * Callback function for the lun rescan 662 */ 663 static void 664 smartpqi_lunrescan_cb(struct cam_periph *periph, union ccb *ccb) 665 { 666 xpt_free_path(ccb->ccb_h.path); 667 xpt_free_ccb(ccb); 668 } 669 670 671 /* 672 * Function to rescan the lun 673 */ 674 static void 675 smartpqi_lun_rescan(struct pqisrc_softstate *softs, int target, 676 int lun) 677 { 678 union ccb *ccb = NULL; 679 cam_status status = 0; 680 struct cam_path *path = NULL; 681 682 DBG_FUNC("IN\n"); 683 684 ccb = xpt_alloc_ccb_nowait(); 685 if (ccb == NULL) { 686 DBG_ERR("Unable to alloc ccb for lun rescan\n"); 687 return; 688 } 689 690 status = xpt_create_path(&path, NULL, 691 cam_sim_path(softs->os_specific.sim), target, lun); 692 if (status != CAM_REQ_CMP) { 693 DBG_ERR("xpt_create_path status(%d) != CAM_REQ_CMP \n", 694 status); 695 xpt_free_ccb(ccb); 696 return; 697 } 698 699 bzero(ccb, sizeof(union ccb)); 700 xpt_setup_ccb(&ccb->ccb_h, path, 5); 701 ccb->ccb_h.func_code = XPT_SCAN_LUN; 702 ccb->ccb_h.cbfcnp = smartpqi_lunrescan_cb; 703 ccb->crcn.flags = CAM_FLAG_NONE; 704 705 xpt_action(ccb); 706 707 DBG_FUNC("OUT\n"); 708 } 709 710 /* 711 * Function to rescan the lun under each target 712 */ 713 void 714 smartpqi_target_rescan(struct pqisrc_softstate *softs) 715 { 716 int target = 0, lun = 0; 717 718 DBG_FUNC("IN\n"); 719 720 for(target = 0; target < PQI_MAX_DEVICES; target++){ 721 for(lun = 0; lun < PQI_MAX_MULTILUN; lun++){ 722 if(softs->device_list[target][lun]){ 723 smartpqi_lun_rescan(softs, target, lun); 724 } 725 } 726 } 727 728 DBG_FUNC("OUT\n"); 729 } 730 731 /* 732 * Set the mode of tagged command queueing for the current task. 733 */ 734 uint8_t 735 os_get_task_attr(rcb_t *rcb) 736 { 737 union ccb *ccb = rcb->cm_ccb; 738 uint8_t tag_action = SOP_TASK_ATTRIBUTE_SIMPLE; 739 740 switch(ccb->csio.tag_action) { 741 case MSG_HEAD_OF_Q_TAG: 742 tag_action = SOP_TASK_ATTRIBUTE_HEAD_OF_QUEUE; 743 break; 744 case MSG_ORDERED_Q_TAG: 745 tag_action = SOP_TASK_ATTRIBUTE_ORDERED; 746 break; 747 case MSG_SIMPLE_Q_TAG: 748 default: 749 tag_action = SOP_TASK_ATTRIBUTE_SIMPLE; 750 break; 751 } 752 return tag_action; 753 } 754 755 /* 756 * Complete all outstanding commands 757 */ 758 void 759 os_complete_outstanding_cmds_nodevice(pqisrc_softstate_t *softs) 760 { 761 int tag = 0; 762 pqi_scsi_dev_t *dvp = NULL; 763 764 DBG_FUNC("IN\n"); 765 766 for (tag = 1; tag <= softs->max_outstanding_io; tag++) { 767 rcb_t *prcb = &softs->rcb[tag]; 768 dvp = prcb->dvp; 769 if(prcb->req_pending && prcb->cm_ccb ) { 770 prcb->req_pending = false; 771 prcb->cm_ccb->ccb_h.status = CAM_REQ_ABORTED | CAM_REQ_CMP; 772 pqi_complete_scsi_io(&prcb->cm_ccb->csio, prcb); 773 if (dvp) 774 pqisrc_decrement_device_active_io(softs, dvp); 775 776 } 777 } 778 779 DBG_FUNC("OUT\n"); 780 } 781 782 /* 783 * IO handling functionality entry point 784 */ 785 static int 786 pqisrc_io_start(struct cam_sim *sim, union ccb *ccb) 787 { 788 rcb_t *rcb; 789 uint32_t tag, no_transfer = 0; 790 pqisrc_softstate_t *softs = (struct pqisrc_softstate *) 791 cam_sim_softc(sim); 792 int32_t error; 793 pqi_scsi_dev_t *dvp; 794 795 DBG_FUNC("IN\n"); 796 797 if (softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun] == NULL) { 798 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 799 DBG_INFO("Device = %d not there\n", ccb->ccb_h.target_id); 800 return ENXIO; 801 } 802 803 dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; 804 /* Check controller state */ 805 if (IN_PQI_RESET(softs)) { 806 ccb->ccb_h.status = CAM_SCSI_BUS_RESET 807 | CAM_BUSY | CAM_REQ_INPROG; 808 DBG_WARN("Device = %d BUSY/IN_RESET\n", ccb->ccb_h.target_id); 809 return ENXIO; 810 } 811 /* Check device state */ 812 if (pqisrc_ctrl_offline(softs) || DEV_GONE(dvp)) { 813 ccb->ccb_h.status = CAM_DEV_NOT_THERE | CAM_REQ_CMP; 814 DBG_WARN("Device = %d GONE/OFFLINE\n", ccb->ccb_h.target_id); 815 return ENXIO; 816 } 817 /* Check device reset */ 818 if (DEVICE_RESET(dvp)) { 819 ccb->ccb_h.status = CAM_SCSI_BUSY | CAM_REQ_INPROG | CAM_BUSY; 820 DBG_WARN("Device %d reset returned busy\n", ccb->ccb_h.target_id); 821 return EBUSY; 822 } 823 824 if (dvp->expose_device == false) { 825 ccb->ccb_h.status = CAM_DEV_NOT_THERE; 826 DBG_INFO("Device = %d not exposed\n", ccb->ccb_h.target_id); 827 return ENXIO; 828 } 829 830 tag = pqisrc_get_tag(&softs->taglist); 831 if (tag == INVALID_ELEM) { 832 DBG_ERR("Get Tag failed\n"); 833 xpt_freeze_simq(softs->os_specific.sim, 1); 834 softs->os_specific.pqi_flags |= PQI_FLAG_BUSY; 835 ccb->ccb_h.status |= (CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ); 836 return EIO; 837 } 838 839 DBG_IO("tag = %d &softs->taglist : %p\n", tag, &softs->taglist); 840 841 rcb = &softs->rcb[tag]; 842 os_reset_rcb(rcb); 843 rcb->tag = tag; 844 rcb->softs = softs; 845 rcb->cmdlen = ccb->csio.cdb_len; 846 ccb->ccb_h.sim_priv.entries[0].ptr = rcb; 847 848 switch (ccb->ccb_h.flags & CAM_DIR_MASK) { 849 case CAM_DIR_IN: 850 rcb->data_dir = SOP_DATA_DIR_FROM_DEVICE; 851 break; 852 case CAM_DIR_OUT: 853 rcb->data_dir = SOP_DATA_DIR_TO_DEVICE; 854 break; 855 case CAM_DIR_NONE: 856 no_transfer = 1; 857 break; 858 default: 859 DBG_ERR("Unknown Dir\n"); 860 break; 861 } 862 rcb->cm_ccb = ccb; 863 rcb->dvp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; 864 865 if (!no_transfer) { 866 rcb->cm_data = (void *)ccb->csio.data_ptr; 867 rcb->bcount = ccb->csio.dxfer_len; 868 } else { 869 rcb->cm_data = NULL; 870 rcb->bcount = 0; 871 } 872 /* 873 * Submit the request to the adapter. 874 * 875 * Note that this may fail if we're unable to map the request (and 876 * if we ever learn a transport layer other than simple, may fail 877 * if the adapter rejects the command). 878 */ 879 if ((error = pqi_map_request(rcb)) != BSD_SUCCESS) { 880 xpt_freeze_simq(softs->os_specific.sim, 1); 881 if (error == EINPROGRESS) { 882 /* Release simq in the completion */ 883 softs->os_specific.pqi_flags |= PQI_FLAG_BUSY; 884 error = BSD_SUCCESS; 885 } else { 886 rcb->req_pending = false; 887 ccb->ccb_h.status |= CAM_REQUEUE_REQ | CAM_RELEASE_SIMQ; 888 DBG_WARN("Requeue req error = %d target = %d\n", error, 889 ccb->ccb_h.target_id); 890 pqi_unmap_request(rcb); 891 error = EIO; 892 } 893 } 894 895 DBG_FUNC("OUT error = %d\n", error); 896 897 return error; 898 } 899 900 static inline int 901 pqi_tmf_status_to_bsd_tmf_status(int pqi_status, rcb_t *rcb) 902 { 903 if (PQI_STATUS_SUCCESS == pqi_status && 904 REQUEST_SUCCESS == rcb->status) 905 return BSD_SUCCESS; 906 else 907 return EIO; 908 } 909 910 /* 911 * Abort a task, task management functionality 912 */ 913 static int 914 pqisrc_scsi_abort_task(pqisrc_softstate_t *softs, union ccb *ccb) 915 { 916 struct ccb_hdr *ccb_h = &ccb->ccb_h; 917 rcb_t *rcb = NULL; 918 rcb_t *prcb = ccb->ccb_h.sim_priv.entries[0].ptr; 919 uint32_t tag; 920 int rval; 921 922 DBG_FUNC("IN\n"); 923 924 tag = pqisrc_get_tag(&softs->taglist); 925 rcb = &softs->rcb[tag]; 926 rcb->tag = tag; 927 928 if (!rcb->dvp) { 929 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code); 930 rval = ENXIO; 931 goto error_tmf; 932 } 933 934 rcb->tm_req = true; 935 936 rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, prcb, 937 SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK); 938 939 if ((rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb)) == BSD_SUCCESS) 940 ccb->ccb_h.status = CAM_REQ_ABORTED; 941 942 error_tmf: 943 os_reset_rcb(rcb); 944 pqisrc_put_tag(&softs->taglist, tag); 945 946 DBG_FUNC("OUT rval = %d\n", rval); 947 948 return rval; 949 } 950 951 /* 952 * Abort a taskset, task management functionality 953 */ 954 static int 955 pqisrc_scsi_abort_task_set(pqisrc_softstate_t *softs, union ccb *ccb) 956 { 957 struct ccb_hdr *ccb_h = &ccb->ccb_h; 958 rcb_t *rcb = NULL; 959 uint32_t tag; 960 int rval; 961 962 DBG_FUNC("IN\n"); 963 964 tag = pqisrc_get_tag(&softs->taglist); 965 rcb = &softs->rcb[tag]; 966 rcb->tag = tag; 967 968 if (!rcb->dvp) { 969 DBG_ERR("dvp is null, tmf type : 0x%x\n", ccb_h->func_code); 970 rval = ENXIO; 971 goto error_tmf; 972 } 973 974 rcb->tm_req = true; 975 976 rval = pqisrc_send_tmf(softs, rcb->dvp, rcb, NULL, 977 SOP_TASK_MANAGEMENT_FUNCTION_ABORT_TASK_SET); 978 979 rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb); 980 981 error_tmf: 982 os_reset_rcb(rcb); 983 pqisrc_put_tag(&softs->taglist, tag); 984 985 DBG_FUNC("OUT rval = %d\n", rval); 986 987 return rval; 988 } 989 990 /* 991 * Target reset task management functionality 992 */ 993 static int 994 pqisrc_target_reset( pqisrc_softstate_t *softs, union ccb *ccb) 995 { 996 struct ccb_hdr *ccb_h = &ccb->ccb_h; 997 pqi_scsi_dev_t *devp = softs->device_list[ccb->ccb_h.target_id][ccb->ccb_h.target_lun]; 998 rcb_t *rcb = NULL; 999 uint32_t tag; 1000 int rval; 1001 1002 DBG_FUNC("IN\n"); 1003 1004 if (devp == NULL) { 1005 DBG_ERR("bad target %d, tmf type : 0x%x\n", ccb_h->target_id, ccb_h->func_code); 1006 return ENXIO; 1007 } 1008 1009 tag = pqisrc_get_tag(&softs->taglist); 1010 rcb = &softs->rcb[tag]; 1011 rcb->tag = tag; 1012 1013 devp->reset_in_progress = true; 1014 1015 rcb->tm_req = true; 1016 1017 rval = pqisrc_send_tmf(softs, devp, rcb, NULL, 1018 SOP_TASK_MANAGEMENT_LUN_RESET); 1019 1020 rval = pqi_tmf_status_to_bsd_tmf_status(rval, rcb); 1021 devp->reset_in_progress = false; 1022 1023 os_reset_rcb(rcb); 1024 pqisrc_put_tag(&softs->taglist, tag); 1025 1026 DBG_FUNC("OUT rval = %d\n", rval); 1027 1028 return rval; 1029 1030 } 1031 1032 /* 1033 * cam entry point of the smartpqi module. 1034 */ 1035 static void 1036 smartpqi_cam_action(struct cam_sim *sim, union ccb *ccb) 1037 { 1038 struct pqisrc_softstate *softs = cam_sim_softc(sim); 1039 struct ccb_hdr *ccb_h = &ccb->ccb_h; 1040 1041 DBG_FUNC("IN\n"); 1042 1043 switch (ccb_h->func_code) { 1044 case XPT_SCSI_IO: 1045 { 1046 if(!pqisrc_io_start(sim, ccb)) { 1047 return; 1048 } 1049 break; 1050 } 1051 case XPT_CALC_GEOMETRY: 1052 { 1053 struct ccb_calc_geometry *ccg; 1054 ccg = &ccb->ccg; 1055 if (ccg->block_size == 0) { 1056 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 1057 ccb->ccb_h.status |= CAM_REQ_INVALID; 1058 break; 1059 } 1060 cam_calc_geometry(ccg, /* extended */ 1); 1061 ccb->ccb_h.status = CAM_REQ_CMP; 1062 break; 1063 } 1064 case XPT_PATH_INQ: 1065 { 1066 update_sim_properties(sim, &ccb->cpi); 1067 ccb->ccb_h.status = CAM_REQ_CMP; 1068 break; 1069 } 1070 case XPT_GET_TRAN_SETTINGS: 1071 get_transport_settings(softs, &ccb->cts); 1072 ccb->ccb_h.status = CAM_REQ_CMP; 1073 break; 1074 case XPT_ABORT: 1075 if(pqisrc_scsi_abort_task(softs, ccb)) { 1076 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1077 xpt_done(ccb); 1078 DBG_ERR("Abort task failed on %d\n", 1079 ccb->ccb_h.target_id); 1080 return; 1081 } 1082 break; 1083 case XPT_TERM_IO: 1084 if (pqisrc_scsi_abort_task_set(softs, ccb)) { 1085 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1086 DBG_ERR("Abort task set failed on %d\n", 1087 ccb->ccb_h.target_id); 1088 xpt_done(ccb); 1089 return; 1090 } 1091 break; 1092 case XPT_RESET_DEV: 1093 if(pqisrc_target_reset(softs, ccb)) { 1094 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 1095 DBG_ERR("Target reset failed on %d\n", 1096 ccb->ccb_h.target_id); 1097 xpt_done(ccb); 1098 return; 1099 } else { 1100 ccb->ccb_h.status = CAM_REQ_CMP; 1101 } 1102 break; 1103 case XPT_RESET_BUS: 1104 ccb->ccb_h.status = CAM_REQ_CMP; 1105 break; 1106 case XPT_SET_TRAN_SETTINGS: 1107 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1108 return; 1109 default: 1110 DBG_WARN("UNSUPPORTED FUNC CODE\n"); 1111 ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 1112 break; 1113 } 1114 xpt_done(ccb); 1115 1116 DBG_FUNC("OUT\n"); 1117 } 1118 1119 /* 1120 * Function to poll the response, when interrupts are unavailable 1121 * This also serves supporting crash dump. 1122 */ 1123 static void 1124 smartpqi_poll(struct cam_sim *sim) 1125 { 1126 struct pqisrc_softstate *softs = cam_sim_softc(sim); 1127 int i; 1128 1129 for (i = 1; i < softs->intr_count; i++ ) 1130 pqisrc_process_response_queue(softs, i); 1131 } 1132 1133 /* 1134 * Function to adjust the queue depth of a device 1135 */ 1136 void 1137 smartpqi_adjust_queue_depth(struct cam_path *path, uint32_t queue_depth) 1138 { 1139 struct ccb_relsim crs; 1140 1141 DBG_INFO("IN\n"); 1142 1143 memset(&crs, 0, sizeof(crs)); 1144 xpt_setup_ccb(&crs.ccb_h, path, 5); 1145 crs.ccb_h.func_code = XPT_REL_SIMQ; 1146 crs.ccb_h.flags = CAM_DEV_QFREEZE; 1147 crs.release_flags = RELSIM_ADJUST_OPENINGS; 1148 crs.openings = queue_depth; 1149 xpt_action((union ccb *)&crs); 1150 if(crs.ccb_h.status != CAM_REQ_CMP) { 1151 printf("XPT_REL_SIMQ failed stat=%d\n", crs.ccb_h.status); 1152 } 1153 1154 DBG_INFO("OUT\n"); 1155 } 1156 1157 /* 1158 * Function to register async callback for setting queue depth 1159 */ 1160 static void 1161 smartpqi_async(void *callback_arg, u_int32_t code, 1162 struct cam_path *path, void *arg) 1163 { 1164 struct pqisrc_softstate *softs; 1165 softs = (struct pqisrc_softstate*)callback_arg; 1166 1167 DBG_FUNC("IN\n"); 1168 1169 switch (code) { 1170 case AC_FOUND_DEVICE: 1171 { 1172 struct ccb_getdev *cgd; 1173 cgd = (struct ccb_getdev *)arg; 1174 if (cgd == NULL) { 1175 break; 1176 } 1177 uint32_t t_id = cgd->ccb_h.target_id; 1178 1179 if (t_id <= (PQI_CTLR_INDEX - 1)) { 1180 if (softs != NULL) { 1181 pqi_scsi_dev_t *dvp = softs->device_list[t_id][cgd->ccb_h.target_lun]; 1182 if (dvp == NULL) { 1183 DBG_ERR("Target is null, target id=%d\n", t_id); 1184 break; 1185 } 1186 smartpqi_adjust_queue_depth(path, 1187 dvp->queue_depth); 1188 } 1189 } 1190 break; 1191 } 1192 default: 1193 break; 1194 } 1195 1196 DBG_FUNC("OUT\n"); 1197 } 1198 1199 /* 1200 * Function to register sim with CAM layer for smartpqi driver 1201 */ 1202 int 1203 register_sim(struct pqisrc_softstate *softs, int card_index) 1204 { 1205 int max_transactions; 1206 union ccb *ccb = NULL; 1207 int error; 1208 struct ccb_setasync csa; 1209 struct cam_sim *sim; 1210 1211 DBG_FUNC("IN\n"); 1212 1213 max_transactions = softs->max_io_for_scsi_ml; 1214 softs->os_specific.devq = cam_simq_alloc(max_transactions); 1215 if (softs->os_specific.devq == NULL) { 1216 DBG_ERR("cam_simq_alloc failed txns = %d\n", 1217 max_transactions); 1218 return ENOMEM; 1219 } 1220 1221 sim = cam_sim_alloc(smartpqi_cam_action, \ 1222 smartpqi_poll, "smartpqi", softs, \ 1223 card_index, &softs->os_specific.cam_lock, \ 1224 1, max_transactions, softs->os_specific.devq); 1225 if (sim == NULL) { 1226 DBG_ERR("cam_sim_alloc failed txns = %d\n", 1227 max_transactions); 1228 cam_simq_free(softs->os_specific.devq); 1229 return ENOMEM; 1230 } 1231 1232 softs->os_specific.sim = sim; 1233 mtx_lock(&softs->os_specific.cam_lock); 1234 error = xpt_bus_register(sim, softs->os_specific.pqi_dev, 0); 1235 if (error != CAM_SUCCESS) { 1236 DBG_ERR("xpt_bus_register failed errno %d\n", error); 1237 cam_sim_free(softs->os_specific.sim, FALSE); 1238 cam_simq_free(softs->os_specific.devq); 1239 mtx_unlock(&softs->os_specific.cam_lock); 1240 return ENXIO; 1241 } 1242 1243 softs->os_specific.sim_registered = TRUE; 1244 ccb = xpt_alloc_ccb_nowait(); 1245 if (ccb == NULL) { 1246 DBG_ERR("xpt_create_path failed\n"); 1247 return ENXIO; 1248 } 1249 1250 if (xpt_create_path(&ccb->ccb_h.path, NULL, 1251 cam_sim_path(softs->os_specific.sim), 1252 CAM_TARGET_WILDCARD, 1253 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 1254 DBG_ERR("xpt_create_path failed\n"); 1255 xpt_free_ccb(ccb); 1256 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim)); 1257 cam_sim_free(softs->os_specific.sim, TRUE); 1258 mtx_unlock(&softs->os_specific.cam_lock); 1259 return ENXIO; 1260 } 1261 /* 1262 * Callback to set the queue depth per target which is 1263 * derived from the FW. 1264 */ 1265 softs->os_specific.path = ccb->ccb_h.path; 1266 memset(&csa, 0, sizeof(csa)); 1267 xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5); 1268 csa.ccb_h.func_code = XPT_SASYNC_CB; 1269 csa.event_enable = AC_FOUND_DEVICE; 1270 csa.callback = smartpqi_async; 1271 csa.callback_arg = softs; 1272 xpt_action((union ccb *)&csa); 1273 if (csa.ccb_h.status != CAM_REQ_CMP) { 1274 DBG_ERR("Unable to register smartpqi_aysnc handler: %d!\n", 1275 csa.ccb_h.status); 1276 } 1277 1278 mtx_unlock(&softs->os_specific.cam_lock); 1279 DBG_INFO("OUT\n"); 1280 1281 return BSD_SUCCESS; 1282 } 1283 1284 /* 1285 * Function to deregister smartpqi sim from cam layer 1286 */ 1287 void 1288 deregister_sim(struct pqisrc_softstate *softs) 1289 { 1290 struct ccb_setasync csa; 1291 1292 DBG_FUNC("IN\n"); 1293 1294 if (softs->os_specific.mtx_init) { 1295 mtx_lock(&softs->os_specific.cam_lock); 1296 } 1297 1298 1299 memset(&csa, 0, sizeof(csa)); 1300 xpt_setup_ccb(&csa.ccb_h, softs->os_specific.path, 5); 1301 csa.ccb_h.func_code = XPT_SASYNC_CB; 1302 csa.event_enable = 0; 1303 csa.callback = smartpqi_async; 1304 csa.callback_arg = softs; 1305 xpt_action((union ccb *)&csa); 1306 xpt_free_path(softs->os_specific.path); 1307 1308 if (softs->os_specific.sim) { 1309 xpt_release_simq(softs->os_specific.sim, 0); 1310 xpt_bus_deregister(cam_sim_path(softs->os_specific.sim)); 1311 softs->os_specific.sim_registered = FALSE; 1312 cam_sim_free(softs->os_specific.sim, FALSE); 1313 softs->os_specific.sim = NULL; 1314 } 1315 1316 if (softs->os_specific.mtx_init) { 1317 mtx_unlock(&softs->os_specific.cam_lock); 1318 } 1319 if (softs->os_specific.devq != NULL) { 1320 cam_simq_free(softs->os_specific.devq); 1321 } 1322 if (softs->os_specific.mtx_init) { 1323 mtx_destroy(&softs->os_specific.cam_lock); 1324 softs->os_specific.mtx_init = FALSE; 1325 } 1326 1327 mtx_destroy(&softs->os_specific.map_lock); 1328 1329 DBG_FUNC("OUT\n"); 1330 } 1331 1332 void 1333 os_rescan_target(pqisrc_softstate_t *softs, pqi_scsi_dev_t *device) 1334 { 1335 struct cam_path *tmppath; 1336 1337 DBG_FUNC("IN\n"); 1338 1339 if(softs->os_specific.sim_registered) { 1340 if (xpt_create_path(&tmppath, NULL, 1341 cam_sim_path(softs->os_specific.sim), 1342 device->target, device->lun) != CAM_REQ_CMP) { 1343 DBG_ERR("unable to create path for async event!!! Bus: %d Target: %d Lun: %d\n", 1344 device->bus, device->target, device->lun); 1345 return; 1346 } 1347 xpt_async(AC_INQ_CHANGED, tmppath, NULL); 1348 xpt_free_path(tmppath); 1349 } 1350 1351 device->scsi_rescan = false; 1352 1353 DBG_FUNC("OUT\n"); 1354 } 1355