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