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