diff options
Diffstat (limited to 'usr/src')
6 files changed, 106 insertions, 43 deletions
diff --git a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c index dd71db017b..08d4e892db 100644 --- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c +++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c @@ -1778,6 +1778,12 @@ pmcs_worker(void *arg) work_flags = atomic_swap_ulong(&pwp->work_flags, 0); + if (work_flags & PMCS_WORK_FLAG_DUMP_REGS) { + mutex_enter(&pwp->lock); + pmcs_register_dump_int(pwp); + mutex_exit(&pwp->lock); + } + if (work_flags & PMCS_WORK_FLAG_SAS_HW_ACK) { pmcs_ack_events(pwp); } diff --git a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c index 9fc98e4fbc..201cd7235f 100644 --- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c +++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c @@ -89,6 +89,14 @@ pmcs_register_dump_int(pmcs_hw_t *pwp) n = pmcs_dump_ioqs(pwp, buf, size_left); ASSERT(size_left >= n); buf += n; size_left -= n; + + if (pwp->state == STATE_DEAD) { + pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, + "%s: HBA dead, skipping AAP1/IOP registers and event logs", + __func__); + goto skip_logs; + } + mutex_exit(&pwp->lock); slice = (PMCS_REGISTER_DUMP_FLASH_SIZE / PMCS_FLASH_CHUNK_SIZE); n = snprintf(buf, size_left, "\nDump AAP1 register: \n" @@ -194,6 +202,7 @@ pmcs_register_dump_int(pmcs_hw_t *pwp) } mutex_enter(&pwp->lock); +skip_logs: n = pmcs_dump_gsm_addiregs(pwp, buf, size_left); ASSERT(size_left >= n); buf += n; size_left -= n; @@ -500,14 +509,12 @@ pmcs_dump_mpi_table(pmcs_hw_t *pwp, caddr_t buf, uint32_t size_left) (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SSP_TENQ + (woff << 2)) >> shf) & 0xff); } - for (uint8_t i = 0; i < pwp->nphy; i++) { - uint32_t woff = i / 4; - uint32_t shf = (i % 4) * 8; - n += snprintf(&buf[n], (size_left - n), "SMP Target " - "Event Notification Queue - PHY ID %d = 0x%02x\n", i, - (pmcs_rd_mpi_tbl(pwp, PMCS_MPI_SMP_TENQ + - (woff << 2)) >> shf) & 0xff); - } + + n += snprintf(&buf[n], (size_left - n), "I/O Abort Delay = 0x%04x\n", + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_IOABTDLY) & 0xffff); + n += snprintf(&buf[n], (size_left - n), + "Customization Setting = 0x%08x\n", + pmcs_rd_mpi_tbl(pwp, PMCS_MPI_CUSTSET)); n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address " "Higher = 0x%08x\n", pmcs_rd_mpi_tbl(pwp, PMCS_MPI_MELBAH)); n += snprintf(&buf[n], (size_left - n), "MSGU Event Log Buffer Address " diff --git a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_intr.c b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_intr.c index 4dd3d396eb..d870649a6d 100644 --- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_intr.c +++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_intr.c @@ -131,7 +131,7 @@ pmcs_work_not_found(pmcs_hw_t *pwp, uint32_t htag, uint32_t *iomb) (void) snprintf(buf, sizeof (buf), "unable to find work structure for tag 0x%x", htag); - pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb); + pmcs_print_entry(pwp, PMCS_PRT_DEBUG1, buf, iomb); if (htag == 0) { return; } @@ -139,12 +139,12 @@ pmcs_work_not_found(pmcs_hw_t *pwp, uint32_t htag, uint32_t *iomb) for (i = 0; i < 256; i++) { mutex_enter(&pwp->dbglock); if (pwp->ltags[i] == htag) { - pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, + pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL, "same tag already completed (%llu us ago)", (unsigned long long) (now - pwp->ltime[i])); } if (pwp->ftags[i] == htag) { - pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, + pmcs_prt(pwp, PMCS_PRT_DEBUG1, NULL, NULL, "same tag started (line %d) (%llu ns ago)", pwp->ftag_lines[i], (unsigned long long) (now - pwp->ftime[i])); @@ -155,7 +155,7 @@ pmcs_work_not_found(pmcs_hw_t *pwp, uint32_t htag, uint32_t *iomb) char buf[64]; (void) snprintf(buf, sizeof (buf), "unable to find work structure for tag 0x%x", htag); - pmcs_print_entry(pwp, PMCS_PRT_DEBUG, buf, iomb); + pmcs_print_entry(pwp, PMCS_PRT_DEBUG1, buf, iomb); #endif } @@ -1233,7 +1233,11 @@ pmcs_process_abort_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) pptr = pwrk->phy; if (pptr) { - pmcs_lock_phy(pptr); + /* + * Don't use pmcs_lock_phy here since it could potentially lock + * other PHYs beneath, which is unnecessary in this context. + */ + mutex_enter(&pptr->phy_lock); pptr->abort_pending = 0; pptr->abort_sent = 0; @@ -1246,7 +1250,7 @@ pmcs_process_abort_completion(pmcs_hw_t *pwp, void *iomb, size_t amt) cv_signal(&pptr->abort_all_cv); } path = pptr->path; - pmcs_unlock_phy(pptr); + mutex_exit(&pptr->phy_lock); } else { path = "(no phy)"; } diff --git a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_scsa.c b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_scsa.c index f9a729ba5c..53ca13b670 100644 --- a/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_scsa.c +++ b/usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_scsa.c @@ -1597,10 +1597,16 @@ pmcs_scsa_wq_run_one(pmcs_hw_t *pwp, pmcs_xscsi_t *xp) while ((sp = STAILQ_FIRST(&xp->wq)) != NULL) { pwrk = pmcs_gwork(pwp, PMCS_TAG_TYPE_CBACK, phyp); if (pwrk == NULL) { - pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, - "%s: out of work structures", __func__); + mutex_exit(&xp->wqlock); + mutex_enter(&pwp->lock); + if (pwp->resource_limited == 0) { + pmcs_prt(pwp, PMCS_PRT_DEBUG, NULL, NULL, + "%s: out of work structures", __func__); + } + pwp->resource_limited = 1; SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES); - break; + mutex_exit(&pwp->lock); + return (B_FALSE); } STAILQ_REMOVE_HEAD(&xp->wq, cmd_next); mutex_exit(&xp->wqlock); @@ -1694,9 +1700,21 @@ pmcs_scsa_wq_run(pmcs_hw_t *pwp) } while (target != target_start); if (rval) { + /* + * If we were resource limited, but apparently are not now, + * reschedule the work queues anyway. + */ + if (pwp->resource_limited) { + SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES); + } pwp->resource_limited = 0; /* Not resource-constrained */ } else { - pwp->resource_limited = 1; /* Give others a chance */ + /* + * Give everybody a chance, and reschedule to run the queues + * again as long as we're limited. + */ + pwp->resource_limited = 1; + SCHEDULE_WORK(pwp, PMCS_WORK_RUN_QUEUES); } pwp->last_wq_dev = target; @@ -2163,15 +2181,6 @@ pmcs_SAS_done(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *msg) out: pmcs_dma_unload(pwp, sp); - - /* - * If the status is other than OK, determine if it's something that - * is worth re-attempting enumeration. If so, mark the PHY. - */ - if (sts != PMCOUT_STATUS_OK) { - pmcs_status_disposition(pptr, sts); - } - mutex_enter(&xp->statlock); /* @@ -2218,6 +2227,15 @@ out: } } mutex_exit(&xp->statlock); + + /* + * If the status is other than OK, determine if it's something that + * is worth re-attempting enumeration. If so, mark the PHY. + */ + if (sts != PMCOUT_STATUS_OK) { + pmcs_status_disposition(pptr, sts); + } + if (dead == 0) { #ifdef DEBUG pmcs_cmd_t *wp; @@ -2645,15 +2663,6 @@ pmcs_SATA_done(pmcs_hw_t *pwp, pmcwork_t *pwrk, uint32_t *msg) out: pmcs_dma_unload(pwp, sp); - - /* - * If the status is other than OK, determine if it's something that - * is worth re-attempting enumeration. If so, mark the PHY. - */ - if (sts != PMCOUT_STATUS_OK) { - pmcs_status_disposition(pptr, sts); - } - mutex_enter(&xp->statlock); xp->tagmap &= ~(1 << sp->cmd_satltag); @@ -2699,6 +2708,14 @@ out: } mutex_exit(&xp->statlock); + /* + * If the status is other than OK, determine if it's something that + * is worth re-attempting enumeration. If so, mark the PHY. + */ + if (sts != PMCOUT_STATUS_OK) { + pmcs_status_disposition(pptr, sts); + } + if (dead == 0) { #ifdef DEBUG pmcs_cmd_t *wp; @@ -3072,10 +3089,10 @@ pmcs_set_resid(struct scsi_pkt *pkt, size_t amt, uint32_t cdbamt) } /* - * Return the existing target softstate if there is one. If there is, - * the PHY is locked as well and that lock must be freed by the caller - * after the target/PHY linkage is established. If there isn't one, and - * alloc_tgt is TRUE, then allocate one. + * Return the existing target softstate (unlocked) if there is one. If so, + * the PHY is locked and that lock must be freed by the caller after the + * target/PHY linkage is established. If there isn't one, and alloc_tgt is + * TRUE, then allocate one. */ pmcs_xscsi_t * pmcs_get_target(pmcs_iport_t *iport, char *tgt_port, boolean_t alloc_tgt) @@ -3100,6 +3117,7 @@ pmcs_get_target(pmcs_iport_t *iport, char *tgt_port, boolean_t alloc_tgt) tgt = ddi_soft_state_bystr_get(iport->tgt_sstate, tgt_port); if (tgt) { + mutex_enter(&tgt->statlock); /* * There's already a target. Check its PHY pointer to see * if we need to clear the old linkages @@ -3115,8 +3133,25 @@ pmcs_get_target(pmcs_iport_t *iport, char *tgt_port, boolean_t alloc_tgt) tgt->phy->target = NULL; } + /* + * If this target has no PHY pointer and alloc_tgt is FALSE, + * that implies we expect the target to already exist. This + * implies that there has already been a tran_tgt_init on at + * least one LU. + */ + if ((tgt->phy == NULL) && !alloc_tgt) { + pmcs_prt(pwp, PMCS_PRT_DEBUG, phyp, tgt, + "%s: Establish linkage from new PHY to old target @" + "%s", __func__, tgt->unit_address); + for (int idx = 0; idx < tgt->ref_count; idx++) { + pmcs_inc_phy_ref_count(phyp); + } + } + tgt->phy = phyp; phyp->target = tgt; + + mutex_exit(&tgt->statlock); return (tgt); } diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h index 88dbfca412..2f53f8d485 100644 --- a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h +++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h @@ -282,6 +282,7 @@ typedef struct { #define PMCS_WORK_DS_ERR_RECOVERY 9 #define PMCS_WORK_SSP_EVT_RECOVERY 10 #define PMCS_WORK_DEREGISTER_DEV 11 +#define PMCS_WORK_DUMP_REGS 12 /* * The actual values as they appear in work_flags @@ -296,6 +297,7 @@ typedef struct { #define PMCS_WORK_FLAG_DS_ERR_RECOVERY (1 << 9) #define PMCS_WORK_FLAG_SSP_EVT_RECOVERY (1 << 10) #define PMCS_WORK_FLAG_DEREGISTER_DEV (1 << 11) +#define PMCS_WORK_FLAG_DUMP_REGS (1 << 12) /* * This structure is used by this function to test MPI (and interrupts) diff --git a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h index b0c875e871..1c4b0fa4e1 100644 --- a/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h +++ b/usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h @@ -19,7 +19,7 @@ * CDDL HEADER END * * - * Copyright 2009 Sun Microsystems, Inc. All rights reserved. + * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* @@ -115,9 +115,17 @@ extern "C" { #define PMCS_MPI_SSP_TENQ PMCS_DWRD(0x10) /* - * SMP Target Event Notification Queue + * I/O Abort Delay */ -#define PMCS_MPI_SMP_TENQ PMCS_DWRD(0x12) +#define PMCS_MPI_IOABTDLY PMCS_DWRD(0x12) + +/* + * Customization Setting + */ +#define PMCS_MPI_CUSTSET PMCS_DWRD(0x13) + +#define PMCS_MPI_CUST_HW_RSC_BSY_ALT 0x1 /* Bit 0 */ +#define PMCS_MPI_CUST_ABORT_ITNL 0x2 /* Bit 1 */ /* * This specifies a log buffer in host memory for the MSGU. @@ -140,6 +148,7 @@ extern "C" { */ #define PMCS_MPI_FERR PMCS_DWRD(0x1C) #define PMCS_FERRIE 0x1 /* Fatal Err Interrupt Enable */ +#define PMCS_PCAD64 0x2 /* PI/CI addresses are 64-bit */ #define PMCS_FERIV_MASK 0xff00 /* Fatal Err Interrupt Mask */ #define PMCS_FERIV_SHIFT 8 /* Fatal Err Interrupt Shift */ |