summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_attach.c6
-rw-r--r--usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_fwlog.c23
-rw-r--r--usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_intr.c16
-rw-r--r--usr/src/uts/common/io/scsi/adapters/pmcs/pmcs_scsa.c87
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_def.h2
-rw-r--r--usr/src/uts/common/sys/scsi/adapters/pmcs/pmcs_mpi.h15
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 */