1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains functions that are called via interrupts. 28 */ 29 30 #include <sys/scsi/adapters/pmcs/pmcs.h> 31 32 #ifdef DEBUG 33 #define VALID_IOMB_CHECK(p, w, m, b, c) \ 34 if (!(w & PMCS_IOMB_VALID)) { \ 35 char l[64]; \ 36 (void) snprintf(l, sizeof (l), \ 37 "%s: INVALID IOMB (oq_ci=%u oq_pi=%u)", __func__, b, c); \ 38 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, l, m); \ 39 STEP_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, b, 1); \ 40 continue; \ 41 } 42 #define WRONG_OBID_CHECK(pwp, w, q) \ 43 if (((w & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT) != q) { \ 44 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, \ 45 "%s: COMPLETION WITH WRONG OBID (0x%x)", __func__, \ 46 (w & PMCS_IOMB_OBID_MASK) >> PMCS_IOMB_OBID_SHIFT); \ 47 } 48 #else 49 #define VALID_IOMB_CHECK(a, b, c, d, e) 50 #define WRONG_OBID_CHECK(a, b, c) 51 #endif 52 53 #define OQLIM_CHECK(p, l) \ 54 if (++l == (p)->ioq_depth) { \ 55 pmcs_prt(p, PMCS_PRT_DEBUG, NULL, NULL, \ 56 "%s: possible ob queue overflow", \ 57 __func__); \ 58 break; \ 59 } 60 61 #define COPY_OUTBOUND(p, w, l, n, a, x, q, c) \ 62 n = ((w & PMCS_IOMB_BC_MASK) >> PMCS_IOMB_BC_SHIFT); \ 63 a = PMCS_QENTRY_SIZE; \ 64 (void) memcpy(l, x, PMCS_QENTRY_SIZE); \ 65 if (n > 1) { \ 66 a <<= 1; \ 67 (void) memcpy(&l[PMCS_QENTRY_SIZE], \ 68 GET_OQ_ENTRY(p, q, c, 1), PMCS_QENTRY_SIZE); \ 69 } \ 70 pmcs_prt(p, PMCS_PRT_DEBUG3, NULL, NULL, \ 71 "%s: ptr %p ci %d w0 %x nbuf %d", \ 72 __func__, (void *)x, ci, w0, n) 73 74 #define EVT_PRT(hwp, msg, phy) \ 75 pmcs_prt(hwp, PMCS_PRT_DEBUG, NULL, NULL, "Phy 0x%x: %s", phy, # msg) 76 77 78 /* 79 * Map the link rate reported in the event to the SAS link rate value 80 */ 81 static uint8_t 82 pmcs_link_rate(uint32_t event_link_rate) 83 { 84 uint8_t sas_link_rate = 0; 85 86 switch (event_link_rate) { 87 case 1: 88 sas_link_rate = SAS_LINK_RATE_1_5GBIT; 89 break; 90 case 2: 91 sas_link_rate = SAS_LINK_RATE_3GBIT; 92 break; 93 case 4: 94 sas_link_rate = SAS_LINK_RATE_6GBIT; 95 break; 96 } 97 98 return (sas_link_rate); 99 } 100 101 /* 102 * Called with pwrk lock 103 */ 104 static void 105 pmcs_complete_work(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *iomb, size_t amt) 106 { 107 #ifdef DEBUG 108 pwp->ltime[pwp->lti] = gethrtime(); 109 pwp->ltags[pwp->lti++] = pwrk->htag; 110 #endif 111 pwrk->htag |= PMCS_TAG_DONE; 112 113 /* 114 * If the command has timed out, leave it in that state. 115 */ 116 if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) { 117 pwrk->state = PMCS_WORK_STATE_INTR; 118 } 119 120 pmcs_complete_work_impl(pwp, pwrk, iomb, amt); 121 } 122 123 static void 124 pmcs_work_not_found(pmcs_hw_t *pwp, uint32_t htag, uint32_t *iomb) 125 { 126 #ifdef DEBUG 127 int i; 128 hrtime_t now; 129 char buf[64]; 130 131 (void) snprintf(buf, sizeof (buf), 132 "unable to find work structure for tag 0x%x", htag); 133 134 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb); 135 if (htag == 0) { 136 return; 137 } 138 now = gethrtime(); 139 for (i = 0; i < 256; i++) { 140 mutex_enter(&pwp->dbglock); 141 if (pwp->ltags[i] == htag) { 142 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 143 "same tag already completed (%llu us ago)", 144 (unsigned long long) (now - pwp->ltime[i])); 145 } 146 if (pwp->ftags[i] == htag) { 147 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 148 "same tag started (line %d) (%llu ns ago)", 149 pwp->ftag_lines[i], (unsigned long long) 150 (now - pwp->ftime[i])); 151 } 152 mutex_exit(&pwp->dbglock); 153 } 154 #else 155 char buf[64]; 156 (void) snprintf(buf, sizeof (buf), 157 "unable to find work structure for tag 0x%x", htag); 158 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb); 159 #endif 160 } 161 162 163 static void 164 pmcs_process_io_completion(pmcs_hw_t *pwp, pmcs_iocomp_cb_t *ioccb, size_t amt) 165 { 166 pmcwork_t *pwrk; 167 uint32_t tag_type; 168 uint32_t htag = LE_32(((uint32_t *)((void *)ioccb->iomb))[1]); 169 170 pwrk = pmcs_tag2wp(pwp, htag); 171 if (pwrk == NULL) { 172 pmcs_work_not_found(pwp, htag, (void *)&ioccb->iomb); 173 kmem_cache_free(pwp->iocomp_cb_cache, ioccb); 174 return; 175 } 176 177 pwrk->htag |= PMCS_TAG_DONE; 178 179 /* 180 * If the command has timed out, leave it in that state. 181 */ 182 if (pwrk->state != PMCS_WORK_STATE_TIMED_OUT) { 183 pwrk->state = PMCS_WORK_STATE_INTR; 184 } 185 186 /* 187 * Some SATA and SAS commands are run in "WAIT" mode. 188 * We can tell this from the tag type. In this case, 189 * we just do a wakeup (not a callback). 190 */ 191 tag_type = PMCS_TAG_TYPE(pwrk->htag); 192 if (tag_type == PMCS_TAG_TYPE_WAIT) { 193 ASSERT(PMCS_TAG_TYPE(pwrk->htag) == PMCS_TAG_TYPE_WAIT); 194 if (pwrk->arg && amt) { 195 (void) memcpy(pwrk->arg, ioccb->iomb, amt); 196 } 197 cv_signal(&pwrk->sleep_cv); 198 mutex_exit(&pwrk->lock); 199 kmem_cache_free(pwp->iocomp_cb_cache, ioccb); 200 return; 201 } 202 ASSERT(tag_type == PMCS_TAG_TYPE_CBACK); 203 204 #ifdef DEBUG 205 pwp->ltime[pwp->lti] = gethrtime(); 206 pwp->ltags[pwp->lti++] = pwrk->htag; 207 #endif 208 209 ioccb->pwrk = pwrk; 210 211 /* 212 * Only update state to IOCOMPQ if we were in the INTR state. 213 * Any other state (e.g. TIMED_OUT, ABORTED) needs to remain. 214 */ 215 if (pwrk->state == PMCS_WORK_STATE_INTR) { 216 pwrk->state = PMCS_WORK_STATE_IOCOMPQ; 217 } 218 219 mutex_enter(&pwp->cq_lock); 220 if (pwp->iocomp_cb_tail) { 221 pwp->iocomp_cb_tail->next = ioccb; 222 pwp->iocomp_cb_tail = ioccb; 223 } else { 224 pwp->iocomp_cb_head = ioccb; 225 pwp->iocomp_cb_tail = ioccb; 226 } 227 ioccb->next = NULL; 228 mutex_exit(&pwp->cq_lock); 229 230 mutex_exit(&pwrk->lock); 231 /* Completion queue will be run at end of pmcs_iodone_intr */ 232 } 233 234 235 static void 236 pmcs_process_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) 237 { 238 pmcwork_t *pwrk; 239 uint32_t htag = LE_32(((uint32_t *)iomb)[1]); 240 241 pwrk = pmcs_tag2wp(pwp, htag); 242 if (pwrk == NULL) { 243 pmcs_work_not_found(pwp, htag, iomb); 244 return; 245 } 246 247 pmcs_complete_work(pwp, pwrk, iomb, amt); 248 /* 249 * The pwrk lock is now released 250 */ 251 } 252 253 static void 254 pmcs_kill_port(pmcs_hw_t *pwp, int portid) 255 { 256 pmcs_phy_t *pptr = pwp->ports[portid]; 257 258 if (pptr == NULL) { 259 return; 260 } 261 262 /* 263 * Clear any subsidiary phys 264 */ 265 mutex_enter(&pwp->lock); 266 267 for (pptr = pwp->root_phys; pptr; pptr = pptr->sibling) { 268 pmcs_lock_phy(pptr); 269 if (pptr->link_rate && pptr->portid == portid && 270 pptr->subsidiary) { 271 pmcs_clear_phy(pwp, pptr); 272 } 273 pmcs_unlock_phy(pptr); 274 } 275 276 pptr = pwp->ports[portid]; 277 pwp->ports[portid] = NULL; 278 mutex_exit(&pwp->lock); 279 280 pmcs_lock_phy(pptr); 281 pmcs_kill_changed(pwp, pptr, 0); 282 pmcs_unlock_phy(pptr); 283 284 RESTART_DISCOVERY(pwp); 285 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, "PortID 0x%x Cleared", portid); 286 } 287 288 void 289 pmcs_process_sas_hw_event(pmcs_hw_t *pwp, void *iomb, size_t amt) 290 { 291 uint32_t w1 = LE_32(((uint32_t *)iomb)[1]); 292 uint32_t w3 = LE_32(((uint32_t *)iomb)[3]); 293 char buf[32]; 294 uint8_t phynum = IOP_EVENT_PHYNUM(w1); 295 uint8_t portid = IOP_EVENT_PORTID(w1); 296 pmcs_iport_t *iport; 297 pmcs_phy_t *pptr, *subphy, *tphyp; 298 int need_ack = 0; 299 int primary; 300 301 switch (IOP_EVENT_EVENT(w1)) { 302 case IOP_EVENT_PHY_STOP_STATUS: 303 if (IOP_EVENT_STATUS(w1)) { 304 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 305 "PORT %d failed to stop (0x%x)", 306 phynum, IOP_EVENT_STATUS(w1)); 307 } else { 308 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 309 "PHY 0x%x Stopped", phynum); 310 mutex_enter(&pwp->lock); 311 pptr = pwp->root_phys + phynum; 312 pmcs_lock_phy(pptr); 313 mutex_exit(&pwp->lock); 314 if (pptr->configured) { 315 pmcs_kill_changed(pwp, pptr, 0); 316 } else { 317 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 318 } 319 pmcs_unlock_phy(pptr); 320 RESTART_DISCOVERY(pwp); 321 } 322 /* Reposition htag to the 'expected' position. */ 323 ((uint32_t *)iomb)[1] = ((uint32_t *)iomb)[2]; 324 pmcs_process_completion(pwp, iomb, amt); 325 break; 326 case IOP_EVENT_SAS_PHY_UP: 327 { 328 static const uint8_t sas_identify_af_endian_xfvec[] = { 329 0x5c, 0x5a, 0x56, 0x00 330 }; 331 pmcs_phy_t *rp; 332 sas_identify_af_t af; 333 uint64_t phy_id, wwn; 334 335 /* 336 * If we're not at running state, don't do anything 337 */ 338 mutex_enter(&pwp->lock); 339 if (pwp->state != STATE_RUNNING) { 340 mutex_exit(&pwp->lock); 341 break; 342 } 343 pptr = pwp->root_phys + phynum; 344 pmcs_lock_phy(pptr); 345 346 /* 347 * No need to lock the primary root PHY. It can never go 348 * away, and we're only concerned with the port width and 349 * the portid, both of which only ever change in this function. 350 */ 351 rp = pwp->ports[portid]; 352 353 mutex_exit(&pwp->lock); 354 355 pmcs_endian_transform(pwp, &af, &((uint32_t *)iomb)[4], 356 sas_identify_af_endian_xfvec); 357 358 /* Copy the remote address into our phy handle */ 359 (void) memcpy(pptr->sas_address, af.sas_address, 8); 360 wwn = pmcs_barray2wwn(pptr->sas_address); 361 phy_id = (uint64_t)af.phy_identifier; 362 363 /* 364 * Check to see if there is a PortID already active. 365 */ 366 if (rp) { 367 if (rp->portid != portid) { 368 pmcs_unlock_phy(pptr); 369 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 370 "PortID 0x%x: PHY 0x%x SAS LINK UP IS FOR " 371 "A DIFFERENT PORTID 0x%x", rp->portid, 372 phynum, portid); 373 break; 374 } 375 376 /* 377 * If the dtype isn't NOTHING, then this is actually 378 * the primary PHY for this port. It probably went 379 * down and came back up, so be sure not to mark it 380 * as a subsidiary. 381 */ 382 if (pptr->dtype == NOTHING) { 383 pptr->subsidiary = 1; 384 } 385 pptr->link_rate = 386 pmcs_link_rate(IOP_EVENT_LINK_RATE(w1)); 387 pptr->portid = portid; 388 pptr->dead = 0; 389 pmcs_unlock_phy(pptr); 390 391 rp->width = IOP_EVENT_NPIP(w3); 392 393 /* Add this PHY to the phymap */ 394 if (sas_phymap_phy_add(pwp->hss_phymap, phynum, 395 pwp->sas_wwns[0], wwn) != DDI_SUCCESS) { 396 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 397 "Unable to add phy %u for 0x%" PRIx64 ".0x%" 398 PRIx64, phynum, pwp->sas_wwns[rp->phynum], 399 wwn); 400 } 401 402 /* 403 * Get our iport, if attached, and set it up. Update 404 * the PHY's phymask props while we're locked. 405 */ 406 pmcs_lock_phy(pptr); 407 pmcs_update_phy_pm_props(pptr, (1ULL << phynum), 408 (1ULL << phy_id), B_TRUE); 409 pmcs_unlock_phy(pptr); 410 iport = pmcs_get_iport_by_wwn(pwp, wwn); 411 if (iport) { 412 primary = !pptr->subsidiary; 413 414 mutex_enter(&iport->lock); 415 if (primary) { 416 iport->pptr = pptr; 417 } 418 if (iport->ua_state == UA_ACTIVE) { 419 pmcs_add_phy_to_iport(iport, pptr); 420 pptr->iport = iport; 421 } 422 mutex_exit(&iport->lock); 423 pmcs_rele_iport(iport); 424 } 425 426 pmcs_update_phy_pm_props(rp, (1ULL << phynum), 427 (1ULL << phy_id), B_TRUE); 428 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 429 "PortID 0x%x: PHY 0x%x SAS LINK UP WIDENS PORT " 430 "TO %d PHYS", portid, phynum, rp->width); 431 432 break; 433 } 434 435 /* 436 * Check to see if anything is here already 437 */ 438 if (pptr->dtype != NOTHING && pptr->configured) { 439 pmcs_unlock_phy(pptr); 440 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 441 "PortID 0x%x: SAS PHY 0x%x UP HITS EXISTING " 442 "CONFIGURED TREE", portid, phynum); 443 break; 444 } 445 446 if (af.address_frame_type != SAS_AF_IDENTIFY) { 447 pmcs_unlock_phy(pptr); 448 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 449 "SAS link up on phy 0x%x, " 450 "but unexpected frame type 0x%x found", phynum, 451 af.address_frame_type); 452 break; 453 } 454 pptr->width = IOP_EVENT_NPIP(w3); 455 pptr->portid = portid; 456 pptr->dead = 0; 457 pptr->link_rate = pmcs_link_rate(IOP_EVENT_LINK_RATE(w1)); 458 459 /* 460 * Check to see whether this is an expander or an endpoint 461 */ 462 switch (af.device_type) { 463 case SAS_IF_DTYPE_ENDPOINT: 464 pptr->pend_dtype = SAS; 465 pptr->dtype = SAS; 466 break; 467 case SAS_IF_DTYPE_EDGE: 468 case SAS_IF_DTYPE_FANOUT: 469 pptr->pend_dtype = EXPANDER; 470 pptr->dtype = EXPANDER; 471 break; 472 default: 473 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 474 "unknown device type 0x%x", af.device_type); 475 pptr->pend_dtype = NOTHING; 476 pptr->dtype = NOTHING; 477 break; 478 } 479 480 /* 481 * If this is a direct-attached SAS drive, do the spinup 482 * release now. 483 */ 484 if (pptr->dtype == SAS) { 485 pptr->spinup_hold = 1; 486 pmcs_spinup_release(pwp, pptr); 487 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, 488 "Release spinup hold on PHY 0x%x", phynum); 489 } 490 491 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 492 if (pptr->width > 1) { 493 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 494 "PortID 0x%x: PHY 0x%x SAS" 495 " LINK UP @ %s Gb with %d phys/s", portid, phynum, 496 pmcs_get_rate(pptr->link_rate), pptr->width); 497 } else { 498 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 499 "PortID 0x%x: PHY 0x%x SAS" 500 " LINK UP @ %s Gb/s", portid, phynum, 501 pmcs_get_rate(pptr->link_rate)); 502 } 503 pmcs_unlock_phy(pptr); 504 505 /* Add this PHY to the phymap */ 506 if (sas_phymap_phy_add(pwp->hss_phymap, phynum, 507 pwp->sas_wwns[0], wwn) != DDI_SUCCESS) { 508 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 509 "Unable to add phy %u for 0x%" PRIx64 ".0x%" 510 PRIx64, phynum, pwp->sas_wwns[pptr->phynum], wwn); 511 } 512 513 /* Get a pointer to our iport and set it up if attached */ 514 iport = pmcs_get_iport_by_wwn(pwp, wwn); 515 if (iport) { 516 primary = !pptr->subsidiary; 517 518 mutex_enter(&iport->lock); 519 if (primary) { 520 iport->pptr = pptr; 521 } 522 if (iport->ua_state == UA_ACTIVE) { 523 pmcs_add_phy_to_iport(iport, pptr); 524 pptr->iport = iport; 525 } 526 mutex_exit(&iport->lock); 527 pmcs_rele_iport(iport); 528 } 529 530 pmcs_lock_phy(pptr); 531 pmcs_update_phy_pm_props(pptr, (1ULL << phynum), 532 (1ULL << phy_id), B_TRUE); 533 pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT, 534 SAS_PHY_ONLINE, pptr); 535 pmcs_unlock_phy(pptr); 536 537 mutex_enter(&pwp->lock); 538 pwp->ports[portid] = pptr; 539 mutex_exit(&pwp->lock); 540 RESTART_DISCOVERY(pwp); 541 542 break; 543 } 544 case IOP_EVENT_SATA_PHY_UP: { 545 uint64_t wwn; 546 /* 547 * If we're not at running state, don't do anything 548 */ 549 mutex_enter(&pwp->lock); 550 if (pwp->state != STATE_RUNNING) { 551 mutex_exit(&pwp->lock); 552 break; 553 } 554 555 /* 556 * Check to see if anything is here already 557 */ 558 pmcs_lock_phy(pwp->root_phys + phynum); 559 pptr = pwp->root_phys + phynum; 560 mutex_exit(&pwp->lock); 561 562 if (pptr->dtype != NOTHING && pptr->configured) { 563 pmcs_unlock_phy(pptr); 564 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 565 "PortID 0x%x: SATA PHY 0x%x" 566 " UP HITS EXISTING CONFIGURED TREE", 567 portid, phynum); 568 break; 569 } 570 571 pptr->width = 1; 572 pptr->dead = 0; 573 574 /* 575 * Install the PHY number in the least significant byte 576 * with a NAA=3 (locally assigned address) in the most 577 * significant nubble. 578 * 579 * Later, we'll either use that or dig a 580 * WWN out of words 108..111. 581 */ 582 pptr->sas_address[0] = 0x30; 583 pptr->sas_address[1] = 0; 584 pptr->sas_address[2] = 0; 585 pptr->sas_address[3] = 0; 586 pptr->sas_address[4] = 0; 587 pptr->sas_address[5] = 0; 588 pptr->sas_address[6] = 0; 589 pptr->sas_address[7] = phynum; 590 pptr->portid = portid; 591 pptr->link_rate = pmcs_link_rate(IOP_EVENT_LINK_RATE(w1)); 592 pptr->dtype = SATA; 593 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 594 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 595 "PortID 0x%x: PHY 0x%x SATA LINK UP @ %s Gb/s", 596 pptr->portid, phynum, pmcs_get_rate(pptr->link_rate)); 597 wwn = pmcs_barray2wwn(pptr->sas_address); 598 pmcs_unlock_phy(pptr); 599 600 /* Add this PHY to the phymap */ 601 if (sas_phymap_phy_add(pwp->hss_phymap, phynum, 602 pwp->sas_wwns[0], wwn) != DDI_SUCCESS) { 603 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 604 "Unable to add phy %u for 0x%" PRIx64 ".0x%" 605 PRIx64, phynum, pwp->sas_wwns[pptr->phynum], 606 wwn); 607 } 608 609 /* Get our iport, if attached, and set it up */ 610 iport = pmcs_get_iport_by_wwn(pwp, wwn); 611 if (iport) { 612 mutex_enter(&iport->lock); 613 iport->pptr = pptr; 614 if (iport->ua_state == UA_ACTIVE) { 615 pmcs_add_phy_to_iport(iport, pptr); 616 pptr->iport = iport; 617 ASSERT(iport->nphy == 1); 618 iport->nphy = 1; 619 } 620 mutex_exit(&iport->lock); 621 pmcs_rele_iport(iport); 622 } 623 624 pmcs_lock_phy(pptr); 625 pmcs_update_phy_pm_props(pptr, (1ULL << phynum), 1ULL, B_TRUE); 626 pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT, 627 SAS_PHY_ONLINE, pptr); 628 pmcs_unlock_phy(pptr); 629 630 mutex_enter(&pwp->lock); 631 pwp->ports[pptr->portid] = pptr; 632 mutex_exit(&pwp->lock); 633 RESTART_DISCOVERY(pwp); 634 break; 635 } 636 637 case IOP_EVENT_SATA_SPINUP_HOLD: 638 tphyp = (pmcs_phy_t *)(pwp->root_phys + phynum); 639 /* 640 * No need to lock the entire tree for this 641 */ 642 mutex_enter(&tphyp->phy_lock); 643 tphyp->spinup_hold = 1; 644 pmcs_spinup_release(pwp, tphyp); 645 mutex_exit(&tphyp->phy_lock); 646 break; 647 case IOP_EVENT_PHY_DOWN: { 648 uint64_t wwn; 649 650 /* 651 * If we're not at running state, don't do anything 652 */ 653 mutex_enter(&pwp->lock); 654 if (pwp->state != STATE_RUNNING) { 655 mutex_exit(&pwp->lock); 656 break; 657 } 658 pptr = pwp->ports[portid]; 659 660 subphy = pwp->root_phys + phynum; 661 /* 662 * subphy is a pointer to the PHY corresponding to the incoming 663 * event. pptr points to the primary PHY for the corresponding 664 * port. So, subphy and pptr may or may not be the same PHY, 665 * but that doesn't change what we need to do with each. 666 */ 667 ASSERT(subphy); 668 mutex_exit(&pwp->lock); 669 670 if (pptr == NULL) { 671 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 672 "PortID 0x%x: PHY 0x%x LINK DOWN- no portid ptr", 673 portid, phynum); 674 break; 675 } 676 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_NIL) { 677 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 678 "PortID 0x%x: PHY 0x%x NOT VALID YET", 679 portid, phynum); 680 need_ack = 1; 681 break; 682 } 683 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_IN_RESET) { 684 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 685 "PortID 0x%x: PHY 0x%x IN RESET", 686 portid, phynum); 687 /* Entire port is down due to a host-initiated reset */ 688 mutex_enter(&pptr->phy_lock); 689 /* Clear the phymask props in pptr */ 690 pmcs_update_phy_pm_props(pptr, pptr->att_port_pm_tmp, 691 pptr->tgt_port_pm_tmp, B_FALSE); 692 iport = pptr->iport; 693 mutex_exit(&pptr->phy_lock); 694 if (iport) { 695 mutex_enter(&iport->lock); 696 pmcs_iport_teardown_phys(iport); 697 mutex_exit(&iport->lock); 698 } 699 700 /* Clear down all PHYs in the port */ 701 for (pptr = pwp->root_phys; pptr; 702 pptr = pptr->sibling) { 703 pmcs_lock_phy(pptr); 704 if (pptr->portid == portid) { 705 pptr->dtype = NOTHING; 706 pptr->portid = 707 PMCS_IPORT_INVALID_PORT_ID; 708 if (pptr->valid_device_id) { 709 pptr->deregister_wait = 1; 710 } 711 } 712 pmcs_unlock_phy(pptr); 713 SCHEDULE_WORK(pwp, PMCS_WORK_DEREGISTER_DEV); 714 (void) ddi_taskq_dispatch(pwp->tq, pmcs_worker, 715 pwp, DDI_NOSLEEP); 716 } 717 718 break; 719 } 720 721 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_LOSTCOMM) { 722 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 723 "PortID 0x%x: PHY 0x%x TEMPORARILY DOWN", 724 portid, phynum); 725 need_ack = 1; 726 break; 727 } 728 729 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_VALID) { 730 731 /* 732 * This is not the last phy in the port, so if this 733 * is the primary PHY, promote another PHY to primary. 734 */ 735 if (pptr == subphy) { 736 primary = !subphy->subsidiary; 737 ASSERT(primary); 738 739 tphyp = pptr; 740 pptr = pmcs_promote_next_phy(tphyp); 741 742 if (pptr) { 743 /* Update primary pptr in ports */ 744 pwp->ports[portid] = pptr; 745 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, 746 NULL, "PortID 0x%x: PHY 0x%x " 747 "promoted to primary", portid, 748 pptr->phynum); 749 } else { 750 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, 751 NULL, "PortID 0x%x: PHY 0x%x: " 752 "unable to promote phy", portid, 753 phynum); 754 } 755 } 756 757 /* 758 * Drop port width on the primary phy handle 759 * No need to lock the entire tree for this 760 */ 761 mutex_enter(&pptr->phy_lock); 762 pmcs_update_phy_pm_props(pptr, subphy->att_port_pm_tmp, 763 subphy->tgt_port_pm_tmp, B_FALSE); 764 pptr->width = IOP_EVENT_NPIP(w3); 765 mutex_exit(&pptr->phy_lock); 766 767 /* Clear the iport reference and portid on the subphy */ 768 mutex_enter(&subphy->phy_lock); 769 iport = subphy->iport; 770 subphy->iport = NULL; 771 subphy->portid = PMCS_PHY_INVALID_PORT_ID; 772 subphy->dtype = NOTHING; 773 mutex_exit(&subphy->phy_lock); 774 775 /* 776 * If the iport was set on this phy, decrement its 777 * nphy count and remove this phy from the phys list. 778 */ 779 if (iport) { 780 mutex_enter(&iport->lock); 781 if (iport->ua_state == UA_ACTIVE) { 782 pmcs_remove_phy_from_iport(iport, 783 subphy); 784 } 785 mutex_exit(&iport->lock); 786 } 787 788 pmcs_lock_phy(subphy); 789 wwn = pmcs_barray2wwn(pptr->sas_address); 790 if (subphy->subsidiary) 791 pmcs_clear_phy(pwp, subphy); 792 pmcs_unlock_phy(subphy); 793 794 /* Remove this PHY from the phymap */ 795 if (sas_phymap_phy_rem(pwp->hss_phymap, phynum) != 796 DDI_SUCCESS) { 797 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 798 "Unable to remove phy %u for 0x%" PRIx64 799 ".0x%" PRIx64, phynum, 800 pwp->sas_wwns[pptr->phynum], wwn); 801 } 802 803 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 804 "PortID 0x%x: PHY 0x%x LINK DOWN NARROWS PORT " 805 "TO %d PHYS", portid, phynum, pptr->width); 806 break; 807 } 808 if (IOP_EVENT_PORT_STATE(w3) != IOP_EVENT_PS_INVALID) { 809 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 810 "PortID 0x%x: PHY 0x%x LINK DOWN NOT HANDLED " 811 "(state 0x%x)", portid, phynum, 812 IOP_EVENT_PORT_STATE(w3)); 813 need_ack = 1; 814 break; 815 } 816 /* Remove this PHY from the phymap */ 817 if (sas_phymap_phy_rem(pwp->hss_phymap, phynum) != 818 DDI_SUCCESS) { 819 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 820 "Unable to remove phy %u for 0x%" PRIx64 821 ".0x%" PRIx64, phynum, 822 pwp->sas_wwns[pptr->phynum], wwn); 823 } 824 825 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 826 "PortID 0x%x: PHY 0x%x LINK DOWN (port invalid)", 827 portid, phynum); 828 829 /* 830 * Last PHY on the port. 831 * Assumption: pptr and subphy are both "valid". In fact, 832 * they should be one and the same. 833 * 834 * Drop port width on the primary phy handle 835 * Report the event and clear its PHY pm props while we've 836 * got the lock 837 */ 838 ASSERT(pptr == subphy); 839 mutex_enter(&pptr->phy_lock); 840 pptr->width = 0; 841 pmcs_update_phy_pm_props(pptr, pptr->att_port_pm_tmp, 842 pptr->tgt_port_pm_tmp, B_FALSE); 843 pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT, 844 SAS_PHY_OFFLINE, pptr); 845 mutex_exit(&pptr->phy_lock); 846 847 /* Clear the iport reference and portid on the subphy */ 848 pmcs_lock_phy(subphy); 849 iport = subphy->iport; 850 subphy->deregister_wait = 1; 851 subphy->iport = NULL; 852 subphy->portid = PMCS_PHY_INVALID_PORT_ID; 853 subphy->dtype = NOTHING; 854 pmcs_unlock_phy(subphy); 855 SCHEDULE_WORK(pwp, PMCS_WORK_DEREGISTER_DEV); 856 (void) ddi_taskq_dispatch(pwp->tq, pmcs_worker, 857 pwp, DDI_NOSLEEP); 858 859 /* 860 * If the iport was set on this phy, decrement its 861 * nphy count and remove this phy from the phys list. 862 * Also, clear the iport's pptr as this port is now 863 * down. 864 */ 865 if (iport) { 866 mutex_enter(&iport->lock); 867 if (iport->ua_state == UA_ACTIVE) { 868 pmcs_remove_phy_from_iport(iport, subphy); 869 iport->pptr = NULL; 870 iport->ua_state = UA_PEND_DEACTIVATE; 871 } 872 mutex_exit(&iport->lock); 873 } 874 875 pmcs_lock_phy(subphy); 876 if (subphy->subsidiary) 877 pmcs_clear_phy(pwp, subphy); 878 pmcs_unlock_phy(subphy); 879 880 /* 881 * Since we're now really dead, it's time to clean up. 882 */ 883 pmcs_kill_port(pwp, portid); 884 need_ack = 1; 885 886 break; 887 } 888 case IOP_EVENT_BROADCAST_CHANGE: 889 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 890 "PortID 0x%x: PHY 0x%x Broadcast Change", portid, phynum); 891 need_ack = 1; 892 mutex_enter(&pwp->lock); 893 pptr = pwp->ports[portid]; 894 if (pptr) { 895 pmcs_lock_phy(pptr); 896 if (pptr->phynum == phynum) { 897 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 898 } 899 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 900 SAS_PORT_BROADCAST_CHANGE, pptr); 901 pmcs_unlock_phy(pptr); 902 } 903 mutex_exit(&pwp->lock); 904 RESTART_DISCOVERY(pwp); 905 break; 906 case IOP_EVENT_BROADCAST_SES: 907 EVT_PRT(pwp, IOP_EVENT_BROADCAST_SES, phynum); 908 mutex_enter(&pwp->lock); 909 pptr = pwp->ports[portid]; 910 mutex_exit(&pwp->lock); 911 if (pptr) { 912 pmcs_lock_phy(pptr); 913 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 914 SAS_PORT_BROADCAST_SES, pptr); 915 pmcs_unlock_phy(pptr); 916 } 917 break; 918 case IOP_EVENT_PHY_ERR_INBOUND_CRC: 919 { 920 char buf[32]; 921 (void) snprintf(buf, sizeof (buf), "Inbound PHY CRC error"); 922 need_ack = 1; 923 break; 924 } 925 case IOP_EVENT_HARD_RESET_RECEIVED: 926 EVT_PRT(pwp, IOP_EVENT_HARD_RESET_RECEIVED, phynum); 927 break; 928 case IOP_EVENT_EVENT_ID_FRAME_TIMO: 929 EVT_PRT(pwp, IOP_EVENT_EVENT_ID_FRAME_TIMO, phynum); 930 break; 931 case IOP_EVENT_BROADCAST_EXP: 932 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 933 "PortID 0x%x: PHY 0x%x Broadcast Exp Change", 934 portid, phynum); 935 /* 936 * Comparing Section 6.8.1.4 of SMHBA (rev 7) spec and Section 937 * 7.2.3 of SAS2 (Rev 15) spec, 938 * _BROADCAST_EXPANDER event corresponds to _D01_4 primitive 939 */ 940 mutex_enter(&pwp->lock); 941 pptr = pwp->ports[portid]; 942 mutex_exit(&pwp->lock); 943 if (pptr) { 944 pmcs_lock_phy(pptr); 945 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 946 SAS_PORT_BROADCAST_D01_4, pptr); 947 pmcs_unlock_phy(pptr); 948 } 949 break; 950 case IOP_EVENT_PHY_START_STATUS: 951 switch (IOP_EVENT_STATUS(w1)) { 952 case IOP_PHY_START_OK: 953 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 954 "PHY 0x%x Started", phynum); 955 break; 956 case IOP_PHY_START_ALREADY: 957 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 958 "PHY 0x%x Started (Already)", phynum); 959 break; 960 case IOP_PHY_START_INVALID: 961 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 962 "PHY 0x%x failed to start (invalid phy)", phynum); 963 break; 964 case IOP_PHY_START_ERROR: 965 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 966 "PHY 0x%x Start Error", phynum); 967 break; 968 default: 969 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 970 "PHY 0x%x failed to start (0x%x)", phynum, 971 IOP_EVENT_STATUS(w1)); 972 break; 973 } 974 /* Reposition htag to the 'expected' position. */ 975 ((uint32_t *)iomb)[1] = ((uint32_t *)iomb)[2]; 976 pmcs_process_completion(pwp, iomb, amt); 977 break; 978 case IOP_EVENT_PHY_ERR_INVALID_DWORD: 979 need_ack = 1; 980 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_INVALID_DWORD, phynum); 981 break; 982 case IOP_EVENT_PHY_ERR_DISPARITY_ERROR: 983 need_ack = 1; 984 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_DISPARITY_ERROR, phynum); 985 break; 986 case IOP_EVENT_PHY_ERR_CODE_VIOLATION: 987 need_ack = 1; 988 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_CODE_VIOLATION, phynum); 989 break; 990 case IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN: 991 need_ack = 1; 992 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN, phynum); 993 break; 994 case IOP_EVENT_PHY_ERR_PHY_RESET_FAILD: 995 need_ack = 1; 996 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_PHY_RESET_FAILD, phynum); 997 break; 998 case IOP_EVENT_PORT_RECOVERY_TIMER_TMO: 999 EVT_PRT(pwp, IOP_EVENT_PORT_RECOVERY_TIMER_TMO, phynum); 1000 break; 1001 case IOP_EVENT_PORT_RECOVER: 1002 EVT_PRT(pwp, IOP_EVENT_PORT_RECOVER, phynum); 1003 break; 1004 case IOP_EVENT_PORT_INVALID: 1005 mutex_enter(&pwp->lock); 1006 if (pwp->state != STATE_RUNNING) { 1007 mutex_exit(&pwp->lock); 1008 break; 1009 } 1010 mutex_exit(&pwp->lock); 1011 pmcs_kill_port(pwp, portid); 1012 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 1013 "PortID 0x%x: PORT Now Invalid", portid); 1014 break; 1015 case IOP_EVENT_PORT_RESET_TIMER_TMO: 1016 EVT_PRT(pwp, IOP_EVENT_PORT_RESET_TIMER_TMO, phynum); 1017 break; 1018 case IOP_EVENT_PORT_RESET_COMPLETE: 1019 EVT_PRT(pwp, IOP_EVENT_PORT_RESET_COMPLETE, phynum); 1020 break; 1021 case IOP_EVENT_BROADCAST_ASYNC_EVENT: 1022 EVT_PRT(pwp, IOP_EVENT_BROADCAST_ASYNC_EVENT, phynum); 1023 /* 1024 * Comparing Section 6.8.1.4 of SMHBA (rev 7) spec and Section 1025 * 7.2.3 of SAS2 (Rev 15) spec, 1026 * _BROADCAST_ASYNC event corresponds to _D04_7 primitive 1027 */ 1028 mutex_enter(&pwp->lock); 1029 pptr = pwp->ports[portid]; 1030 mutex_exit(&pwp->lock); 1031 if (pptr) { 1032 pmcs_lock_phy(pptr); 1033 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 1034 SAS_PORT_BROADCAST_D04_7, pptr); 1035 pmcs_unlock_phy(pptr); 1036 } 1037 break; 1038 default: 1039 (void) snprintf(buf, sizeof (buf), 1040 "unknown SAS H/W Event PHY 0x%x", phynum); 1041 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb); 1042 break; 1043 } 1044 if (need_ack) { 1045 mutex_enter(&pwp->lock); 1046 /* 1047 * Don't lock the entire tree for this. Just grab the mutex 1048 * on the root PHY. 1049 */ 1050 tphyp = pwp->root_phys + phynum; 1051 mutex_enter(&tphyp->phy_lock); 1052 tphyp->hw_event_ack = w1; 1053 mutex_exit(&tphyp->phy_lock); 1054 mutex_exit(&pwp->lock); 1055 pmcs_ack_events(pwp); 1056 } 1057 } 1058 1059 static void 1060 pmcs_process_echo_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) 1061 { 1062 echo_test_t fred; 1063 pmcwork_t *pwrk; 1064 uint32_t *msg = iomb, htag = LE_32(msg[1]); 1065 pwrk = pmcs_tag2wp(pwp, htag); 1066 if (pwrk) { 1067 (void) memcpy(&fred, &((uint32_t *)iomb)[2], sizeof (fred)); 1068 fred.ptr[0]++; 1069 msg[2] = LE_32(PMCOUT_STATUS_OK); 1070 pmcs_complete_work(pwp, pwrk, msg, amt); 1071 } else { 1072 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, 1073 "ECHO completion with no work structure", iomb); 1074 } 1075 } 1076 1077 static void 1078 pmcs_process_ssp_event(pmcs_hw_t *pwp, void *iomb, size_t amt) 1079 { 1080 _NOTE(ARGUNUSED(amt)); 1081 uint32_t status, htag, *w; 1082 pmcwork_t *pwrk; 1083 pmcs_phy_t *phyp = NULL; 1084 char *path; 1085 1086 w = iomb; 1087 htag = LE_32(w[1]); 1088 status = LE_32(w[2]); 1089 1090 1091 pwrk = pmcs_tag2wp(pwp, htag); 1092 if (pwrk == NULL) { 1093 path = "????"; 1094 } else { 1095 phyp = pwrk->phy; 1096 path = pwrk->phy->path; 1097 } 1098 1099 if (status != PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) { 1100 char buf[20]; 1101 const char *emsg = pmcs_status_str(status); 1102 1103 if (emsg == NULL) { 1104 (void) snprintf(buf, sizeof (buf), "Status 0x%x", 1105 status); 1106 emsg = buf; 1107 } 1108 pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL, "%s: Bad SAS Status " 1109 "(tag 0x%x) %s on %s", __func__, htag, emsg, path); 1110 if (pwrk != NULL) { 1111 /* 1112 * There may be pending command on a target device. 1113 * Or, it may be a double fault. 1114 */ 1115 pmcs_start_ssp_event_recovery(pwp, pwrk, iomb, amt); 1116 } 1117 } else { 1118 pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, NULL, 1119 "%s: tag %x put onto the wire for %s", 1120 __func__, htag, path); 1121 if (pwrk) { 1122 pwrk->onwire = 1; 1123 mutex_exit(&pwrk->lock); 1124 } 1125 } 1126 } 1127 1128 static void 1129 pmcs_process_sata_event(pmcs_hw_t *pwp, void *iomb, size_t amt) 1130 { 1131 _NOTE(ARGUNUSED(amt)); 1132 pmcwork_t *pwrk = NULL; 1133 pmcs_phy_t *pptr; 1134 uint32_t status, htag, *w; 1135 char *path; 1136 1137 w = iomb; 1138 htag = LE_32(w[1]); 1139 status = LE_32(w[2]); 1140 1141 /* 1142 * If the status is PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE, 1143 * we have to issue a READ LOG EXT ATA (page 0x10) command 1144 * to the device. In this case, htag is not valid. 1145 * 1146 * If the status is PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED, we're 1147 * just noting that an I/O got put onto the wire. 1148 * 1149 * Othewise, other errors are indicative that things need to 1150 * be aborted. 1151 */ 1152 path = NULL; 1153 if (htag) { 1154 pwrk = pmcs_tag2wp(pwp, htag); 1155 if (pwrk) { 1156 pmcs_lock_phy(pwrk->phy); 1157 pptr = pwrk->phy; 1158 path = pptr->path; 1159 } 1160 } 1161 if (path == NULL) { 1162 mutex_enter(&pwp->lock); 1163 pptr = pmcs_find_phy_by_devid(pwp, LE_32(w[4])); 1164 /* This PHY is now locked */ 1165 mutex_exit(&pwp->lock); 1166 if (pptr) { 1167 path = pptr->path; 1168 } else { 1169 path = "????"; 1170 } 1171 } 1172 1173 if (status != PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) { 1174 char buf[20]; 1175 const char *emsg = pmcs_status_str(status); 1176 1177 ASSERT(pptr != NULL); 1178 if (emsg == NULL) { 1179 (void) snprintf(buf, sizeof (buf), "Status 0x%x", 1180 status); 1181 emsg = buf; 1182 } 1183 if (status == PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE) { 1184 ASSERT(pptr != NULL); 1185 pptr->need_rl_ext = 1; 1186 htag = 0; 1187 } else { 1188 pptr->abort_pending = 1; 1189 } 1190 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1191 "%s: Bad SATA Status (tag 0x%x) %s on %s", 1192 __func__, htag, emsg, path); 1193 SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE); 1194 /* 1195 * Unlike SSP devices, we let the abort we 1196 * schedule above force the completion of 1197 * problem commands. 1198 */ 1199 if (pwrk) { 1200 mutex_exit(&pwrk->lock); 1201 } 1202 } else if (status == PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) { 1203 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, NULL, 1204 "%s: tag %x put onto the wire for %s", 1205 __func__, htag, path); 1206 if (pwrk) { 1207 pwrk->onwire = 1; 1208 mutex_exit(&pwrk->lock); 1209 } 1210 } 1211 1212 if (pptr) { 1213 pmcs_unlock_phy(pptr); 1214 } 1215 } 1216 1217 static void 1218 pmcs_process_abort_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) 1219 { 1220 pmcs_phy_t *pptr; 1221 struct pmcwork *pwrk; 1222 uint32_t htag = LE_32(((uint32_t *)iomb)[1]); 1223 uint32_t status = LE_32(((uint32_t *)iomb)[2]); 1224 uint32_t scp = LE_32(((uint32_t *)iomb)[3]) & 0x1; 1225 char *path; 1226 1227 pwrk = pmcs_tag2wp(pwp, htag); 1228 if (pwrk == NULL) { 1229 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1230 "%s: cannot find work structure for ABORT", __func__); 1231 return; 1232 } 1233 1234 pptr = pwrk->phy; 1235 if (pptr) { 1236 pmcs_lock_phy(pptr); 1237 pptr->abort_pending = 0; 1238 pptr->abort_sent = 0; 1239 1240 /* 1241 * Don't do this if the status was ABORT_IN_PROGRESS and 1242 * the scope bit was set 1243 */ 1244 if ((status != PMCOUT_STATUS_IO_ABORT_IN_PROGRESS) || !scp) { 1245 pptr->abort_all_start = 0; 1246 cv_signal(&pptr->abort_all_cv); 1247 } 1248 path = pptr->path; 1249 pmcs_unlock_phy(pptr); 1250 } else { 1251 path = "(no phy)"; 1252 } 1253 1254 switch (status) { 1255 case PMCOUT_STATUS_OK: 1256 if (scp) { 1257 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1258 "%s: abort all succeeded for %s. (htag=0x%x)", 1259 __func__, path, htag); 1260 } else { 1261 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1262 "%s: abort tag 0x%x succeeded for %s. (htag=0x%x)", 1263 __func__, pwrk->abt_htag, path, htag); 1264 } 1265 break; 1266 1267 case PMCOUT_STATUS_IO_NOT_VALID: 1268 if (scp) { 1269 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1270 "%s: ABORT %s failed (DEV NOT VALID) for %s. " 1271 "(htag=0x%x)", __func__, scp ? "all" : "tag", 1272 path, htag); 1273 } else { 1274 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1275 "%s: ABORT %s failed (I/O NOT VALID) for %s. " 1276 "(htag=0x%x)", __func__, scp ? "all" : "tag", 1277 path, htag); 1278 } 1279 break; 1280 1281 case PMCOUT_STATUS_IO_ABORT_IN_PROGRESS: 1282 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: ABORT %s failed " 1283 "for %s, htag 0x%x (ABORT IN PROGRESS)", __func__, 1284 scp ? "all" : "tag", path, htag); 1285 break; 1286 1287 default: 1288 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: Unknown status " 1289 "%d for ABORT %s, htag 0x%x, PHY %s", __func__, status, 1290 scp ? "all" : "tag", htag, path); 1291 break; 1292 } 1293 1294 pmcs_complete_work(pwp, pwrk, iomb, amt); 1295 } 1296 1297 static void 1298 pmcs_process_general_event(pmcs_hw_t *pwp, uint32_t *iomb) 1299 { 1300 uint32_t htag; 1301 char local[60]; 1302 struct pmcwork *pwrk; 1303 int i; 1304 1305 if (LE_32(iomb[1]) == INBOUND_IOMB_V_BIT_NOT_SET) { 1306 (void) snprintf(local, sizeof (local), 1307 "VALID bit not set on INBOUND IOMB"); 1308 } else if (LE_32(iomb[1]) == 1309 INBOUND_IOMB_OPC_NOT_SUPPORTED) { 1310 (void) snprintf(local, sizeof (local), 1311 "opcode not set on inbound IOMB"); 1312 } else { 1313 (void) snprintf(local, sizeof (local), 1314 "unknown GENERAL EVENT status (0x%x)", 1315 LE_32(iomb[1])); 1316 } 1317 /* Pull up bad IOMB into usual position */ 1318 for (i = 0; i < PMCS_MSG_SIZE - 2; i++) { 1319 iomb[i] = iomb[i+2]; 1320 } 1321 /* overwrite status with an error */ 1322 iomb[2] = LE_32(PMCOUT_STATUS_PROG_ERROR); 1323 iomb[PMCS_MSG_SIZE - 2] = 0; 1324 iomb[PMCS_MSG_SIZE - 1] = 0; 1325 htag = LE_32(iomb[1]); 1326 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, iomb); 1327 pwrk = pmcs_tag2wp(pwp, htag); 1328 if (pwrk) { 1329 pmcs_complete_work(pwp, pwrk, iomb, PMCS_QENTRY_SIZE); 1330 } 1331 } 1332 1333 void 1334 pmcs_general_intr(pmcs_hw_t *pwp) 1335 { 1336 char local[PMCS_QENTRY_SIZE << 1]; 1337 uint32_t w0, pi, ci; 1338 uint32_t *ptr, nbuf, lim = 0; 1339 size_t amt; 1340 1341 ci = pmcs_rd_oqci(pwp, PMCS_OQ_GENERAL); 1342 pi = pmcs_rd_oqpi(pwp, PMCS_OQ_GENERAL); 1343 1344 while (ci != pi) { 1345 OQLIM_CHECK(pwp, lim); 1346 ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, 0); 1347 w0 = LE_32(ptr[0]); 1348 VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi); 1349 WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_GENERAL); 1350 COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr, 1351 PMCS_OQ_GENERAL, ci); 1352 1353 switch (w0 & PMCS_IOMB_OPCODE_MASK) { 1354 case PMCOUT_SSP_COMPLETION: 1355 /* 1356 * We only get SSP completion here for Task Management 1357 * completions. 1358 */ 1359 case PMCOUT_SMP_COMPLETION: 1360 case PMCOUT_LOCAL_PHY_CONTROL: 1361 case PMCOUT_DEVICE_REGISTRATION: 1362 case PMCOUT_DEREGISTER_DEVICE_HANDLE: 1363 case PMCOUT_GET_NVMD_DATA: 1364 case PMCOUT_SET_NVMD_DATA: 1365 case PMCOUT_GET_DEVICE_STATE: 1366 case PMCOUT_SET_DEVICE_STATE: 1367 pmcs_process_completion(pwp, local, amt); 1368 break; 1369 case PMCOUT_SSP_ABORT: 1370 case PMCOUT_SATA_ABORT: 1371 case PMCOUT_SMP_ABORT: 1372 pmcs_process_abort_completion(pwp, local, amt); 1373 break; 1374 case PMCOUT_SSP_EVENT: 1375 pmcs_process_ssp_event(pwp, local, amt); 1376 break; 1377 case PMCOUT_ECHO: 1378 pmcs_process_echo_completion(pwp, local, amt); 1379 break; 1380 case PMCOUT_SAS_HW_EVENT_ACK_ACK: 1381 if (LE_32(ptr[2]) != SAS_HW_EVENT_ACK_OK) { 1382 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1383 "SAS H/W EVENT ACK/ACK Status=0x%b", 1384 LE_32(ptr[2]), "\020\4InvParm\3" 1385 "InvPort\2InvPhy\1InvSEA"); 1386 } 1387 pmcs_process_completion(pwp, local, amt); 1388 break; 1389 case PMCOUT_SKIP_ENTRIES: 1390 pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL, 1391 "%s: skip %d entries", __func__, nbuf); 1392 break; 1393 default: 1394 (void) snprintf(local, sizeof (local), 1395 "%s: unhandled message", __func__); 1396 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, ptr); 1397 break; 1398 } 1399 STEP_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, nbuf); 1400 } 1401 if (lim) { 1402 SYNC_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, pi); 1403 } 1404 } 1405 1406 /* 1407 * pmcs_check_intr_coal 1408 * 1409 * This function makes a determination on the dynamic value of the 1410 * interrupt coalescing timer register. We only use this for I/O 1411 * completions. 1412 * 1413 * The basic algorithm is as follows: 1414 * 1415 * PMCS_MAX_IO_COMPS_PER_INTR: The maximum number of I/O completions per 1416 * I/O completion interrupt. We won't increase the interrupt coalescing 1417 * timer if we're already processing this many completions per interrupt 1418 * beyond the threshold. 1419 * 1420 * Values in io_intr_coal structure: 1421 * 1422 * intr_latency: The average number of nsecs between interrupts during 1423 * the echo test. Used to help determine whether to increase the coalescing 1424 * timer. 1425 * 1426 * intr_threshold: Calculated number of interrupts beyond which we may 1427 * increase the timer. This value is calculated based on the calculated 1428 * interrupt latency during the ECHO test and the current value of the 1429 * coalescing timer. 1430 * 1431 * nsecs_between_intrs: Total number of nsecs between all the interrupts 1432 * in the current timeslice. 1433 * 1434 * last_io_comp: Time of the last I/O interrupt. 1435 * 1436 * num_io_completions: Number of I/O completions during the slice 1437 * 1438 * num_intrs: Number of I/O completion interrupts during the slice 1439 * 1440 * max_io_completions: Number of times we hit >= PMCS_MAX_IO_COMPS_PER_INTR 1441 * during interrupt processing. 1442 * 1443 * PMCS_MAX_IO_COMPS_LOWAT_SHIFT/HIWAT_SHIFT 1444 * Low and high marks used to determine whether we processed enough interrupts 1445 * that contained the maximum number of I/O completions to warrant increasing 1446 * the timer 1447 * 1448 * intr_coal_timer: The current value of the register (in usecs) 1449 * 1450 * timer_on: B_TRUE means we are using the timer 1451 * 1452 * The timer is increased if we processed more than intr_threshold interrupts 1453 * during the quantum and the number of interrupts containing the maximum 1454 * number of I/O completions is between PMCS_MAX_IO_COMPS_LOWAT_SHIFT and 1455 * _HIWAT_SHIFT 1456 * 1457 * If the average time between completions is greater than twice 1458 * the current timer value, the timer value is decreased. 1459 * 1460 * If we did not take any interrupts during a quantum, we turn the timer off. 1461 */ 1462 void 1463 pmcs_check_intr_coal(void *arg) 1464 { 1465 pmcs_hw_t *pwp = (pmcs_hw_t *)arg; 1466 uint32_t avg_nsecs; 1467 pmcs_io_intr_coal_t *ici; 1468 1469 ici = &pwp->io_intr_coal; 1470 mutex_enter(&pwp->ict_lock); 1471 1472 while (ici->stop_thread == B_FALSE) { 1473 /* 1474 * Wait for next time quantum... collect stats 1475 */ 1476 (void) cv_timedwait(&pwp->ict_cv, &pwp->ict_lock, 1477 ddi_get_lbolt() + ici->quantum); 1478 1479 if (ici->stop_thread == B_TRUE) { 1480 continue; 1481 } 1482 1483 DTRACE_PROBE1(pmcs__check__intr__coal, pmcs_io_intr_coal_t *, 1484 &pwp->io_intr_coal); 1485 1486 /* 1487 * Determine whether to adjust timer 1488 */ 1489 if (ici->num_intrs == 0) { 1490 /* 1491 * If timer is off, nothing more to do. 1492 */ 1493 if (!pwp->io_intr_coal.timer_on) { 1494 continue; 1495 } 1496 1497 /* 1498 * No interrupts. Turn off the timer. 1499 */ 1500 pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL, 0); 1501 1502 if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) { 1503 pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR, 1504 pwp->odb_auto_clear); 1505 } 1506 1507 ici->timer_on = B_FALSE; 1508 ici->max_io_completions = 0; 1509 ici->num_intrs = 0; 1510 ici->int_cleared = B_FALSE; 1511 ici->num_io_completions = 0; 1512 DTRACE_PROBE1(pmcs__intr__coalesce__timer__off, 1513 pmcs_io_intr_coal_t *, ici); 1514 continue; 1515 } 1516 1517 avg_nsecs = ici->nsecs_between_intrs / ici->num_intrs; 1518 1519 if ((ici->num_intrs > ici->intr_threshold) && 1520 (ici->max_io_completions > (ici->num_intrs >> 1521 PMCS_MAX_IO_COMPS_LOWAT_SHIFT)) && 1522 (ici->max_io_completions < (ici->num_intrs >> 1523 PMCS_MAX_IO_COMPS_HIWAT_SHIFT))) { 1524 pmcs_set_intr_coal_timer(pwp, INCREASE_TIMER); 1525 } else if (avg_nsecs > 1526 (ici->intr_coal_timer * 1000 * 2)) { 1527 pmcs_set_intr_coal_timer(pwp, DECREASE_TIMER); 1528 } 1529 1530 /* 1531 * Reset values for new sampling period. 1532 */ 1533 ici->max_io_completions = 0; 1534 ici->nsecs_between_intrs = 0; 1535 ici->num_intrs = 0; 1536 ici->num_io_completions = 0; 1537 1538 /* 1539 * If a firmware event log file is configured, check to see 1540 * if it needs to be written to the file. We do this here 1541 * because writing to a file from a callout thread (i.e. 1542 * from the watchdog timer) can cause livelocks. 1543 */ 1544 if (pwp->fwlog_file) { 1545 pmcs_gather_fwlog(pwp); 1546 } 1547 } 1548 1549 mutex_exit(&pwp->ict_lock); 1550 thread_exit(); 1551 } 1552 1553 void 1554 pmcs_iodone_intr(pmcs_hw_t *pwp) 1555 { 1556 char local[PMCS_QENTRY_SIZE << 1]; 1557 pmcs_iocomp_cb_t *ioccb; 1558 uint32_t w0, ci, pi, nbuf, lim = 0, niodone = 0, iomb_opcode; 1559 size_t amt; 1560 uint32_t *ptr; 1561 hrtime_t curtime = gethrtime(); 1562 1563 ci = pmcs_rd_oqci(pwp, PMCS_OQ_IODONE); 1564 pi = pmcs_rd_oqpi(pwp, PMCS_OQ_IODONE); 1565 1566 while (ci != pi) { 1567 OQLIM_CHECK(pwp, lim); 1568 ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, 0); 1569 w0 = LE_32(ptr[0]); 1570 VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi); 1571 WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_IODONE); 1572 iomb_opcode = (w0 & PMCS_IOMB_OPCODE_MASK); 1573 1574 if ((iomb_opcode == PMCOUT_SSP_COMPLETION) || 1575 (iomb_opcode == PMCOUT_SATA_COMPLETION)) { 1576 ioccb = 1577 kmem_cache_alloc(pwp->iocomp_cb_cache, KM_NOSLEEP); 1578 if (ioccb == NULL) { 1579 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 1580 "%s: kmem_cache_alloc failed", __func__); 1581 break; 1582 } 1583 1584 COPY_OUTBOUND(pwp, w0, ioccb->iomb, nbuf, amt, ptr, 1585 PMCS_OQ_IODONE, ci); 1586 1587 niodone++; 1588 pmcs_process_io_completion(pwp, ioccb, amt); 1589 } else { 1590 COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr, 1591 PMCS_OQ_IODONE, ci); 1592 1593 switch (iomb_opcode) { 1594 case PMCOUT_ECHO: 1595 pmcs_process_echo_completion(pwp, local, amt); 1596 break; 1597 case PMCOUT_SATA_EVENT: 1598 pmcs_process_sata_event(pwp, local, amt); 1599 break; 1600 case PMCOUT_SSP_EVENT: 1601 pmcs_process_ssp_event(pwp, local, amt); 1602 break; 1603 case PMCOUT_SKIP_ENTRIES: 1604 pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL, 1605 "%s: skip %d entries", __func__, nbuf); 1606 break; 1607 default: 1608 (void) snprintf(local, sizeof (local), 1609 "%s: unhandled message", __func__); 1610 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, 1611 ptr); 1612 break; 1613 } 1614 } 1615 1616 STEP_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, nbuf); 1617 } 1618 1619 if (lim != 0) { 1620 SYNC_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, pi); 1621 } 1622 1623 /* 1624 * Update the interrupt coalescing timer check stats and run 1625 * completions for queued up commands. 1626 */ 1627 1628 if (niodone > 0) { 1629 /* 1630 * If we can't get the lock, then completions are either 1631 * already running or will be scheduled to do so shortly. 1632 */ 1633 if (mutex_tryenter(&pwp->cq_lock) != 0) { 1634 PMCS_CQ_RUN_LOCKED(pwp); 1635 mutex_exit(&pwp->cq_lock); 1636 } 1637 1638 mutex_enter(&pwp->ict_lock); 1639 pwp->io_intr_coal.nsecs_between_intrs += 1640 curtime - pwp->io_intr_coal.last_io_comp; 1641 pwp->io_intr_coal.num_intrs++; 1642 pwp->io_intr_coal.num_io_completions += niodone; 1643 if (niodone >= PMCS_MAX_IO_COMPS_PER_INTR) { 1644 pwp->io_intr_coal.max_io_completions++; 1645 } 1646 pwp->io_intr_coal.last_io_comp = gethrtime(); 1647 mutex_exit(&pwp->ict_lock); 1648 } 1649 } 1650 1651 void 1652 pmcs_event_intr(pmcs_hw_t *pwp) 1653 { 1654 char local[PMCS_QENTRY_SIZE << 1]; 1655 uint32_t w0, ci, pi, nbuf, lim = 0; 1656 size_t amt; 1657 uint32_t *ptr; 1658 1659 ci = pmcs_rd_oqci(pwp, PMCS_OQ_EVENTS); 1660 pi = pmcs_rd_oqpi(pwp, PMCS_OQ_EVENTS); 1661 1662 while (ci != pi) { 1663 OQLIM_CHECK(pwp, lim); 1664 ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, 0); 1665 w0 = LE_32(ptr[0]); 1666 VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi); 1667 WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_EVENTS); 1668 COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr, 1669 PMCS_OQ_EVENTS, ci); 1670 1671 switch (w0 & PMCS_IOMB_OPCODE_MASK) { 1672 case PMCOUT_ECHO: 1673 pmcs_process_echo_completion(pwp, local, amt); 1674 break; 1675 case PMCOUT_SATA_EVENT: 1676 pmcs_process_sata_event(pwp, local, amt); 1677 break; 1678 case PMCOUT_SSP_EVENT: 1679 pmcs_process_ssp_event(pwp, local, amt); 1680 break; 1681 case PMCOUT_GENERAL_EVENT: 1682 pmcs_process_general_event(pwp, ptr); 1683 break; 1684 case PMCOUT_DEVICE_HANDLE_REMOVED: 1685 { 1686 uint32_t port = IOP_EVENT_PORTID(LE_32(ptr[1])); 1687 uint32_t did = LE_32(ptr[2]); 1688 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1689 "PortID 0x%x device_id 0x%x removed", port, did); 1690 break; 1691 } 1692 case PMCOUT_SAS_HW_EVENT: 1693 if (nbuf > 1) { 1694 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 1695 "multiple SAS HW_EVENT (%d) responses " 1696 "in EVENT OQ", nbuf); 1697 } 1698 pmcs_process_sas_hw_event(pwp, local, PMCS_QENTRY_SIZE); 1699 break; 1700 case PMCOUT_FW_FLASH_UPDATE: 1701 case PMCOUT_GET_TIME_STAMP: 1702 case PMCOUT_GET_DEVICE_STATE: 1703 case PMCOUT_SET_DEVICE_STATE: 1704 case PMCOUT_SAS_DIAG_EXECUTE: 1705 pmcs_process_completion(pwp, local, amt); 1706 break; 1707 case PMCOUT_SKIP_ENTRIES: 1708 pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL, 1709 "%s: skip %d entries", __func__, nbuf); 1710 break; 1711 default: 1712 (void) snprintf(local, sizeof (local), 1713 "%s: unhandled message", __func__); 1714 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, ptr); 1715 break; 1716 } 1717 STEP_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, nbuf); 1718 } 1719 if (lim) { 1720 SYNC_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, pi); 1721 } 1722 } 1723 1724 void 1725 pmcs_timed_out(pmcs_hw_t *pwp, uint32_t htag, const char *func) 1726 { 1727 #ifdef DEBUG 1728 hrtime_t now = gethrtime(); 1729 int i; 1730 1731 for (i = 0; i < 256; i++) { 1732 if (pwp->ftags[i] == htag) { 1733 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1734 "Inbound msg (tag 0x%8x) timed out - " 1735 "was started %llu ns ago in %s:%d", 1736 htag, (unsigned long long) (now - pwp->ftime[i]), 1737 func, pwp->ftag_lines[i]); 1738 return; 1739 } 1740 } 1741 #endif 1742 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1743 "Inbound Message (tag 0x%08x) timed out- was started in %s", 1744 htag, func); 1745 } 1746