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