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