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; 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 phy_id = (uint64_t)af.phy_identifier; 361 362 /* 363 * Check to see if there is a PortID already active. 364 */ 365 if (rp) { 366 if (rp->portid != portid) { 367 pmcs_unlock_phy(pptr); 368 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 369 "PortID 0x%x: PHY 0x%x SAS LINK UP IS FOR " 370 "A DIFFERENT PORTID 0x%x", rp->portid, 371 phynum, portid); 372 break; 373 } 374 375 /* 376 * If the dtype isn't NOTHING, then this is actually 377 * the primary PHY for this port. It probably went 378 * down and came back up, so be sure not to mark it 379 * as a subsidiary. 380 */ 381 if (pptr->dtype == NOTHING) { 382 pptr->subsidiary = 1; 383 } 384 pptr->link_rate = 385 pmcs_link_rate(IOP_EVENT_LINK_RATE(w1)); 386 pptr->portid = portid; 387 pptr->dead = 0; 388 pmcs_unlock_phy(pptr); 389 390 rp->width = IOP_EVENT_NPIP(w3); 391 392 /* Add this PHY to the phymap */ 393 if (sas_phymap_phy_add(pwp->hss_phymap, phynum, 394 pwp->sas_wwns[0], 395 pmcs_barray2wwn(pptr->sas_address)) != 396 DDI_SUCCESS) { 397 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 398 "Unable to add phy %u for 0x%" PRIx64 ".0x%" 399 PRIx64, phynum, pwp->sas_wwns[rp->phynum], 400 pmcs_barray2wwn(pptr->sas_address)); 401 } 402 403 /* 404 * Get our iport, if attached, and set it up. Update 405 * the PHY's phymask props while we're locked. 406 */ 407 pmcs_lock_phy(pptr); 408 pmcs_update_phy_pm_props(pptr, (1ULL << phynum), 409 (1ULL << phy_id), B_TRUE); 410 iport = pmcs_get_iport_by_phy(pwp, pptr); 411 pmcs_unlock_phy(pptr); 412 if (iport) { 413 primary = !pptr->subsidiary; 414 415 mutex_enter(&iport->lock); 416 if (primary) { 417 iport->pptr = pptr; 418 } 419 if (iport->ua_state == UA_ACTIVE) { 420 pmcs_add_phy_to_iport(iport, pptr); 421 pptr->iport = iport; 422 } 423 mutex_exit(&iport->lock); 424 pmcs_rele_iport(iport); 425 } 426 427 pmcs_update_phy_pm_props(rp, (1ULL << phynum), 428 (1ULL << phy_id), B_TRUE); 429 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 430 "PortID 0x%x: PHY 0x%x SAS LINK UP WIDENS PORT " 431 "TO %d PHYS", portid, phynum, rp->width); 432 433 break; 434 } 435 436 /* 437 * Check to see if anything is here already 438 */ 439 if (pptr->dtype != NOTHING && pptr->configured) { 440 pmcs_unlock_phy(pptr); 441 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 442 "PortID 0x%x: SAS PHY 0x%x UP HITS EXISTING " 443 "CONFIGURED TREE", portid, phynum); 444 break; 445 } 446 447 if (af.address_frame_type != SAS_AF_IDENTIFY) { 448 pmcs_unlock_phy(pptr); 449 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 450 "SAS link up on phy 0x%x, " 451 "but unexpected frame type 0x%x found", phynum, 452 af.address_frame_type); 453 break; 454 } 455 pptr->width = IOP_EVENT_NPIP(w3); 456 pptr->portid = portid; 457 pptr->dead = 0; 458 pptr->link_rate = pmcs_link_rate(IOP_EVENT_LINK_RATE(w1)); 459 460 /* 461 * Check to see whether this is an expander or an endpoint 462 */ 463 switch (af.device_type) { 464 case SAS_IF_DTYPE_ENDPOINT: 465 pptr->pend_dtype = SAS; 466 pptr->dtype = SAS; 467 break; 468 case SAS_IF_DTYPE_EDGE: 469 case SAS_IF_DTYPE_FANOUT: 470 pptr->pend_dtype = EXPANDER; 471 pptr->dtype = EXPANDER; 472 break; 473 default: 474 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 475 "unknown device type 0x%x", af.device_type); 476 pptr->pend_dtype = NOTHING; 477 pptr->dtype = NOTHING; 478 break; 479 } 480 481 /* 482 * If this is a direct-attached SAS drive, do the spinup 483 * release now. 484 */ 485 if (pptr->dtype == SAS) { 486 pptr->spinup_hold = 1; 487 pmcs_spinup_release(pwp, pptr); 488 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, pptr, NULL, 489 "Release spinup hold on PHY 0x%x", phynum); 490 } 491 492 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 493 if (pptr->width > 1) { 494 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 495 "PortID 0x%x: PHY 0x%x SAS" 496 " LINK UP @ %s Gb with %d phys/s", portid, phynum, 497 pmcs_get_rate(pptr->link_rate), pptr->width); 498 } else { 499 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 500 "PortID 0x%x: PHY 0x%x SAS" 501 " LINK UP @ %s Gb/s", portid, phynum, 502 pmcs_get_rate(pptr->link_rate)); 503 } 504 pmcs_unlock_phy(pptr); 505 506 /* Add this PHY to the phymap */ 507 if (sas_phymap_phy_add(pwp->hss_phymap, phynum, 508 pwp->sas_wwns[0], 509 pmcs_barray2wwn(pptr->sas_address)) != DDI_SUCCESS) { 510 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 511 "Unable to add phy %u for 0x%" PRIx64 ".0x%" 512 PRIx64, phynum, pwp->sas_wwns[pptr->phynum], 513 pmcs_barray2wwn(pptr->sas_address)); 514 } 515 516 /* Get a pointer to our iport and set it up if attached */ 517 pmcs_lock_phy(pptr); 518 iport = pmcs_get_iport_by_phy(pwp, pptr); 519 pmcs_unlock_phy(pptr); 520 if (iport) { 521 primary = !pptr->subsidiary; 522 523 mutex_enter(&iport->lock); 524 if (primary) { 525 iport->pptr = pptr; 526 } 527 if (iport->ua_state == UA_ACTIVE) { 528 pmcs_add_phy_to_iport(iport, pptr); 529 pptr->iport = iport; 530 } 531 mutex_exit(&iport->lock); 532 pmcs_rele_iport(iport); 533 } 534 535 pmcs_lock_phy(pptr); 536 pmcs_update_phy_pm_props(pptr, (1ULL << phynum), 537 (1ULL << phy_id), B_TRUE); 538 pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT, 539 SAS_PHY_ONLINE, pptr); 540 pmcs_unlock_phy(pptr); 541 542 mutex_enter(&pwp->lock); 543 pwp->ports[portid] = pptr; 544 mutex_exit(&pwp->lock); 545 RESTART_DISCOVERY(pwp); 546 547 break; 548 } 549 case IOP_EVENT_SATA_PHY_UP: 550 /* 551 * If we're not at running state, don't do anything 552 */ 553 mutex_enter(&pwp->lock); 554 if (pwp->state != STATE_RUNNING) { 555 mutex_exit(&pwp->lock); 556 break; 557 } 558 559 /* 560 * Check to see if anything is here already 561 */ 562 pmcs_lock_phy(pwp->root_phys + phynum); 563 pptr = pwp->root_phys + phynum; 564 mutex_exit(&pwp->lock); 565 566 if (pptr->dtype != NOTHING && pptr->configured) { 567 pmcs_unlock_phy(pptr); 568 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 569 "PortID 0x%x: SATA PHY 0x%x" 570 " UP HITS EXISTING CONFIGURED TREE", 571 portid, phynum); 572 break; 573 } 574 575 pptr->width = 1; 576 pptr->dead = 0; 577 578 /* 579 * Install the PHY number in the least significant byte 580 * with a NAA=3 (locally assigned address) in the most 581 * significant nubble. 582 * 583 * Later, we'll either use that or dig a 584 * WWN out of words 108..111. 585 */ 586 pptr->sas_address[0] = 0x30; 587 pptr->sas_address[1] = 0; 588 pptr->sas_address[2] = 0; 589 pptr->sas_address[3] = 0; 590 pptr->sas_address[4] = 0; 591 pptr->sas_address[5] = 0; 592 pptr->sas_address[6] = 0; 593 pptr->sas_address[7] = phynum; 594 pptr->portid = portid; 595 pptr->link_rate = pmcs_link_rate(IOP_EVENT_LINK_RATE(w1)); 596 pptr->dtype = SATA; 597 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 598 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 599 "PortID 0x%x: PHY 0x%x SATA LINK UP @ %s Gb/s", 600 pptr->portid, phynum, pmcs_get_rate(pptr->link_rate)); 601 pmcs_unlock_phy(pptr); 602 603 /* Add this PHY to the phymap */ 604 if (sas_phymap_phy_add(pwp->hss_phymap, phynum, 605 pwp->sas_wwns[0], 606 pmcs_barray2wwn(pptr->sas_address)) != DDI_SUCCESS) { 607 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 608 "Unable to add phy %u for 0x%" PRIx64 ".0x%" 609 PRIx64, phynum, pwp->sas_wwns[pptr->phynum], 610 pmcs_barray2wwn(pptr->sas_address)); 611 } 612 613 /* Get our iport, if attached, and set it up */ 614 pmcs_lock_phy(pptr); 615 iport = pmcs_get_iport_by_phy(pwp, pptr); 616 pmcs_unlock_phy(pptr); 617 if (iport) { 618 mutex_enter(&iport->lock); 619 iport->pptr = pptr; 620 if (iport->ua_state == UA_ACTIVE) { 621 pmcs_add_phy_to_iport(iport, pptr); 622 pptr->iport = iport; 623 ASSERT(iport->nphy == 1); 624 iport->nphy = 1; 625 } 626 mutex_exit(&iport->lock); 627 pmcs_rele_iport(iport); 628 } 629 630 pmcs_lock_phy(pptr); 631 pmcs_update_phy_pm_props(pptr, (1ULL << phynum), 1ULL, B_TRUE); 632 pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT, 633 SAS_PHY_ONLINE, pptr); 634 pmcs_unlock_phy(pptr); 635 636 mutex_enter(&pwp->lock); 637 pwp->ports[pptr->portid] = pptr; 638 mutex_exit(&pwp->lock); 639 RESTART_DISCOVERY(pwp); 640 break; 641 642 case IOP_EVENT_SATA_SPINUP_HOLD: 643 tphyp = (pmcs_phy_t *)(pwp->root_phys + phynum); 644 /* 645 * No need to lock the entire tree for this 646 */ 647 mutex_enter(&tphyp->phy_lock); 648 tphyp->spinup_hold = 1; 649 pmcs_spinup_release(pwp, tphyp); 650 mutex_exit(&tphyp->phy_lock); 651 break; 652 case IOP_EVENT_PHY_DOWN: 653 /* 654 * If we're not at running state, don't do anything 655 */ 656 mutex_enter(&pwp->lock); 657 if (pwp->state != STATE_RUNNING) { 658 mutex_exit(&pwp->lock); 659 break; 660 } 661 pptr = pwp->ports[portid]; 662 663 subphy = pwp->root_phys + phynum; 664 /* 665 * subphy is a pointer to the PHY corresponding to the incoming 666 * event. pptr points to the primary PHY for the corresponding 667 * port. So, subphy and pptr may or may not be the same PHY, 668 * but that doesn't change what we need to do with each. 669 */ 670 ASSERT(subphy); 671 mutex_exit(&pwp->lock); 672 673 if (pptr == NULL) { 674 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 675 "PortID 0x%x: PHY 0x%x LINK DOWN- no portid ptr", 676 portid, phynum); 677 break; 678 } 679 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_NIL) { 680 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 681 "PortID 0x%x: PHY 0x%x NOT VALID YET", 682 portid, phynum); 683 need_ack = 1; 684 break; 685 } 686 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_IN_RESET) { 687 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 688 "PortID 0x%x: PHY 0x%x IN RESET", 689 portid, phynum); 690 /* Entire port is down due to a host-initiated reset */ 691 mutex_enter(&pptr->phy_lock); 692 /* Clear the phymask props in pptr */ 693 pmcs_update_phy_pm_props(pptr, pptr->att_port_pm_tmp, 694 pptr->tgt_port_pm_tmp, B_FALSE); 695 iport = pptr->iport; 696 mutex_exit(&pptr->phy_lock); 697 if (iport) { 698 mutex_enter(&iport->lock); 699 pmcs_iport_teardown_phys(iport); 700 mutex_exit(&iport->lock); 701 } 702 703 /* Clear down all PHYs in the port */ 704 for (pptr = pwp->root_phys; pptr; 705 pptr = pptr->sibling) { 706 pmcs_lock_phy(pptr); 707 if (pptr->portid == portid) { 708 pptr->dtype = NOTHING; 709 pptr->portid = 710 PMCS_IPORT_INVALID_PORT_ID; 711 if (pptr->valid_device_id) { 712 pptr->deregister_wait = 1; 713 } 714 } 715 pmcs_unlock_phy(pptr); 716 SCHEDULE_WORK(pwp, PMCS_WORK_DEREGISTER_DEV); 717 (void) ddi_taskq_dispatch(pwp->tq, pmcs_worker, 718 pwp, DDI_NOSLEEP); 719 } 720 721 break; 722 } 723 724 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_LOSTCOMM) { 725 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 726 "PortID 0x%x: PHY 0x%x TEMPORARILY DOWN", 727 portid, phynum); 728 need_ack = 1; 729 break; 730 } 731 732 if (IOP_EVENT_PORT_STATE(w3) == IOP_EVENT_PS_VALID) { 733 /* 734 * This is not the last phy in the port, so if this 735 * is the primary PHY, promote another PHY to primary. 736 */ 737 if (pptr == subphy) { 738 primary = !subphy->subsidiary; 739 ASSERT(primary); 740 741 tphyp = pptr; 742 pptr = pmcs_promote_next_phy(tphyp); 743 744 if (pptr) { 745 /* Update primary pptr in ports */ 746 pwp->ports[portid] = pptr; 747 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, 748 NULL, "PortID 0x%x: PHY 0x%x " 749 "promoted to primary", portid, 750 pptr->phynum); 751 } else { 752 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, 753 NULL, "PortID 0x%x: PHY 0x%x: " 754 "unable to promote phy", portid, 755 phynum); 756 } 757 } 758 759 /* 760 * Drop port width on the primary phy handle 761 * No need to lock the entire tree for this 762 */ 763 mutex_enter(&pptr->phy_lock); 764 pmcs_update_phy_pm_props(pptr, subphy->att_port_pm_tmp, 765 subphy->tgt_port_pm_tmp, B_FALSE); 766 pptr->width = IOP_EVENT_NPIP(w3); 767 mutex_exit(&pptr->phy_lock); 768 769 /* Clear the iport reference and portid on the subphy */ 770 mutex_enter(&subphy->phy_lock); 771 iport = subphy->iport; 772 subphy->iport = NULL; 773 subphy->portid = PMCS_PHY_INVALID_PORT_ID; 774 subphy->dtype = NOTHING; 775 mutex_exit(&subphy->phy_lock); 776 777 /* 778 * If the iport was set on this phy, decrement its 779 * nphy count and remove this phy from the phys list. 780 */ 781 if (iport) { 782 mutex_enter(&iport->lock); 783 if (iport->ua_state == UA_ACTIVE) { 784 pmcs_remove_phy_from_iport(iport, 785 subphy); 786 } 787 mutex_exit(&iport->lock); 788 } 789 790 pmcs_lock_phy(subphy); 791 if (subphy->subsidiary) 792 pmcs_clear_phy(pwp, subphy); 793 pmcs_unlock_phy(subphy); 794 795 /* Remove this PHY from the phymap */ 796 if (sas_phymap_phy_rem(pwp->hss_phymap, phynum) != 797 DDI_SUCCESS) { 798 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 799 "Unable to remove phy %u for 0x%" PRIx64 800 ".0x%" PRIx64, phynum, 801 pwp->sas_wwns[pptr->phynum], 802 pmcs_barray2wwn((pwp->root_phys + 803 pptr->phynum)-> sas_address)); 804 } 805 806 pmcs_prt(pwp, PMCS_PRT_INFO, pptr, NULL, 807 "PortID 0x%x: PHY 0x%x LINK DOWN NARROWS PORT " 808 "TO %d PHYS", portid, phynum, pptr->width); 809 break; 810 } 811 if (IOP_EVENT_PORT_STATE(w3) != IOP_EVENT_PS_INVALID) { 812 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 813 "PortID 0x%x: PHY 0x%x LINK DOWN NOT HANDLED " 814 "(state 0x%x)", portid, phynum, 815 IOP_EVENT_PORT_STATE(w3)); 816 need_ack = 1; 817 break; 818 } 819 /* Remove this PHY from the phymap */ 820 if (sas_phymap_phy_rem(pwp->hss_phymap, phynum) != 821 DDI_SUCCESS) { 822 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 823 "Unable to remove phy %u for 0x%" PRIx64 824 ".0x%" PRIx64, phynum, 825 pwp->sas_wwns[pptr->phynum], 826 pmcs_barray2wwn( 827 (pwp->root_phys + pptr->phynum)->sas_address)); 828 } 829 830 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 831 "PortID 0x%x: PHY 0x%x LINK DOWN (port invalid)", 832 portid, phynum); 833 834 /* 835 * Last PHY on the port. 836 * Assumption: pptr and subphy are both "valid". In fact, 837 * they should be one and the same. 838 * 839 * Drop port width on the primary phy handle 840 * Report the event and clear its PHY pm props while we've 841 * got the lock 842 */ 843 ASSERT(pptr == subphy); 844 mutex_enter(&pptr->phy_lock); 845 pptr->width = 0; 846 pmcs_update_phy_pm_props(pptr, pptr->att_port_pm_tmp, 847 pptr->tgt_port_pm_tmp, B_FALSE); 848 pmcs_smhba_log_sysevent(pwp, ESC_SAS_PHY_EVENT, 849 SAS_PHY_OFFLINE, pptr); 850 mutex_exit(&pptr->phy_lock); 851 852 /* Clear the iport reference and portid on the subphy */ 853 pmcs_lock_phy(subphy); 854 iport = subphy->iport; 855 subphy->deregister_wait = 1; 856 subphy->iport = NULL; 857 subphy->portid = PMCS_PHY_INVALID_PORT_ID; 858 subphy->dtype = NOTHING; 859 pmcs_unlock_phy(subphy); 860 SCHEDULE_WORK(pwp, PMCS_WORK_DEREGISTER_DEV); 861 (void) ddi_taskq_dispatch(pwp->tq, pmcs_worker, 862 pwp, DDI_NOSLEEP); 863 864 /* 865 * If the iport was set on this phy, decrement its 866 * nphy count and remove this phy from the phys list. 867 * Also, clear the iport's pptr as this port is now 868 * down. 869 */ 870 if (iport) { 871 mutex_enter(&iport->lock); 872 if (iport->ua_state == UA_ACTIVE) { 873 pmcs_remove_phy_from_iport(iport, subphy); 874 iport->pptr = NULL; 875 iport->ua_state = UA_PEND_DEACTIVATE; 876 } 877 mutex_exit(&iport->lock); 878 } 879 880 pmcs_lock_phy(subphy); 881 if (subphy->subsidiary) 882 pmcs_clear_phy(pwp, subphy); 883 pmcs_unlock_phy(subphy); 884 885 /* 886 * Since we're now really dead, it's time to clean up. 887 */ 888 pmcs_kill_port(pwp, portid); 889 need_ack = 1; 890 891 break; 892 case IOP_EVENT_BROADCAST_CHANGE: 893 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 894 "PortID 0x%x: PHY 0x%x Broadcast Change", portid, phynum); 895 need_ack = 1; 896 mutex_enter(&pwp->lock); 897 pptr = pwp->ports[portid]; 898 if (pptr) { 899 pmcs_lock_phy(pptr); 900 if (pptr->phynum == phynum) { 901 pmcs_set_changed(pwp, pptr, B_TRUE, 0); 902 } 903 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 904 SAS_PORT_BROADCAST_CHANGE, pptr); 905 pmcs_unlock_phy(pptr); 906 } 907 mutex_exit(&pwp->lock); 908 RESTART_DISCOVERY(pwp); 909 break; 910 case IOP_EVENT_BROADCAST_SES: 911 EVT_PRT(pwp, IOP_EVENT_BROADCAST_SES, phynum); 912 mutex_enter(&pwp->lock); 913 pptr = pwp->ports[portid]; 914 mutex_exit(&pwp->lock); 915 if (pptr) { 916 pmcs_lock_phy(pptr); 917 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 918 SAS_PORT_BROADCAST_SES, pptr); 919 pmcs_unlock_phy(pptr); 920 } 921 break; 922 case IOP_EVENT_PHY_ERR_INBOUND_CRC: 923 { 924 char buf[32]; 925 (void) snprintf(buf, sizeof (buf), "Inbound PHY CRC error"); 926 need_ack = 1; 927 break; 928 } 929 case IOP_EVENT_HARD_RESET_RECEIVED: 930 EVT_PRT(pwp, IOP_EVENT_HARD_RESET_RECEIVED, phynum); 931 break; 932 case IOP_EVENT_EVENT_ID_FRAME_TIMO: 933 EVT_PRT(pwp, IOP_EVENT_EVENT_ID_FRAME_TIMO, phynum); 934 break; 935 case IOP_EVENT_BROADCAST_EXP: 936 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 937 "PortID 0x%x: PHY 0x%x Broadcast Exp Change", 938 portid, phynum); 939 /* 940 * Comparing Section 6.8.1.4 of SMHBA (rev 7) spec and Section 941 * 7.2.3 of SAS2 (Rev 15) spec, 942 * _BROADCAST_EXPANDER event corresponds to _D01_4 primitive 943 */ 944 mutex_enter(&pwp->lock); 945 pptr = pwp->ports[portid]; 946 mutex_exit(&pwp->lock); 947 if (pptr) { 948 pmcs_lock_phy(pptr); 949 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 950 SAS_PORT_BROADCAST_D01_4, pptr); 951 pmcs_unlock_phy(pptr); 952 } 953 break; 954 case IOP_EVENT_PHY_START_STATUS: 955 switch (IOP_EVENT_STATUS(w1)) { 956 case IOP_PHY_START_OK: 957 pmcs_prt(pwp, PMCS_PRT_DEBUG_CONFIG, NULL, NULL, 958 "PHY 0x%x Started", phynum); 959 break; 960 case IOP_PHY_START_ALREADY: 961 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 962 "PHY 0x%x Started (Already)", phynum); 963 break; 964 case IOP_PHY_START_INVALID: 965 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 966 "PHY 0x%x failed to start (invalid phy)", phynum); 967 break; 968 case IOP_PHY_START_ERROR: 969 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 970 "PHY 0x%x Start Error", phynum); 971 break; 972 default: 973 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 974 "PHY 0x%x failed to start (0x%x)", phynum, 975 IOP_EVENT_STATUS(w1)); 976 break; 977 } 978 /* Reposition htag to the 'expected' position. */ 979 ((uint32_t *)iomb)[1] = ((uint32_t *)iomb)[2]; 980 pmcs_process_completion(pwp, iomb, amt); 981 break; 982 case IOP_EVENT_PHY_ERR_INVALID_DWORD: 983 need_ack = 1; 984 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_INVALID_DWORD, phynum); 985 break; 986 case IOP_EVENT_PHY_ERR_DISPARITY_ERROR: 987 need_ack = 1; 988 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_DISPARITY_ERROR, phynum); 989 break; 990 case IOP_EVENT_PHY_ERR_CODE_VIOLATION: 991 need_ack = 1; 992 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_CODE_VIOLATION, phynum); 993 break; 994 case IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN: 995 need_ack = 1; 996 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_LOSS_OF_DWORD_SYN, phynum); 997 break; 998 case IOP_EVENT_PHY_ERR_PHY_RESET_FAILD: 999 need_ack = 1; 1000 EVT_PRT(pwp, IOP_EVENT_PHY_ERR_PHY_RESET_FAILD, phynum); 1001 break; 1002 case IOP_EVENT_PORT_RECOVERY_TIMER_TMO: 1003 EVT_PRT(pwp, IOP_EVENT_PORT_RECOVERY_TIMER_TMO, phynum); 1004 break; 1005 case IOP_EVENT_PORT_RECOVER: 1006 EVT_PRT(pwp, IOP_EVENT_PORT_RECOVER, phynum); 1007 break; 1008 case IOP_EVENT_PORT_INVALID: 1009 mutex_enter(&pwp->lock); 1010 if (pwp->state != STATE_RUNNING) { 1011 mutex_exit(&pwp->lock); 1012 break; 1013 } 1014 mutex_exit(&pwp->lock); 1015 pmcs_kill_port(pwp, portid); 1016 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 1017 "PortID 0x%x: PORT Now Invalid", portid); 1018 break; 1019 case IOP_EVENT_PORT_RESET_TIMER_TMO: 1020 EVT_PRT(pwp, IOP_EVENT_PORT_RESET_TIMER_TMO, phynum); 1021 break; 1022 case IOP_EVENT_PORT_RESET_COMPLETE: 1023 EVT_PRT(pwp, IOP_EVENT_PORT_RESET_COMPLETE, phynum); 1024 break; 1025 case IOP_EVENT_BROADCAST_ASYNC_EVENT: 1026 EVT_PRT(pwp, IOP_EVENT_BROADCAST_ASYNC_EVENT, phynum); 1027 /* 1028 * Comparing Section 6.8.1.4 of SMHBA (rev 7) spec and Section 1029 * 7.2.3 of SAS2 (Rev 15) spec, 1030 * _BROADCAST_ASYNC event corresponds to _D04_7 primitive 1031 */ 1032 mutex_enter(&pwp->lock); 1033 pptr = pwp->ports[portid]; 1034 mutex_exit(&pwp->lock); 1035 if (pptr) { 1036 pmcs_lock_phy(pptr); 1037 pmcs_smhba_log_sysevent(pwp, ESC_SAS_HBA_PORT_BROADCAST, 1038 SAS_PORT_BROADCAST_D04_7, pptr); 1039 pmcs_unlock_phy(pptr); 1040 } 1041 break; 1042 default: 1043 (void) snprintf(buf, sizeof (buf), 1044 "unknown SAS H/W Event PHY 0x%x", phynum); 1045 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb); 1046 break; 1047 } 1048 if (need_ack) { 1049 mutex_enter(&pwp->lock); 1050 /* 1051 * Don't lock the entire tree for this. Just grab the mutex 1052 * on the root PHY. 1053 */ 1054 tphyp = pwp->root_phys + phynum; 1055 mutex_enter(&tphyp->phy_lock); 1056 tphyp->hw_event_ack = w1; 1057 mutex_exit(&tphyp->phy_lock); 1058 mutex_exit(&pwp->lock); 1059 pmcs_ack_events(pwp); 1060 } 1061 } 1062 1063 static void 1064 pmcs_process_echo_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) 1065 { 1066 echo_test_t fred; 1067 pmcwork_t *pwrk; 1068 uint32_t *msg = iomb, htag = LE_32(msg[1]); 1069 pwrk = pmcs_tag2wp(pwp, htag); 1070 if (pwrk) { 1071 (void) memcpy(&fred, &((uint32_t *)iomb)[2], sizeof (fred)); 1072 fred.ptr[0]++; 1073 msg[2] = LE_32(PMCOUT_STATUS_OK); 1074 pmcs_complete_work(pwp, pwrk, msg, amt); 1075 } else { 1076 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, 1077 "ECHO completion with no work structure", iomb); 1078 } 1079 } 1080 1081 static void 1082 pmcs_process_ssp_event(pmcs_hw_t *pwp, void *iomb, size_t amt) 1083 { 1084 _NOTE(ARGUNUSED(amt)); 1085 uint32_t status, htag, *w; 1086 pmcwork_t *pwrk; 1087 pmcs_phy_t *phyp = NULL; 1088 char *path; 1089 1090 w = iomb; 1091 htag = LE_32(w[1]); 1092 status = LE_32(w[2]); 1093 1094 1095 pwrk = pmcs_tag2wp(pwp, htag); 1096 if (pwrk == NULL) { 1097 path = "????"; 1098 } else { 1099 phyp = pwrk->phy; 1100 path = pwrk->phy->path; 1101 } 1102 1103 if (status != PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) { 1104 char buf[20]; 1105 const char *emsg = pmcs_status_str(status); 1106 1107 if (emsg == NULL) { 1108 (void) snprintf(buf, sizeof (buf), "Status 0x%x", 1109 status); 1110 emsg = buf; 1111 } 1112 pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, NULL, "%s: Bad SAS Status " 1113 "(tag 0x%x) %s on %s", __func__, htag, emsg, path); 1114 if (pwrk != NULL) { 1115 /* 1116 * There may be pending command on a target device. 1117 * Or, it may be a double fault. 1118 */ 1119 pmcs_start_ssp_event_recovery(pwp, pwrk, iomb, amt); 1120 } 1121 } else { 1122 pmcs_prt(pwp, PMCS_PRT_DEBUG2, phyp, NULL, 1123 "%s: tag %x put onto the wire for %s", 1124 __func__, htag, path); 1125 if (pwrk) { 1126 pwrk->onwire = 1; 1127 mutex_exit(&pwrk->lock); 1128 } 1129 } 1130 } 1131 1132 static void 1133 pmcs_process_sata_event(pmcs_hw_t *pwp, void *iomb, size_t amt) 1134 { 1135 _NOTE(ARGUNUSED(amt)); 1136 pmcwork_t *pwrk = NULL; 1137 pmcs_phy_t *pptr; 1138 uint32_t status, htag, *w; 1139 char *path; 1140 1141 w = iomb; 1142 htag = LE_32(w[1]); 1143 status = LE_32(w[2]); 1144 1145 /* 1146 * If the status is PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE, 1147 * we have to issue a READ LOG EXT ATA (page 0x10) command 1148 * to the device. In this case, htag is not valid. 1149 * 1150 * If the status is PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED, we're 1151 * just noting that an I/O got put onto the wire. 1152 * 1153 * Othewise, other errors are indicative that things need to 1154 * be aborted. 1155 */ 1156 path = NULL; 1157 if (htag) { 1158 pwrk = pmcs_tag2wp(pwp, htag); 1159 if (pwrk) { 1160 pmcs_lock_phy(pwrk->phy); 1161 pptr = pwrk->phy; 1162 path = pptr->path; 1163 } 1164 } 1165 if (path == NULL) { 1166 mutex_enter(&pwp->lock); 1167 pptr = pmcs_find_phy_by_devid(pwp, LE_32(w[4])); 1168 /* This PHY is now locked */ 1169 mutex_exit(&pwp->lock); 1170 if (pptr) { 1171 path = pptr->path; 1172 } else { 1173 path = "????"; 1174 } 1175 } 1176 1177 if (status != PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) { 1178 char buf[20]; 1179 const char *emsg = pmcs_status_str(status); 1180 1181 ASSERT(pptr != NULL); 1182 if (emsg == NULL) { 1183 (void) snprintf(buf, sizeof (buf), "Status 0x%x", 1184 status); 1185 emsg = buf; 1186 } 1187 if (status == PMCOUT_STATUS_XFER_ERROR_ABORTED_NCQ_MODE) { 1188 ASSERT(pptr != NULL); 1189 pptr->need_rl_ext = 1; 1190 htag = 0; 1191 } else { 1192 pptr->abort_pending = 1; 1193 } 1194 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1195 "%s: Bad SATA Status (tag 0x%x) %s on %s", 1196 __func__, htag, emsg, path); 1197 SCHEDULE_WORK(pwp, PMCS_WORK_ABORT_HANDLE); 1198 /* 1199 * Unlike SSP devices, we let the abort we 1200 * schedule above force the completion of 1201 * problem commands. 1202 */ 1203 if (pwrk) { 1204 mutex_exit(&pwrk->lock); 1205 } 1206 } else if (status == PMCOUT_STATUS_XFER_CMD_FRAME_ISSUED) { 1207 pmcs_prt(pwp, PMCS_PRT_DEBUG2, pptr, NULL, 1208 "%s: tag %x put onto the wire for %s", 1209 __func__, htag, path); 1210 if (pwrk) { 1211 pwrk->onwire = 1; 1212 mutex_exit(&pwrk->lock); 1213 } 1214 } 1215 1216 if (pptr) { 1217 pmcs_unlock_phy(pptr); 1218 } 1219 } 1220 1221 static void 1222 pmcs_process_abort_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) 1223 { 1224 pmcs_phy_t *pptr; 1225 struct pmcwork *pwrk; 1226 uint32_t htag = LE_32(((uint32_t *)iomb)[1]); 1227 uint32_t status = LE_32(((uint32_t *)iomb)[2]); 1228 uint32_t scp = LE_32(((uint32_t *)iomb)[3]) & 0x1; 1229 char *path; 1230 1231 pwrk = pmcs_tag2wp(pwp, htag); 1232 if (pwrk == NULL) { 1233 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1234 "%s: cannot find work structure for ABORT", __func__); 1235 return; 1236 } 1237 1238 pptr = pwrk->phy; 1239 if (pptr) { 1240 pmcs_lock_phy(pptr); 1241 pptr->abort_pending = 0; 1242 pptr->abort_sent = 0; 1243 1244 /* 1245 * Don't do this if the status was ABORT_IN_PROGRESS and 1246 * the scope bit was set 1247 */ 1248 if ((status != PMCOUT_STATUS_IO_ABORT_IN_PROGRESS) || !scp) { 1249 pptr->abort_all_start = 0; 1250 cv_signal(&pptr->abort_all_cv); 1251 } 1252 path = pptr->path; 1253 pmcs_unlock_phy(pptr); 1254 } else { 1255 path = "(no phy)"; 1256 } 1257 1258 switch (status) { 1259 case PMCOUT_STATUS_OK: 1260 if (scp) { 1261 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1262 "%s: abort all succeeded for %s. (htag=0x%x)", 1263 __func__, path, htag); 1264 } else { 1265 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1266 "%s: abort tag 0x%x succeeded for %s. (htag=0x%x)", 1267 __func__, pwrk->abt_htag, path, htag); 1268 } 1269 break; 1270 1271 case PMCOUT_STATUS_IO_NOT_VALID: 1272 if (scp) { 1273 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1274 "%s: ABORT %s failed (DEV NOT VALID) for %s. " 1275 "(htag=0x%x)", __func__, scp ? "all" : "tag", 1276 path, htag); 1277 } else { 1278 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, 1279 "%s: ABORT %s failed (I/O NOT VALID) for %s. " 1280 "(htag=0x%x)", __func__, scp ? "all" : "tag", 1281 path, htag); 1282 } 1283 break; 1284 1285 case PMCOUT_STATUS_IO_ABORT_IN_PROGRESS: 1286 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: ABORT %s failed " 1287 "for %s, htag 0x%x (ABORT IN PROGRESS)", __func__, 1288 scp ? "all" : "tag", path, htag); 1289 break; 1290 1291 default: 1292 pmcs_prt(pwp, PMCS_PRT_DEBUG, pptr, NULL, "%s: Unknown status " 1293 "%d for ABORT %s, htag 0x%x, PHY %s", __func__, status, 1294 scp ? "all" : "tag", htag, path); 1295 break; 1296 } 1297 1298 pmcs_complete_work(pwp, pwrk, iomb, amt); 1299 } 1300 1301 static void 1302 pmcs_process_general_event(pmcs_hw_t *pwp, uint32_t *iomb) 1303 { 1304 uint32_t htag; 1305 char local[60]; 1306 struct pmcwork *pwrk; 1307 int i; 1308 1309 if (LE_32(iomb[1]) == INBOUND_IOMB_V_BIT_NOT_SET) { 1310 (void) snprintf(local, sizeof (local), 1311 "VALID bit not set on INBOUND IOMB"); 1312 } else if (LE_32(iomb[1]) == 1313 INBOUND_IOMB_OPC_NOT_SUPPORTED) { 1314 (void) snprintf(local, sizeof (local), 1315 "opcode not set on inbound IOMB"); 1316 } else { 1317 (void) snprintf(local, sizeof (local), 1318 "unknown GENERAL EVENT status (0x%x)", 1319 LE_32(iomb[1])); 1320 } 1321 /* Pull up bad IOMB into usual position */ 1322 for (i = 0; i < PMCS_MSG_SIZE - 2; i++) { 1323 iomb[i] = iomb[i+2]; 1324 } 1325 /* overwrite status with an error */ 1326 iomb[2] = LE_32(PMCOUT_STATUS_PROG_ERROR); 1327 iomb[PMCS_MSG_SIZE - 2] = 0; 1328 iomb[PMCS_MSG_SIZE - 1] = 0; 1329 htag = LE_32(iomb[1]); 1330 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, iomb); 1331 pwrk = pmcs_tag2wp(pwp, htag); 1332 if (pwrk) { 1333 pmcs_complete_work(pwp, pwrk, iomb, PMCS_QENTRY_SIZE); 1334 } 1335 } 1336 1337 void 1338 pmcs_general_intr(pmcs_hw_t *pwp) 1339 { 1340 char local[PMCS_QENTRY_SIZE << 1]; 1341 uint32_t w0, pi, ci; 1342 uint32_t *ptr, nbuf, lim = 0; 1343 size_t amt; 1344 1345 ci = pmcs_rd_oqci(pwp, PMCS_OQ_GENERAL); 1346 pi = pmcs_rd_oqpi(pwp, PMCS_OQ_GENERAL); 1347 1348 while (ci != pi) { 1349 OQLIM_CHECK(pwp, lim); 1350 ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, 0); 1351 w0 = LE_32(ptr[0]); 1352 VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi); 1353 WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_GENERAL); 1354 COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr, 1355 PMCS_OQ_GENERAL, ci); 1356 1357 switch (w0 & PMCS_IOMB_OPCODE_MASK) { 1358 case PMCOUT_SSP_COMPLETION: 1359 /* 1360 * We only get SSP completion here for Task Management 1361 * completions. 1362 */ 1363 case PMCOUT_SMP_COMPLETION: 1364 case PMCOUT_LOCAL_PHY_CONTROL: 1365 case PMCOUT_DEVICE_REGISTRATION: 1366 case PMCOUT_DEREGISTER_DEVICE_HANDLE: 1367 case PMCOUT_GET_NVMD_DATA: 1368 case PMCOUT_SET_NVMD_DATA: 1369 case PMCOUT_GET_DEVICE_STATE: 1370 case PMCOUT_SET_DEVICE_STATE: 1371 pmcs_process_completion(pwp, local, amt); 1372 break; 1373 case PMCOUT_SSP_ABORT: 1374 case PMCOUT_SATA_ABORT: 1375 case PMCOUT_SMP_ABORT: 1376 pmcs_process_abort_completion(pwp, local, amt); 1377 break; 1378 case PMCOUT_SSP_EVENT: 1379 pmcs_process_ssp_event(pwp, local, amt); 1380 break; 1381 case PMCOUT_ECHO: 1382 pmcs_process_echo_completion(pwp, local, amt); 1383 break; 1384 case PMCOUT_SAS_HW_EVENT_ACK_ACK: 1385 if (LE_32(ptr[2]) != SAS_HW_EVENT_ACK_OK) { 1386 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1387 "SAS H/W EVENT ACK/ACK Status=0x%b", 1388 LE_32(ptr[2]), "\020\4InvParm\3" 1389 "InvPort\2InvPhy\1InvSEA"); 1390 } 1391 pmcs_process_completion(pwp, local, amt); 1392 break; 1393 case PMCOUT_SKIP_ENTRIES: 1394 pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL, 1395 "%s: skip %d entries", __func__, nbuf); 1396 break; 1397 default: 1398 (void) snprintf(local, sizeof (local), 1399 "%s: unhandled message", __func__); 1400 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, ptr); 1401 break; 1402 } 1403 STEP_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, nbuf); 1404 } 1405 if (lim) { 1406 SYNC_OQ_ENTRY(pwp, PMCS_OQ_GENERAL, ci, pi); 1407 } 1408 } 1409 1410 /* 1411 * pmcs_check_intr_coal 1412 * 1413 * This function makes a determination on the dynamic value of the 1414 * interrupt coalescing timer register. We only use this for I/O 1415 * completions. 1416 * 1417 * The basic algorithm is as follows: 1418 * 1419 * PMCS_MAX_IO_COMPS_PER_INTR: The maximum number of I/O completions per 1420 * I/O completion interrupt. We won't increase the interrupt coalescing 1421 * timer if we're already processing this many completions per interrupt 1422 * beyond the threshold. 1423 * 1424 * Values in io_intr_coal structure: 1425 * 1426 * intr_latency: The average number of nsecs between interrupts during 1427 * the echo test. Used to help determine whether to increase the coalescing 1428 * timer. 1429 * 1430 * intr_threshold: Calculated number of interrupts beyond which we may 1431 * increase the timer. This value is calculated based on the calculated 1432 * interrupt latency during the ECHO test and the current value of the 1433 * coalescing timer. 1434 * 1435 * nsecs_between_intrs: Total number of nsecs between all the interrupts 1436 * in the current timeslice. 1437 * 1438 * last_io_comp: Time of the last I/O interrupt. 1439 * 1440 * num_io_completions: Number of I/O completions during the slice 1441 * 1442 * num_intrs: Number of I/O completion interrupts during the slice 1443 * 1444 * max_io_completions: Number of times we hit >= PMCS_MAX_IO_COMPS_PER_INTR 1445 * during interrupt processing. 1446 * 1447 * PMCS_MAX_IO_COMPS_LOWAT_SHIFT/HIWAT_SHIFT 1448 * Low and high marks used to determine whether we processed enough interrupts 1449 * that contained the maximum number of I/O completions to warrant increasing 1450 * the timer 1451 * 1452 * intr_coal_timer: The current value of the register (in usecs) 1453 * 1454 * timer_on: B_TRUE means we are using the timer 1455 * 1456 * The timer is increased if we processed more than intr_threshold interrupts 1457 * during the quantum and the number of interrupts containing the maximum 1458 * number of I/O completions is between PMCS_MAX_IO_COMPS_LOWAT_SHIFT and 1459 * _HIWAT_SHIFT 1460 * 1461 * If the average time between completions is greater than twice 1462 * the current timer value, the timer value is decreased. 1463 * 1464 * If we did not take any interrupts during a quantum, we turn the timer off. 1465 */ 1466 void 1467 pmcs_check_intr_coal(void *arg) 1468 { 1469 pmcs_hw_t *pwp = (pmcs_hw_t *)arg; 1470 uint32_t avg_nsecs; 1471 pmcs_io_intr_coal_t *ici; 1472 1473 ici = &pwp->io_intr_coal; 1474 mutex_enter(&pwp->ict_lock); 1475 1476 while (ici->stop_thread == B_FALSE) { 1477 /* 1478 * Wait for next time quantum... collect stats 1479 */ 1480 (void) cv_timedwait(&pwp->ict_cv, &pwp->ict_lock, 1481 ddi_get_lbolt() + ici->quantum); 1482 1483 if (ici->stop_thread == B_TRUE) { 1484 continue; 1485 } 1486 1487 DTRACE_PROBE1(pmcs__check__intr__coal, pmcs_io_intr_coal_t *, 1488 &pwp->io_intr_coal); 1489 1490 /* 1491 * Determine whether to adjust timer 1492 */ 1493 if (ici->num_intrs == 0) { 1494 /* 1495 * If timer is off, nothing more to do. 1496 */ 1497 if (!pwp->io_intr_coal.timer_on) { 1498 continue; 1499 } 1500 1501 /* 1502 * No interrupts. Turn off the timer. 1503 */ 1504 pmcs_wr_topunit(pwp, PMCS_INT_COALESCING_CONTROL, 0); 1505 1506 if (pwp->odb_auto_clear & (1 << PMCS_MSIX_IODONE)) { 1507 pmcs_wr_topunit(pwp, PMCS_OBDB_AUTO_CLR, 1508 pwp->odb_auto_clear); 1509 } 1510 1511 ici->timer_on = B_FALSE; 1512 ici->max_io_completions = 0; 1513 ici->num_intrs = 0; 1514 ici->int_cleared = B_FALSE; 1515 ici->num_io_completions = 0; 1516 DTRACE_PROBE1(pmcs__intr__coalesce__timer__off, 1517 pmcs_io_intr_coal_t *, ici); 1518 continue; 1519 } 1520 1521 avg_nsecs = ici->nsecs_between_intrs / ici->num_intrs; 1522 1523 if ((ici->num_intrs > ici->intr_threshold) && 1524 (ici->max_io_completions > (ici->num_intrs >> 1525 PMCS_MAX_IO_COMPS_LOWAT_SHIFT)) && 1526 (ici->max_io_completions < (ici->num_intrs >> 1527 PMCS_MAX_IO_COMPS_HIWAT_SHIFT))) { 1528 pmcs_set_intr_coal_timer(pwp, INCREASE_TIMER); 1529 } else if (avg_nsecs > 1530 (ici->intr_coal_timer * 1000 * 2)) { 1531 pmcs_set_intr_coal_timer(pwp, DECREASE_TIMER); 1532 } 1533 1534 /* 1535 * Reset values for new sampling period. 1536 */ 1537 ici->max_io_completions = 0; 1538 ici->nsecs_between_intrs = 0; 1539 ici->num_intrs = 0; 1540 ici->num_io_completions = 0; 1541 } 1542 1543 mutex_exit(&pwp->ict_lock); 1544 thread_exit(); 1545 } 1546 1547 void 1548 pmcs_iodone_intr(pmcs_hw_t *pwp) 1549 { 1550 char local[PMCS_QENTRY_SIZE << 1]; 1551 pmcs_iocomp_cb_t *ioccb; 1552 uint32_t w0, ci, pi, nbuf, lim = 0, niodone = 0, iomb_opcode; 1553 size_t amt; 1554 uint32_t *ptr; 1555 hrtime_t curtime = gethrtime(); 1556 1557 ci = pmcs_rd_oqci(pwp, PMCS_OQ_IODONE); 1558 pi = pmcs_rd_oqpi(pwp, PMCS_OQ_IODONE); 1559 1560 while (ci != pi) { 1561 OQLIM_CHECK(pwp, lim); 1562 ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, 0); 1563 w0 = LE_32(ptr[0]); 1564 VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi); 1565 WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_IODONE); 1566 iomb_opcode = (w0 & PMCS_IOMB_OPCODE_MASK); 1567 1568 if ((iomb_opcode == PMCOUT_SSP_COMPLETION) || 1569 (iomb_opcode == PMCOUT_SATA_COMPLETION)) { 1570 ioccb = 1571 kmem_cache_alloc(pwp->iocomp_cb_cache, KM_NOSLEEP); 1572 if (ioccb == NULL) { 1573 pmcs_prt(pwp, PMCS_PRT_WARN, NULL, NULL, 1574 "%s: kmem_cache_alloc failed", __func__); 1575 break; 1576 } 1577 1578 COPY_OUTBOUND(pwp, w0, ioccb->iomb, nbuf, amt, ptr, 1579 PMCS_OQ_IODONE, ci); 1580 1581 niodone++; 1582 pmcs_process_io_completion(pwp, ioccb, amt); 1583 } else { 1584 COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr, 1585 PMCS_OQ_IODONE, ci); 1586 1587 switch (iomb_opcode) { 1588 case PMCOUT_ECHO: 1589 pmcs_process_echo_completion(pwp, local, amt); 1590 break; 1591 case PMCOUT_SATA_EVENT: 1592 pmcs_process_sata_event(pwp, local, amt); 1593 break; 1594 case PMCOUT_SSP_EVENT: 1595 pmcs_process_ssp_event(pwp, local, amt); 1596 break; 1597 case PMCOUT_SKIP_ENTRIES: 1598 pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL, 1599 "%s: skip %d entries", __func__, nbuf); 1600 break; 1601 default: 1602 (void) snprintf(local, sizeof (local), 1603 "%s: unhandled message", __func__); 1604 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, 1605 ptr); 1606 break; 1607 } 1608 } 1609 1610 STEP_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, nbuf); 1611 } 1612 1613 if (lim != 0) { 1614 SYNC_OQ_ENTRY(pwp, PMCS_OQ_IODONE, ci, pi); 1615 } 1616 1617 /* 1618 * Update the interrupt coalescing timer check stats and run 1619 * completions for queued up commands. 1620 */ 1621 1622 if (niodone > 0) { 1623 /* 1624 * If we can't get the lock, then completions are either 1625 * already running or will be scheduled to do so shortly. 1626 */ 1627 if (mutex_tryenter(&pwp->cq_lock) != 0) { 1628 PMCS_CQ_RUN_LOCKED(pwp); 1629 mutex_exit(&pwp->cq_lock); 1630 } 1631 1632 mutex_enter(&pwp->ict_lock); 1633 pwp->io_intr_coal.nsecs_between_intrs += 1634 curtime - pwp->io_intr_coal.last_io_comp; 1635 pwp->io_intr_coal.num_intrs++; 1636 pwp->io_intr_coal.num_io_completions += niodone; 1637 if (niodone >= PMCS_MAX_IO_COMPS_PER_INTR) { 1638 pwp->io_intr_coal.max_io_completions++; 1639 } 1640 pwp->io_intr_coal.last_io_comp = gethrtime(); 1641 mutex_exit(&pwp->ict_lock); 1642 } 1643 } 1644 1645 void 1646 pmcs_event_intr(pmcs_hw_t *pwp) 1647 { 1648 char local[PMCS_QENTRY_SIZE << 1]; 1649 uint32_t w0, ci, pi, nbuf, lim = 0; 1650 size_t amt; 1651 uint32_t *ptr; 1652 1653 ci = pmcs_rd_oqci(pwp, PMCS_OQ_EVENTS); 1654 pi = pmcs_rd_oqpi(pwp, PMCS_OQ_EVENTS); 1655 1656 while (ci != pi) { 1657 OQLIM_CHECK(pwp, lim); 1658 ptr = GET_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, 0); 1659 w0 = LE_32(ptr[0]); 1660 VALID_IOMB_CHECK(pwp, w0, ptr, ci, pi); 1661 WRONG_OBID_CHECK(pwp, w0, PMCS_OQ_EVENTS); 1662 COPY_OUTBOUND(pwp, w0, local, nbuf, amt, ptr, 1663 PMCS_OQ_EVENTS, ci); 1664 1665 switch (w0 & PMCS_IOMB_OPCODE_MASK) { 1666 case PMCOUT_ECHO: 1667 pmcs_process_echo_completion(pwp, local, amt); 1668 break; 1669 case PMCOUT_SATA_EVENT: 1670 pmcs_process_sata_event(pwp, local, amt); 1671 break; 1672 case PMCOUT_SSP_EVENT: 1673 pmcs_process_ssp_event(pwp, local, amt); 1674 break; 1675 case PMCOUT_GENERAL_EVENT: 1676 pmcs_process_general_event(pwp, ptr); 1677 break; 1678 case PMCOUT_DEVICE_HANDLE_REMOVED: 1679 { 1680 uint32_t port = IOP_EVENT_PORTID(LE_32(ptr[1])); 1681 uint32_t did = LE_32(ptr[2]); 1682 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1683 "PortID 0x%x device_id 0x%x removed", port, did); 1684 break; 1685 } 1686 case PMCOUT_SAS_HW_EVENT: 1687 if (nbuf > 1) { 1688 pmcs_prt(pwp, PMCS_PRT_INFO, NULL, NULL, 1689 "multiple SAS HW_EVENT (%d) responses " 1690 "in EVENT OQ", nbuf); 1691 } 1692 pmcs_process_sas_hw_event(pwp, local, PMCS_QENTRY_SIZE); 1693 break; 1694 case PMCOUT_FW_FLASH_UPDATE: 1695 case PMCOUT_GET_TIME_STAMP: 1696 case PMCOUT_GET_DEVICE_STATE: 1697 case PMCOUT_SET_DEVICE_STATE: 1698 case PMCOUT_SAS_DIAG_EXECUTE: 1699 pmcs_process_completion(pwp, local, amt); 1700 break; 1701 case PMCOUT_SKIP_ENTRIES: 1702 pmcs_prt(pwp, PMCS_PRT_DEBUG3, NULL, NULL, 1703 "%s: skip %d entries", __func__, nbuf); 1704 break; 1705 default: 1706 (void) snprintf(local, sizeof (local), 1707 "%s: unhandled message", __func__); 1708 pmcs_print_entry(pwp, PMCS_PRT_DEBUG, local, ptr); 1709 break; 1710 } 1711 STEP_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, nbuf); 1712 } 1713 if (lim) { 1714 SYNC_OQ_ENTRY(pwp, PMCS_OQ_EVENTS, ci, pi); 1715 } 1716 } 1717 1718 void 1719 pmcs_timed_out(pmcs_hw_t *pwp, uint32_t htag, const char *func) 1720 { 1721 #ifdef DEBUG 1722 hrtime_t now = gethrtime(); 1723 int i; 1724 1725 for (i = 0; i < 256; i++) { 1726 if (pwp->ftags[i] == htag) { 1727 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1728 "Inbound msg (tag 0x%8x) timed out - " 1729 "was started %llu ns ago in %s:%d", 1730 htag, (unsigned long long) (now - pwp->ftime[i]), 1731 func, pwp->ftag_lines[i]); 1732 return; 1733 } 1734 } 1735 #endif 1736 pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, 1737 "Inbound Message (tag 0x%08x) timed out- was started in %s", 1738 htag, func); 1739 } 1740