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