1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2023 Tintri by DDN, Inc. All rights reserved. 14 * Copyright 2021 RackTop Systems, Inc. 15 */ 16 17 /* 18 * This file contains all routines necessary to interface with SCSA trans. 19 */ 20 #include <smartpqi.h> 21 22 /* 23 * []------------------------------------------------------------------[] 24 * | Forward declarations for SCSA trans routines. | 25 * []------------------------------------------------------------------[] 26 */ 27 static int pqi_scsi_tgt_init(dev_info_t *hba_dip, dev_info_t *tgt_dip, 28 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 29 static void pqi_scsi_tgt_free(dev_info_t *hba_dip, dev_info_t *tgt_dip, 30 scsi_hba_tran_t *hba_tran, struct scsi_device *sd); 31 static int pqi_start(struct scsi_address *ap, struct scsi_pkt *pkt); 32 static int pqi_scsi_reset(struct scsi_address *ap, int level); 33 static int pqi_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt); 34 static int pqi_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly); 35 static int pqi_scsi_setcap(struct scsi_address *ap, char *cap, int value, 36 int tgtonly); 37 static struct scsi_pkt *pqi_init_pkt(struct scsi_address *ap, 38 struct scsi_pkt *pkt, struct buf *bp, int cmdlen, int statuslen, int tgtlen, 39 int flags, int (*callback)(), caddr_t arg); 40 static void pqi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt); 41 static void pqi_dmafree(struct scsi_address *ap, struct scsi_pkt *pkt); 42 static void pqi_sync_pkt(struct scsi_address *ap, struct scsi_pkt *pkt); 43 static int pqi_reset_notify(struct scsi_address *ap, int flag, 44 void (*callback)(caddr_t), caddr_t arg); 45 static int pqi_quiesce(dev_info_t *dip); 46 static int pqi_unquiesce(dev_info_t *dip); 47 static int pqi_bus_config(dev_info_t *pdip, uint_t flag, 48 ddi_bus_config_op_t op, void *arg, dev_info_t **childp); 49 50 /* ---- Support method declaration ---- */ 51 static int config_one(dev_info_t *pdip, pqi_state_t *s, pqi_device_t *, 52 dev_info_t **childp); 53 static void abort_all(struct scsi_address *ap, pqi_state_t *s); 54 static int cmd_ext_alloc(pqi_cmd_t *cmd, int kf); 55 static void cmd_ext_free(pqi_cmd_t *cmd); 56 static boolean_t is_physical_dev(pqi_device_t *d); 57 static void cmd_timeout_scan(void *); 58 59 boolean_t 60 smartpqi_register_hba(pqi_state_t *s) 61 { 62 scsi_hba_tran_t *tran; 63 int flags; 64 char iport_str[16]; 65 int instance = ddi_get_instance(s->s_dip); 66 67 tran = scsi_hba_tran_alloc(s->s_dip, SCSI_HBA_CANSLEEP); 68 if (tran == NULL) 69 return (B_FALSE); 70 s->s_tran = tran; 71 72 tran->tran_hba_private = s; 73 tran->tran_tgt_private = NULL; 74 75 tran->tran_tgt_init = pqi_scsi_tgt_init; 76 tran->tran_tgt_free = pqi_scsi_tgt_free; 77 tran->tran_tgt_probe = scsi_hba_probe; 78 79 tran->tran_start = pqi_start; 80 tran->tran_reset = pqi_scsi_reset; 81 tran->tran_abort = pqi_scsi_abort; 82 tran->tran_getcap = pqi_scsi_getcap; 83 tran->tran_setcap = pqi_scsi_setcap; 84 tran->tran_bus_config = pqi_bus_config; 85 86 tran->tran_init_pkt = pqi_init_pkt; 87 tran->tran_destroy_pkt = pqi_destroy_pkt; 88 tran->tran_dmafree = pqi_dmafree; 89 tran->tran_sync_pkt = pqi_sync_pkt; 90 91 tran->tran_reset_notify = pqi_reset_notify; 92 tran->tran_quiesce = pqi_quiesce; 93 tran->tran_unquiesce = pqi_unquiesce; 94 tran->tran_bus_reset = NULL; 95 96 tran->tran_add_eventcall = NULL; 97 tran->tran_get_eventcookie = NULL; 98 tran->tran_post_event = NULL; 99 tran->tran_remove_eventcall = NULL; 100 tran->tran_bus_config = pqi_bus_config; 101 tran->tran_interconnect_type = INTERCONNECT_SAS; 102 103 /* 104 * scsi_vhci needs to have "initiator-port" set, but doesn't 105 * seem to care what it's set to. iSCSI uses the InitiatorName 106 * whereas mpt_sas uses the WWN port id, but this HBA doesn't 107 * have such a value. So, for now the instance number will be used. 108 */ 109 (void) snprintf(iport_str, sizeof (iport_str), "0x%x", instance); 110 if (ddi_prop_update_string(DDI_DEV_T_NONE, s->s_dip, 111 SCSI_ADDR_PROP_INITIATOR_PORT, iport_str) != DDI_PROP_SUCCESS) { 112 cmn_err(CE_WARN, "%s: Failed to create prop (%s) on %d\n", 113 __func__, SCSI_ADDR_PROP_INITIATOR_PORT, instance); 114 } 115 116 flags = SCSI_HBA_ADDR_COMPLEX | SCSI_HBA_TRAN_SCB; 117 if (scsi_hba_attach_setup(s->s_dip, &s->s_msg_dma_attr, tran, 118 flags) != DDI_SUCCESS) { 119 dev_err(s->s_dip, CE_NOTE, "scsi_hba_attach_setup failed"); 120 scsi_hba_tran_free(s->s_tran); 121 s->s_tran = NULL; 122 return (B_FALSE); 123 } 124 125 if (!s->s_disable_mpxio) { 126 if (mdi_phci_register(MDI_HCI_CLASS_SCSI, s->s_dip, 0) != 127 MDI_SUCCESS) { 128 cmn_err(CE_WARN, "%s: Failed to register with mpxio", 129 __func__); 130 s->s_disable_mpxio = B_TRUE; 131 } 132 } 133 134 s->s_cmd_timeout = timeout(cmd_timeout_scan, s, 135 CMD_TIMEOUT_SCAN_SECS * drv_usectohz(MICROSEC)); 136 137 return (B_TRUE); 138 } 139 140 void 141 smartpqi_unregister_hba(pqi_state_t *s) 142 { 143 if (!s->s_disable_mpxio) 144 (void) mdi_phci_unregister(s->s_dip, 0); 145 146 if (s->s_cmd_timeout != NULL) { 147 (void) untimeout(s->s_cmd_timeout); 148 s->s_cmd_timeout = NULL; 149 } 150 151 if (s->s_tran == NULL) 152 return; 153 scsi_hba_tran_free(s->s_tran); 154 s->s_tran = NULL; 155 } 156 157 static int 158 pqi_scsi_tgt_init(dev_info_t *hba_dip __unused, dev_info_t *tgt_dip, 159 scsi_hba_tran_t *hba_tran, struct scsi_device *sd) 160 { 161 pqi_device_t *d; 162 pqi_state_t *s = hba_tran->tran_hba_private; 163 mdi_pathinfo_t *pip; 164 int type; 165 char *ua; 166 167 if ((ua = scsi_device_unit_address(sd)) == NULL) { 168 return (DDI_FAILURE); 169 } 170 171 if ((d = pqi_find_target_ua(s, ua)) == NULL) { 172 return (DDI_FAILURE); 173 } 174 175 scsi_device_hba_private_set(sd, d); 176 177 type = mdi_get_component_type(tgt_dip); 178 if (type == MDI_COMPONENT_CLIENT) { 179 char wwid_str[64]; 180 181 if ((pip = (mdi_pathinfo_t *)sd->sd_private) == NULL) 182 return (DDI_NOT_WELL_FORMED); 183 184 (void) snprintf(wwid_str, sizeof (wwid_str), "%" PRIx64, 185 d->pd_wwid); 186 (void) mdi_prop_update_string(pip, SCSI_ADDR_PROP_TARGET_PORT, 187 wwid_str); 188 } 189 190 return (DDI_SUCCESS); 191 } 192 193 static void 194 pqi_scsi_tgt_free(dev_info_t *hba_dip __unused, dev_info_t *tgt_dip __unused, 195 scsi_hba_tran_t *hba_tran __unused, struct scsi_device *sd __unused) 196 { 197 } 198 199 /* 200 * Notes: 201 * - transport the command to the addressed SCSI target/lun device 202 * - normal operation is to schedule the command to be transported, 203 * and return TRAN_ACCEPT if this is successful. 204 * - if NO_INTR, tran_start must poll device for command completion 205 */ 206 static int 207 pqi_start(struct scsi_address *ap, struct scsi_pkt *pkt) 208 { 209 boolean_t poll = ((pkt->pkt_flags & FLAG_NOINTR) != 0); 210 int rc; 211 pqi_cmd_t *cmd = PKT2CMD(pkt); 212 pqi_state_t *s = ap->a_hba_tran->tran_hba_private; 213 214 ASSERT3P(cmd->pc_pkt, ==, pkt); 215 ASSERT3P(cmd->pc_softc, ==, s); 216 217 if (pqi_is_offline(s) || !cmd->pc_device->pd_online) 218 return (TRAN_FATAL_ERROR); 219 220 /* 221 * Reinitialize some fields because the packet may have been 222 * resubmitted. 223 */ 224 pkt->pkt_reason = CMD_CMPLT; 225 pkt->pkt_state = 0; 226 pkt->pkt_statistics = 0; 227 228 /* ---- Zero status byte ---- */ 229 *(pkt->pkt_scbp) = 0; 230 231 if ((cmd->pc_flags & PQI_FLAG_DMA_VALID) != 0) { 232 ASSERT(cmd->pc_dma_count); 233 pkt->pkt_resid = cmd->pc_dma_count; 234 235 /* ---- Sync consistent packets first (only write data) ---- */ 236 if (((cmd->pc_flags & PQI_FLAG_IO_IOPB) != 0) || 237 ((cmd->pc_flags & PQI_FLAG_IO_READ) == 0)) { 238 (void) ddi_dma_sync(cmd->pc_dmahdl, 0, 0, 239 DDI_DMA_SYNC_FORDEV); 240 } 241 } 242 243 mutex_enter(&s->s_mutex); 244 if (HBA_IS_QUIESCED(s) && !poll) { 245 mutex_exit(&s->s_mutex); 246 return (TRAN_BUSY); 247 } 248 mutex_exit(&s->s_mutex); 249 250 rc = pqi_transport_command(s, cmd); 251 252 if (poll) { 253 boolean_t qnotify; 254 255 if (rc == TRAN_ACCEPT) { 256 uint32_t old_state; 257 int timeo; 258 259 timeo = pkt->pkt_time ? pkt->pkt_time : 260 SCSI_POLL_TIMEOUT; 261 timeo *= MILLISEC / 2; 262 old_state = pqi_disable_intr(s); 263 do { 264 drv_usecwait(MILLISEC / 2); 265 pqi_process_io_intr(s, &s->s_queue_groups[0]); 266 if (--timeo == 0) { 267 pkt->pkt_state |= STAT_TIMEOUT; 268 pkt->pkt_reason = CMD_TIMEOUT; 269 break; 270 } 271 } while (pkt->pkt_state == 0); 272 pqi_enable_intr(s, old_state); 273 } 274 275 scsi_hba_pkt_comp(pkt); 276 277 mutex_enter(&s->s_mutex); 278 qnotify = HBA_QUIESCED_PENDING(s); 279 mutex_exit(&s->s_mutex); 280 281 if (qnotify) 282 pqi_quiesced_notify(s); 283 } 284 285 return (rc); 286 } 287 288 static int 289 pqi_scsi_reset(struct scsi_address *ap, int level) 290 { 291 pqi_device_t *d; 292 pqi_state_t *s; 293 int rval = FALSE; 294 295 s = ap->a_hba_tran->tran_hba_private; 296 switch (level) { 297 case RESET_TARGET: 298 case RESET_LUN: 299 if ((d = scsi_device_hba_private_get(ap->a.a_sd)) == NULL) 300 break; 301 302 pqi_lun_reset(s, d); 303 rval = TRUE; 304 break; 305 306 case RESET_BUS: 307 case RESET_ALL: 308 mutex_enter(&s->s_mutex); 309 for (d = list_head(&s->s_devnodes); d != NULL; 310 d = list_next(&s->s_devnodes, d)) { 311 pqi_lun_reset(s, d); 312 } 313 mutex_exit(&s->s_mutex); 314 rval = TRUE; 315 break; 316 } 317 return (rval); 318 } 319 320 /* 321 * abort handling: 322 * 323 * Notes: 324 * - if pkt is not NULL, abort just that command 325 * - if pkt is NULL, abort all outstanding commands for target 326 */ 327 static int 328 pqi_scsi_abort(struct scsi_address *ap, struct scsi_pkt *pkt) 329 { 330 boolean_t qnotify = B_FALSE; 331 pqi_state_t *s = ADDR2PQI(ap); 332 333 if (pkt != NULL) { 334 /* ---- Abort single command ---- */ 335 pqi_cmd_t *cmd = PKT2CMD(pkt); 336 337 mutex_enter(&cmd->pc_device->pd_mutex); 338 (void) pqi_fail_cmd(cmd, CMD_ABORTED, STAT_ABORTED); 339 mutex_exit(&cmd->pc_device->pd_mutex); 340 } else { 341 abort_all(ap, s); 342 } 343 qnotify = HBA_QUIESCED_PENDING(s); 344 345 if (qnotify) 346 pqi_quiesced_notify(s); 347 return (1); 348 } 349 350 /* 351 * capability handling: 352 * (*tran_getcap). Get the capability named, and return its value. 353 */ 354 static int 355 pqi_scsi_getcap(struct scsi_address *ap, char *cap, int tgtonly __unused) 356 { 357 pqi_state_t *s = ap->a_hba_tran->tran_hba_private; 358 359 if (cap == NULL) 360 return (-1); 361 switch (scsi_hba_lookup_capstr(cap)) { 362 case SCSI_CAP_LUN_RESET: 363 return ((s->s_flags & PQI_HBA_LUN_RESET_CAP) != 0); 364 case SCSI_CAP_ARQ: 365 return ((s->s_flags & PQI_HBA_AUTO_REQUEST_SENSE) != 0); 366 case SCSI_CAP_UNTAGGED_QING: 367 return (1); 368 default: 369 return (-1); 370 } 371 } 372 373 /* 374 * (*tran_setcap). Set the capability named to the value given. 375 */ 376 static int 377 pqi_scsi_setcap(struct scsi_address *ap, char *cap, int value, 378 int tgtonly __unused) 379 { 380 pqi_state_t *s = ADDR2PQI(ap); 381 int rval = FALSE; 382 383 if (cap == NULL) 384 return (-1); 385 386 switch (scsi_hba_lookup_capstr(cap)) { 387 case SCSI_CAP_ARQ: 388 if (value) 389 s->s_flags |= PQI_HBA_AUTO_REQUEST_SENSE; 390 else 391 s->s_flags &= ~PQI_HBA_AUTO_REQUEST_SENSE; 392 rval = 1; 393 break; 394 395 case SCSI_CAP_LUN_RESET: 396 if (value) 397 s->s_flags |= PQI_HBA_LUN_RESET_CAP; 398 else 399 s->s_flags &= ~PQI_HBA_LUN_RESET_CAP; 400 break; 401 402 default: 403 break; 404 } 405 406 return (rval); 407 } 408 409 int 410 pqi_cache_constructor(void *buf, void *un, int flags) 411 { 412 pqi_cmd_t *c = (pqi_cmd_t *)buf; 413 pqi_state_t *s = un; 414 int (*callback)(caddr_t); 415 416 bzero(c, sizeof (*c)); 417 c->pc_softc = s; 418 callback = (flags == KM_SLEEP) ? DDI_DMA_SLEEP : DDI_DMA_DONTWAIT; 419 420 /* ---- Allocate a DMA handle for data transfers ---- */ 421 if (ddi_dma_alloc_handle(s->s_dip, &s->s_msg_dma_attr, callback, 422 NULL, &c->pc_dmahdl) != DDI_SUCCESS) { 423 dev_err(s->s_dip, CE_WARN, "Failed to alloc dma handle"); 424 return (-1); 425 } 426 427 return (0); 428 } 429 430 void 431 pqi_cache_destructor(void *buf, void *un __unused) 432 { 433 pqi_cmd_t *cmd = buf; 434 if (cmd->pc_dmahdl != NULL) { 435 (void) ddi_dma_unbind_handle(cmd->pc_dmahdl); 436 ddi_dma_free_handle(&cmd->pc_dmahdl); 437 cmd->pc_dmahdl = NULL; 438 } 439 } 440 441 /* 442 * tran_init_pkt(9E) - allocate scsi_pkt(9S) for command 443 * 444 * One of three possibilities: 445 * - allocate scsi_pkt 446 * - allocate scsi_pkt and DMA resources 447 * - allocate DMA resources to an already-allocated pkt 448 */ 449 static struct scsi_pkt * 450 pqi_init_pkt(struct scsi_address *ap, struct scsi_pkt *pkt, 451 struct buf *bp, int cmdlen, int statuslen, int tgtlen, int flags, 452 int (*callback)(), caddr_t arg) 453 { 454 pqi_cmd_t *cmd; 455 pqi_state_t *s; 456 int kf = (callback == SLEEP_FUNC) ? KM_SLEEP : KM_NOSLEEP; 457 boolean_t is_new = B_FALSE; 458 int rc; 459 int i; 460 pqi_device_t *devp; 461 462 s = ap->a_hba_tran->tran_hba_private; 463 464 if (pkt == NULL) { 465 ddi_dma_handle_t saved_dmahdl; 466 pqi_cmd_action_t saved_action; 467 468 if ((devp = scsi_device_hba_private_get(ap->a.a_sd)) == NULL) 469 return (NULL); 470 if ((cmd = kmem_cache_alloc(s->s_cmd_cache, kf)) == NULL) 471 return (NULL); 472 473 is_new = B_TRUE; 474 saved_dmahdl = cmd->pc_dmahdl; 475 saved_action = cmd->pc_last_action; 476 477 (void) memset(cmd, 0, sizeof (*cmd)); 478 mutex_init(&cmd->pc_mutex, NULL, MUTEX_DRIVER, NULL); 479 480 cmd->pc_dmahdl = saved_dmahdl; 481 cmd->pc_last_action = saved_action; 482 483 cmd->pc_device = devp; 484 cmd->pc_pkt = &cmd->pc_cached_pkt; 485 cmd->pc_softc = s; 486 cmd->pc_tgtlen = tgtlen; 487 cmd->pc_statuslen = statuslen; 488 cmd->pc_cmdlen = cmdlen; 489 cmd->pc_dma_count = 0; 490 491 pkt = cmd->pc_pkt; 492 pkt->pkt_ha_private = cmd; 493 pkt->pkt_address = *ap; 494 pkt->pkt_scbp = (uint8_t *)&cmd->pc_cmd_scb; 495 pkt->pkt_cdbp = cmd->pc_cdb; 496 pkt->pkt_private = (opaque_t)cmd->pc_tgt_priv; 497 if (pkt->pkt_time == 0) 498 pkt->pkt_time = SCSI_POLL_TIMEOUT; 499 500 if (cmdlen > sizeof (cmd->pc_cdb) || 501 statuslen > sizeof (cmd->pc_cmd_scb) || 502 tgtlen > sizeof (cmd->pc_tgt_priv)) { 503 if (cmd_ext_alloc(cmd, kf) != DDI_SUCCESS) { 504 dev_err(s->s_dip, CE_WARN, 505 "extent allocation failed"); 506 goto out; 507 } 508 } 509 } else { 510 cmd = PKT2CMD(pkt); 511 cmd->pc_flags &= PQI_FLAGS_PERSISTENT; 512 } 513 514 /* ---- Handle partial DMA transfer ---- */ 515 if (cmd->pc_nwin > 0) { 516 if (++cmd->pc_winidx >= cmd->pc_nwin) 517 return (NULL); 518 if (ddi_dma_getwin(cmd->pc_dmahdl, cmd->pc_winidx, 519 &cmd->pc_dma_offset, &cmd->pc_dma_len, &cmd->pc_dmac, 520 &cmd->pc_dmaccount) == DDI_FAILURE) 521 return (NULL); 522 goto handle_dma_cookies; 523 } 524 525 /* ---- Setup data buffer ---- */ 526 if (bp != NULL && bp->b_bcount > 0 && 527 (cmd->pc_flags & PQI_FLAG_DMA_VALID) == 0) { 528 int dma_flags; 529 530 ASSERT(cmd->pc_dmahdl != NULL); 531 532 if ((bp->b_flags & B_READ) != 0) { 533 cmd->pc_flags |= PQI_FLAG_IO_READ; 534 dma_flags = DDI_DMA_READ; 535 } else { 536 cmd->pc_flags &= ~PQI_FLAG_IO_READ; 537 dma_flags = DDI_DMA_WRITE; 538 } 539 if ((flags & PKT_CONSISTENT) != 0) { 540 cmd->pc_flags |= PQI_FLAG_IO_IOPB; 541 dma_flags |= DDI_DMA_CONSISTENT; 542 } 543 if ((flags & PKT_DMA_PARTIAL) != 0) { 544 dma_flags |= DDI_DMA_PARTIAL; 545 } 546 rc = ddi_dma_buf_bind_handle(cmd->pc_dmahdl, bp, 547 dma_flags, callback, arg, &cmd->pc_dmac, 548 &cmd->pc_dmaccount); 549 550 if (rc == DDI_DMA_PARTIAL_MAP) { 551 (void) ddi_dma_numwin(cmd->pc_dmahdl, &cmd->pc_nwin); 552 cmd->pc_winidx = 0; 553 (void) ddi_dma_getwin(cmd->pc_dmahdl, cmd->pc_winidx, 554 &cmd->pc_dma_offset, &cmd->pc_dma_len, 555 &cmd->pc_dmac, &cmd->pc_dmaccount); 556 } else if (rc != 0 && rc != DDI_DMA_MAPPED) { 557 switch (rc) { 558 case DDI_DMA_NORESOURCES: 559 bioerror(bp, 0); 560 break; 561 case DDI_DMA_BADATTR: 562 case DDI_DMA_NOMAPPING: 563 bioerror(bp, EFAULT); 564 break; 565 case DDI_DMA_TOOBIG: 566 default: 567 bioerror(bp, EINVAL); 568 break; 569 } 570 goto out; 571 } 572 573 handle_dma_cookies: 574 ASSERT(cmd->pc_dmaccount > 0); 575 if (cmd->pc_dmaccount > 576 (sizeof (cmd->pc_cached_cookies) / 577 sizeof (ddi_dma_cookie_t))) { 578 dev_err(s->s_dip, CE_WARN, 579 "invalid cookie count: %d", cmd->pc_dmaccount); 580 goto out; 581 } 582 if (cmd->pc_dmaccount > 583 (s->s_sg_chain_buf_length / sizeof (pqi_sg_entry_t))) { 584 dev_err(s->s_dip, CE_WARN, 585 "Cookie(0x%x) verses SG(0x%" PRIx64 ") mismatch", 586 cmd->pc_dmaccount, 587 s->s_sg_chain_buf_length / sizeof (pqi_sg_entry_t)); 588 goto out; 589 } 590 591 cmd->pc_flags |= PQI_FLAG_DMA_VALID; 592 cmd->pc_dma_count = cmd->pc_dmac.dmac_size; 593 cmd->pc_cached_cookies[0] = cmd->pc_dmac; 594 595 for (i = 1; i < cmd->pc_dmaccount; i++) { 596 ddi_dma_nextcookie(cmd->pc_dmahdl, &cmd->pc_dmac); 597 cmd->pc_cached_cookies[i] = cmd->pc_dmac; 598 cmd->pc_dma_count += cmd->pc_dmac.dmac_size; 599 } 600 601 pkt->pkt_resid = bp->b_bcount - cmd->pc_dma_count; 602 } 603 604 return (pkt); 605 606 out: 607 if (is_new == B_TRUE) 608 pqi_destroy_pkt(ap, pkt); 609 return (NULL); 610 } 611 612 /* 613 * tran_destroy_pkt(9E) - scsi_pkt(9s) deallocation 614 * 615 * Notes: 616 * - also frees DMA resources if allocated 617 * - implicit DMA synchonization 618 */ 619 static void 620 pqi_destroy_pkt(struct scsi_address *ap, struct scsi_pkt *pkt) 621 { 622 pqi_cmd_t *c = PKT2CMD(pkt); 623 pqi_state_t *s = ADDR2PQI(ap); 624 625 if ((c->pc_flags & PQI_FLAG_DMA_VALID) != 0) { 626 c->pc_flags &= ~PQI_FLAG_DMA_VALID; 627 (void) ddi_dma_unbind_handle(c->pc_dmahdl); 628 } 629 cmd_ext_free(c); 630 631 kmem_cache_free(s->s_cmd_cache, c); 632 } 633 634 /* 635 * tran_dmafree(9E) - deallocate DMA resources allocated for command 636 */ 637 static void 638 pqi_dmafree(struct scsi_address *ap __unused, struct scsi_pkt *pkt) 639 { 640 pqi_cmd_t *cmd = PKT2CMD(pkt); 641 642 if (cmd->pc_flags & PQI_FLAG_DMA_VALID) { 643 cmd->pc_flags &= ~PQI_FLAG_DMA_VALID; 644 (void) ddi_dma_unbind_handle(cmd->pc_dmahdl); 645 } 646 } 647 648 /* 649 * tran_sync_pkt(9E) - explicit DMA synchronization 650 */ 651 static void 652 pqi_sync_pkt(struct scsi_address *ap __unused, struct scsi_pkt *pkt) 653 { 654 pqi_cmd_t *cmd = PKT2CMD(pkt); 655 656 if (cmd->pc_dmahdl != NULL) { 657 (void) ddi_dma_sync(cmd->pc_dmahdl, 0, 0, 658 (cmd->pc_flags & PQI_FLAG_IO_READ) ? DDI_DMA_SYNC_FORCPU : 659 DDI_DMA_SYNC_FORDEV); 660 } 661 } 662 663 static int 664 pqi_reset_notify(struct scsi_address *ap, int flag, 665 void (*callback)(caddr_t), caddr_t arg) 666 { 667 pqi_state_t *s = ADDR2PQI(ap); 668 669 return (scsi_hba_reset_notify_setup(ap, flag, callback, arg, 670 &s->s_mutex, &s->s_reset_notify_listf)); 671 } 672 673 /* 674 * Device / Hotplug control 675 */ 676 static int 677 pqi_quiesce(dev_info_t *dip) 678 { 679 pqi_state_t *s; 680 scsi_hba_tran_t *tran; 681 682 if ((tran = ddi_get_driver_private(dip)) == NULL || 683 (s = TRAN2PQI(tran)) == NULL) 684 return (-1); 685 686 mutex_enter(&s->s_mutex); 687 if (!HBA_IS_QUIESCED(s)) 688 s->s_flags |= PQI_HBA_QUIESCED; 689 690 if (s->s_cmd_queue_len != 0) { 691 /* ---- Outstanding commands present, wait ---- */ 692 s->s_flags |= PQI_HBA_QUIESCED_PENDING; 693 cv_wait(&s->s_quiescedvar, &s->s_mutex); 694 ASSERT0(s->s_cmd_queue_len); 695 } 696 mutex_exit(&s->s_mutex); 697 698 return (0); 699 } 700 701 static int 702 pqi_unquiesce(dev_info_t *dip) 703 { 704 pqi_state_t *s; 705 scsi_hba_tran_t *tran; 706 707 if ((tran = ddi_get_driver_private(dip)) == NULL || 708 (s = TRAN2PQI(tran)) == NULL) 709 return (-1); 710 711 mutex_enter(&s->s_mutex); 712 if (!HBA_IS_QUIESCED(s)) { 713 mutex_exit(&s->s_mutex); 714 return (0); 715 } 716 ASSERT0(s->s_cmd_queue_len); 717 s->s_flags &= ~PQI_HBA_QUIESCED; 718 mutex_exit(&s->s_mutex); 719 720 return (0); 721 } 722 723 static int 724 pqi_bus_config(dev_info_t *pdip, uint_t flag, 725 ddi_bus_config_op_t op, void *arg, dev_info_t **childp) 726 { 727 scsi_hba_tran_t *tran; 728 pqi_state_t *s; 729 int ret = NDI_FAILURE; 730 pqi_device_t *d; 731 char *ua; 732 733 tran = ddi_get_driver_private(pdip); 734 s = tran->tran_hba_private; 735 if (pqi_is_offline(s)) 736 return (NDI_FAILURE); 737 738 ndi_devi_enter(scsi_vhci_dip); 739 ndi_devi_enter(pdip); 740 switch (op) { 741 case BUS_CONFIG_ONE: 742 if ((ua = strrchr((char *)arg, '@')) != NULL) { 743 ua++; 744 d = pqi_find_target_ua(s, ua); 745 if (d != NULL) 746 ret = config_one(pdip, s, d, childp); 747 } else { 748 dev_err(s->s_dip, CE_WARN, "Couldn't decode %s", 749 (char *)arg); 750 } 751 flag |= NDI_MDI_FALLBACK; 752 break; 753 754 case BUS_CONFIG_DRIVER: 755 case BUS_CONFIG_ALL: 756 ret = pqi_config_all(pdip, s); 757 break; 758 default: 759 ret = NDI_FAILURE; 760 } 761 if (ret == NDI_SUCCESS) 762 ret = ndi_busop_bus_config(pdip, flag, op, arg, childp, 0); 763 ndi_devi_exit(pdip); 764 ndi_devi_exit(scsi_vhci_dip); 765 766 return (ret); 767 } 768 769 pqi_device_t * 770 pqi_find_target_ua(pqi_state_t *s, char *ua) 771 { 772 pqi_device_t *d; 773 774 mutex_enter(&s->s_mutex); 775 for (d = list_head(&s->s_devnodes); d != NULL; 776 d = list_next(&s->s_devnodes, d)) { 777 if (d->pd_online && strcmp(ua, d->pd_unit_address) == 0) 778 break; 779 } 780 mutex_exit(&s->s_mutex); 781 return (d); 782 } 783 784 int 785 pqi_config_all(dev_info_t *pdip, pqi_state_t *s) 786 { 787 pqi_device_t *d; 788 789 /* 790 * Make sure we bring the available devices into play first. These 791 * might be brand new devices just hotplugged into the system or 792 * they could be devices previously offlined because either they 793 * were pulled from an enclosure or a cable to the enclosure was 794 * pulled. 795 */ 796 /* ---- XXX Grab s_mutex ---- */ 797 for (d = list_head(&s->s_devnodes); d != NULL; 798 d = list_next(&s->s_devnodes, d)) { 799 if (d->pd_online) 800 (void) config_one(pdip, s, d, NULL); 801 } 802 803 /* 804 * Now deal with devices that we had previously known about, but are 805 * no longer available. 806 */ 807 for (d = list_head(&s->s_devnodes); d != NULL; 808 d = list_next(&s->s_devnodes, d)) { 809 if (!d->pd_online) 810 (void) config_one(pdip, s, d, NULL); 811 } 812 813 return (NDI_SUCCESS); 814 } 815 816 void 817 pqi_quiesced_notify(pqi_state_t *s) 818 { 819 mutex_enter(&s->s_mutex); 820 if (s->s_cmd_queue_len == 0 && 821 (s->s_flags & PQI_HBA_QUIESCED_PENDING) != 0) { 822 s->s_flags &= ~PQI_HBA_QUIESCED_PENDING; 823 cv_broadcast(&s->s_quiescedvar); 824 } 825 mutex_exit(&s->s_mutex); 826 } 827 828 /* 829 * []------------------------------------------------------------------[] 830 * | Support routines used only by the trans_xxx routines | 831 * []------------------------------------------------------------------[] 832 */ 833 #ifdef DEBUG 834 int pqi_force_timeout; 835 #endif /* DEBUG */ 836 837 static void 838 cmd_timeout_drive(pqi_device_t *d) 839 { 840 uint32_t timed_out_cnt = 0; 841 pqi_cmd_t *c, *next_c; 842 hrtime_t now = gethrtime(); 843 844 mutex_enter(&d->pd_mutex); 845 846 rescan: 847 c = list_head(&d->pd_cmd_list); 848 while (c != NULL) { 849 next_c = list_next(&d->pd_cmd_list, c); 850 #ifdef DEBUG 851 if (c->pc_expiration < now || pqi_force_timeout != 0) { 852 pqi_force_timeout = 0; 853 #else 854 if (c->pc_expiration < now) { 855 #endif /* DEBUG */ 856 struct scsi_pkt *pkt = CMD2PKT(c); 857 858 if (pkt != NULL) { 859 pkt->pkt_reason = CMD_TIMEOUT; 860 pkt->pkt_statistics = STAT_TIMEOUT; 861 } 862 ASSERT(c->pc_io_rqst != NULL); 863 /* 864 * If the i/o has not been serviced yet, 865 * mark the i/o as timed out and clear it out 866 */ 867 if (pqi_timeout_io(c->pc_io_rqst)) { 868 (void) pqi_cmd_action_nolock(c, 869 PQI_CMD_TIMEOUT); 870 timed_out_cnt++; 871 /* 872 * We dropped pd_mutex so the cmd 873 * list could have changed, restart the 874 * scan of the cmds. This will terminate 875 * since timed out cmds are removed from 876 * the list. 877 */ 878 goto rescan; 879 } 880 } 881 c = next_c; 882 } 883 884 d->pd_timedout += timed_out_cnt; 885 mutex_exit(&d->pd_mutex); 886 } 887 888 static void 889 cmd_timeout_scan(void *v) 890 { 891 pqi_state_t *s = v; 892 pqi_device_t *d; 893 894 mutex_enter(&s->s_mutex); 895 896 for (d = list_head(&s->s_devnodes); d != NULL; 897 d = list_next(&s->s_devnodes, d)) { 898 cmd_timeout_drive(d); 899 } 900 cmd_timeout_drive(&s->s_special_device); 901 902 mutex_exit(&s->s_mutex); 903 s->s_cmd_timeout = timeout(cmd_timeout_scan, s, 904 CMD_TIMEOUT_SCAN_SECS * drv_usectohz(MICROSEC)); 905 } 906 907 static void 908 abort_all(struct scsi_address *ap, pqi_state_t *s __unused) 909 { 910 pqi_device_t *devp; 911 912 if ((devp = scsi_device_hba_private_get(ap->a.a_sd)) == NULL) 913 return; 914 915 pqi_fail_drive_cmds(devp, CMD_ABORTED); 916 } 917 918 static boolean_t 919 create_phys_lun(pqi_state_t *s, pqi_device_t *d, 920 struct scsi_inquiry *inq, dev_info_t **childp) 921 { 922 char **compatible = NULL; 923 char *nodename = NULL; 924 int ncompatible = 0; 925 dev_info_t *dip; 926 927 /* ---- At this point we have a new device not in our list ---- */ 928 scsi_hba_nodename_compatible_get(inq, NULL, 929 inq->inq_dtype, NULL, &nodename, &compatible, &ncompatible); 930 if (nodename == NULL) 931 return (B_FALSE); 932 933 if (ndi_devi_alloc(s->s_dip, nodename, DEVI_SID_NODEID, &dip) != 934 NDI_SUCCESS) { 935 dev_err(s->s_dip, CE_WARN, "failed to alloc device instance"); 936 goto free_nodename; 937 } 938 939 d->pd_dip = dip; 940 d->pd_pip = NULL; 941 942 if (ndi_prop_update_int64(DDI_DEV_T_NONE, dip, LUN64_PROP, 943 d->pd_lun) != DDI_PROP_SUCCESS) { 944 goto free_devi; 945 } 946 947 if (ndi_prop_update_string_array(DDI_DEV_T_NONE, dip, COMPAT_PROP, 948 compatible, ncompatible) != DDI_PROP_SUCCESS) { 949 goto free_devi; 950 } 951 952 if (d->pd_wwid != 0) { 953 char wwn_str[20]; 954 (void) snprintf(wwn_str, 20, "w%016" PRIx64, d->pd_wwid); 955 if (ndi_prop_update_string(DDI_DEV_T_NONE, dip, 956 SCSI_ADDR_PROP_TARGET_PORT, wwn_str) != DDI_PROP_SUCCESS) { 957 goto free_devi; 958 } 959 } else { 960 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, TARGET_PROP, 961 d->pd_target) != DDI_PROP_SUCCESS) { 962 goto free_devi; 963 } 964 } 965 966 if (d->pd_guid != NULL) { 967 if (ddi_prop_update_string(DDI_DEV_T_NONE, dip, NDI_GUID, 968 d->pd_guid) != DDI_PROP_SUCCESS) { 969 goto free_devi; 970 } 971 } 972 973 if (ndi_prop_update_int(DDI_DEV_T_NONE, dip, "pm-capable", 1) != 974 DDI_PROP_SUCCESS) { 975 goto free_devi; 976 } 977 978 if (ndi_devi_online(dip, NDI_ONLINE_ATTACH) != NDI_SUCCESS) 979 goto free_devi; 980 981 if (childp != NULL) 982 *childp = dip; 983 984 scsi_hba_nodename_compatible_free(nodename, compatible); 985 986 return (B_TRUE); 987 988 free_devi: 989 ndi_prop_remove_all(dip); 990 (void) ndi_devi_free(dip); 991 d->pd_dip = NULL; 992 free_nodename: 993 scsi_hba_nodename_compatible_free(nodename, compatible); 994 return (B_FALSE); 995 } 996 997 static boolean_t 998 create_virt_lun(pqi_state_t *s, pqi_device_t *d, struct scsi_inquiry *inq, 999 dev_info_t **childp) 1000 { 1001 char *nodename; 1002 char **compatible; 1003 int ncompatible; 1004 int rval; 1005 mdi_pathinfo_t *pip = NULL; 1006 char *guid_ptr; 1007 char wwid_str[17]; 1008 dev_info_t *lun_dip; 1009 char *old_guid; 1010 1011 if (d->pd_pip_offlined != NULL) { 1012 lun_dip = mdi_pi_get_client(d->pd_pip_offlined); 1013 ASSERT(lun_dip != NULL); 1014 1015 if (ddi_prop_lookup_string(DDI_DEV_T_ANY, lun_dip, 1016 (DDI_PROP_DONTPASS | DDI_PROP_NOTPROM), 1017 MDI_CLIENT_GUID_PROP, &old_guid) == DDI_SUCCESS) { 1018 if (strncmp(d->pd_guid, old_guid, 1019 strlen(d->pd_guid)) == 0) { 1020 /* ---- Same path came back online ---- */ 1021 (void) ddi_prop_free(old_guid); 1022 if (mdi_pi_online(d->pd_pip_offlined, 0) == 1023 DDI_SUCCESS) { 1024 d->pd_pip = d->pd_pip_offlined; 1025 d->pd_pip_offlined = NULL; 1026 return (B_TRUE); 1027 } else { 1028 return (B_FALSE); 1029 } 1030 } else { 1031 /* ---- Different device in slot ---- */ 1032 (void) ddi_prop_free(old_guid); 1033 if (mdi_pi_offline(d->pd_pip_offlined, 0) != 1034 DDI_SUCCESS) { 1035 return (B_FALSE); 1036 } 1037 if (mdi_pi_free(d->pd_pip_offlined, 0) != 1038 MDI_SUCCESS) { 1039 return (B_FALSE); 1040 } 1041 d->pd_pip_offlined = NULL; 1042 } 1043 } else { 1044 dev_err(s->s_dip, CE_WARN, "Can't get client-guid " 1045 "property for lun %lx", d->pd_wwid); 1046 return (B_FALSE); 1047 } 1048 } 1049 1050 scsi_hba_nodename_compatible_get(inq, NULL, inq->inq_dtype, NULL, 1051 &nodename, &compatible, &ncompatible); 1052 if (nodename == NULL) 1053 return (B_FALSE); 1054 1055 if (d->pd_guid != NULL) { 1056 guid_ptr = d->pd_guid; 1057 } else { 1058 (void) snprintf(wwid_str, sizeof (wwid_str), "%" PRIx64, 1059 d->pd_wwid); 1060 guid_ptr = wwid_str; 1061 } 1062 rval = mdi_pi_alloc_compatible(s->s_dip, nodename, guid_ptr, 1063 d->pd_unit_address, compatible, ncompatible, 0, &pip); 1064 if (rval == MDI_SUCCESS) { 1065 mdi_pi_set_phci_private(pip, (caddr_t)d); 1066 1067 if (mdi_prop_update_string(pip, MDI_GUID, guid_ptr) != 1068 DDI_SUCCESS) { 1069 dev_err(s->s_dip, CE_WARN, 1070 "unable to create property (MDI_GUID) for %s", 1071 guid_ptr); 1072 goto cleanup; 1073 } 1074 1075 /* 1076 * For MPxIO, we actually don't really need to care 1077 * about the LUN or target property, because nothing 1078 * really uses them. 1079 */ 1080 if (mdi_prop_update_int64(pip, LUN64_PROP, d->pd_lun) != 1081 DDI_SUCCESS) { 1082 dev_err(s->s_dip, CE_WARN, 1083 "unable to create property (%s) for %s", 1084 LUN64_PROP, guid_ptr); 1085 goto cleanup; 1086 } 1087 1088 if (mdi_prop_update_string_array(pip, COMPAT_PROP, 1089 compatible, ncompatible) != DDI_SUCCESS) { 1090 dev_err(s->s_dip, CE_WARN, 1091 "unable to create property (%s) for %s", 1092 COMPAT_PROP, guid_ptr); 1093 goto cleanup; 1094 } 1095 1096 if (mdi_pi_online(pip, 0) == MDI_NOT_SUPPORTED) 1097 goto cleanup; 1098 1099 d->pd_dip = NULL; 1100 d->pd_pip = pip; 1101 } 1102 1103 scsi_hba_nodename_compatible_free(nodename, compatible); 1104 if (childp != NULL) 1105 *childp = mdi_pi_get_client(pip); 1106 return (B_TRUE); 1107 cleanup: 1108 scsi_hba_nodename_compatible_free(nodename, compatible); 1109 d->pd_pip = NULL; 1110 d->pd_dip = NULL; 1111 (void) mdi_prop_remove(pip, NULL); 1112 (void) mdi_pi_free(pip, 0); 1113 return (B_FALSE); 1114 } 1115 1116 static int 1117 config_one(dev_info_t *pdip, pqi_state_t *s, pqi_device_t *d, 1118 dev_info_t **childp) 1119 { 1120 struct scsi_inquiry inq; 1121 boolean_t rval = B_FALSE; 1122 1123 /* ---- Inquiry target ---- */ 1124 if (!d->pd_online || 1125 pqi_scsi_inquiry(s, d, 0, &inq, sizeof (inq)) == B_FALSE) { 1126 pqi_fail_drive_cmds(d, CMD_DEV_GONE); 1127 1128 if (d->pd_dip != NULL) { 1129 (void) ndi_devi_offline(d->pd_dip, 1130 NDI_DEVFS_CLEAN | NDI_DEVI_REMOVE); 1131 d->pd_dip = NULL; 1132 } else if (d->pd_pip != NULL) { 1133 (void) mdi_pi_offline(d->pd_pip, 0); 1134 d->pd_pip_offlined = d->pd_pip; 1135 d->pd_pip = NULL; 1136 } 1137 return (NDI_FAILURE); 1138 } else if (d->pd_dip != NULL) { 1139 if (childp != NULL) 1140 *childp = d->pd_dip; 1141 return (NDI_SUCCESS); 1142 } else if (d->pd_pip != NULL) { 1143 if (childp != NULL) 1144 *childp = mdi_pi_get_client(d->pd_pip); 1145 return (NDI_SUCCESS); 1146 } 1147 1148 d->pd_parent = pdip; 1149 if ((!s->s_disable_mpxio) && is_physical_dev(d)) 1150 rval = create_virt_lun(s, d, &inq, childp); 1151 1152 if (rval == B_FALSE) 1153 rval = create_phys_lun(s, d, &inq, childp); 1154 1155 return ((rval == B_TRUE) ? NDI_SUCCESS : NDI_FAILURE); 1156 } 1157 1158 static void 1159 cmd_ext_free(pqi_cmd_t *cmd) 1160 { 1161 struct scsi_pkt *pkt = CMD2PKT(cmd); 1162 1163 if ((cmd->pc_flags & PQI_FLAG_CDB_EXT) != 0) { 1164 kmem_free(pkt->pkt_cdbp, cmd->pc_cmdlen); 1165 cmd->pc_flags &= ~PQI_FLAG_CDB_EXT; 1166 } 1167 if ((cmd->pc_flags & PQI_FLAG_SCB_EXT) != 0) { 1168 kmem_free(pkt->pkt_scbp, cmd->pc_statuslen); 1169 cmd->pc_flags &= ~PQI_FLAG_SCB_EXT; 1170 } 1171 if ((cmd->pc_flags & PQI_FLAG_PRIV_EXT) != 0) { 1172 kmem_free(pkt->pkt_private, cmd->pc_tgtlen); 1173 cmd->pc_flags &= ~PQI_FLAG_PRIV_EXT; 1174 } 1175 } 1176 1177 static int 1178 cmd_ext_alloc(pqi_cmd_t *cmd, int kf) 1179 { 1180 struct scsi_pkt *pkt = CMD2PKT(cmd); 1181 void *buf; 1182 1183 if (cmd->pc_cmdlen > sizeof (cmd->pc_cdb)) { 1184 if ((buf = kmem_zalloc(cmd->pc_cmdlen, kf)) == NULL) 1185 return (DDI_FAILURE); 1186 pkt->pkt_cdbp = buf; 1187 cmd->pc_flags |= PQI_FLAG_CDB_EXT; 1188 } 1189 1190 if (cmd->pc_statuslen > sizeof (cmd->pc_cmd_scb)) { 1191 if ((buf = kmem_zalloc(cmd->pc_statuslen, kf)) == NULL) 1192 goto out; 1193 pkt->pkt_scbp = buf; 1194 cmd->pc_flags |= PQI_FLAG_SCB_EXT; 1195 } 1196 1197 if (cmd->pc_tgtlen > sizeof (cmd->pc_tgt_priv)) { 1198 if ((buf = kmem_zalloc(cmd->pc_tgtlen, kf)) == NULL) 1199 goto out; 1200 pkt->pkt_private = buf; 1201 cmd->pc_flags |= PQI_FLAG_PRIV_EXT; 1202 } 1203 1204 return (DDI_SUCCESS); 1205 1206 out: 1207 cmd_ext_free(cmd); 1208 1209 return (DDI_FAILURE); 1210 } 1211 1212 static boolean_t 1213 is_physical_dev(pqi_device_t *d) 1214 { 1215 return (d->pd_phys_dev ? B_TRUE : B_FALSE); 1216 } 1217