summaryrefslogtreecommitdiff
path: root/usr/src/uts
diff options
context:
space:
mode:
authorStephen Hanson <Stephen.Hanson@Sun.COM>2010-04-09 02:48:25 -0700
committerStephen Hanson <Stephen.Hanson@Sun.COM>2010-04-09 02:48:25 -0700
commitbf002425f517afdc1d8b6a9602e59910eeee05aa (patch)
tree00eb38800c281e0718b3b0f7ce9515482dc2cf20 /usr/src/uts
parent44ed9dbbfa620821ecf59a131462082f628dd0f3 (diff)
downloadillumos-joyent-bf002425f517afdc1d8b6a9602e59910eeee05aa.tar.gz
6909799 io retire agent mistakenly disables HBA where rootfs resides and system hangs.
6751140 e_ddi_retire_finalize: devcfg.c: panic: assertion failed: ...devi_flags & 0x0000000 6936040 If retire-store out of sync with boot archive, then this is not corrected if fault recurs 6934812 e_ddi_offline_notify() does not allow retire of nexus device 6627851 /etc/devices/retire_store out of date in boot archive should not prevent auto-boot
Diffstat (limited to 'usr/src/uts')
-rw-r--r--usr/src/uts/common/os/devcfg.c19
-rw-r--r--usr/src/uts/common/os/modctl.c7
-rw-r--r--usr/src/uts/common/os/sunmdi.c40
-rw-r--r--usr/src/uts/common/sys/sunmdi.h5
4 files changed, 43 insertions, 28 deletions
diff --git a/usr/src/uts/common/os/devcfg.c b/usr/src/uts/common/os/devcfg.c
index c49d2f9755..b303223563 100644
--- a/usr/src/uts/common/os/devcfg.c
+++ b/usr/src/uts/common/os/devcfg.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#include <sys/note.h>
@@ -5667,8 +5666,10 @@ out:
"CONSTRAINT flag. dip=%p", (void *)dip));
DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
} else if ((DEVI(dip)->devi_flags & DEVI_RETIRING) &&
- DEVI(dip)->devi_ref == 0) {
- /* also allow retire if device is not in use */
+ ((DEVI(dip)->devi_ops != NULL &&
+ DEVI(dip)->devi_ops->devo_bus_ops != NULL) ||
+ DEVI(dip)->devi_ref == 0)) {
+ /* also allow retire if nexus or if device is not in use */
RIO_VERBOSE((CE_NOTE, "e_ddi_offline_notify(): device not in "
"use. Setting CONSTRAINT flag. dip=%p", (void *)dip));
DEVI(dip)->devi_flags |= DEVI_R_CONSTRAINT;
@@ -8158,8 +8159,6 @@ e_ddi_retire_finalize(dev_info_t *dip, void *arg)
int finalize;
int phci_only;
- ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
-
mutex_enter(&DEVI(dip)->devi_lock);
if (!(DEVI(dip)->devi_flags & DEVI_RETIRING)) {
RIO_DEBUG((CE_WARN,
@@ -8178,6 +8177,8 @@ e_ddi_retire_finalize(dev_info_t *dip, void *arg)
*/
finalize = 0;
if (constraint) {
+ ASSERT(DEVI_BUSY_OWNED(ddi_get_parent(dip)));
+
ASSERT(DEVI(dip)->devi_flags & DEVI_R_CONSTRAINT);
ASSERT(!(DEVI(dip)->devi_flags & DEVI_R_BLOCKED));
DEVI(dip)->devi_flags &= ~DEVI_R_CONSTRAINT;
@@ -8219,7 +8220,7 @@ e_ddi_retire_finalize(dev_info_t *dip, void *arg)
*/
phci_only = 0;
if (MDI_PHCI(dip))
- mdi_phci_retire_finalize(dip, phci_only);
+ mdi_phci_retire_finalize(dip, phci_only, arg);
return (DDI_WALK_CONTINUE);
}
@@ -8498,6 +8499,7 @@ i_ddi_check_retire(dev_info_t *dip)
dev_info_t *pdip;
int circ;
int phci_only;
+ int constraint;
pdip = ddi_get_parent(dip);
@@ -8546,8 +8548,9 @@ i_ddi_check_retire(dev_info_t *dip)
* offline the PHCI
*/
phci_only = 1;
+ constraint = 1;
if (MDI_PHCI(dip))
- mdi_phci_retire_finalize(dip, phci_only);
+ mdi_phci_retire_finalize(dip, phci_only, &constraint);
}
void
diff --git a/usr/src/uts/common/os/modctl.c b/usr/src/uts/common/os/modctl.c
index b5f6d600bd..e91404e25a 100644
--- a/usr/src/uts/common/os/modctl.c
+++ b/usr/src/uts/common/os/modctl.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1990, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -992,10 +991,12 @@ modctl_retire(char *path, char *uconstraints, size_t ulen)
/*
* First check if the device is already retired.
- * If it is, this becomes a NOP
+ * If it is, then persist the retire anyway, just in case the retire
+ * store has got out of sync with the boot archive.
*/
if (e_ddi_device_retired(devpath)) {
cmn_err(CE_NOTE, "Device: already retired: %s", devpath);
+ (void) e_ddi_retire_persist(devpath);
kmem_free(devpath, strlen(devpath) + 1);
return (0);
}
diff --git a/usr/src/uts/common/os/sunmdi.c b/usr/src/uts/common/os/sunmdi.c
index b8b31cf7c9..b9a3f58413 100644
--- a/usr/src/uts/common/os/sunmdi.c
+++ b/usr/src/uts/common/os/sunmdi.c
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/*
@@ -5371,9 +5370,14 @@ mdi_phci_retire_notify(dev_info_t *dip, int *constraint)
* offline the path(s) hanging off the pHCI. If the
* last path to any client, check that constraints
* have been applied.
+ *
+ * If constraint is 0, we aren't going to retire the
+ * pHCI. However we still need to go through the paths
+ * calling e_ddi_retire_finalize() to clear their
+ * contract barriers.
*/
void
-mdi_phci_retire_finalize(dev_info_t *dip, int phci_only)
+mdi_phci_retire_finalize(dev_info_t *dip, int phci_only, void *constraint)
{
mdi_phci_t *ph;
mdi_client_t *ct;
@@ -5381,7 +5385,7 @@ mdi_phci_retire_finalize(dev_info_t *dip, int phci_only)
mdi_pathinfo_t *next;
dev_info_t *cdip;
int unstable = 0;
- int constraint;
+ int tmp_constraint;
if (!MDI_PHCI(dip))
return;
@@ -5435,17 +5439,20 @@ mdi_phci_retire_finalize(dev_info_t *dip, int phci_only)
i_mdi_client_unlock(ct);
MDI_PHCI_UNLOCK(ph);
/*
- * We don't retire clients we just retire the
- * path to a client. If it is the last path
- * to a client, constraints are checked and
- * if we pass the last path is offlined. MPXIO will
- * then fail all I/Os to the client. Since we don't
- * want to retire the client on a path error
- * set constraint = 0 so that the client dip
- * is not retired.
+ * This is the last path to this client.
+ *
+ * Constraint will only be set to 1 if this client can
+ * be retired (as already determined by
+ * mdi_phci_retire_notify). However we don't actually
+ * need to retire the client (we just retire the last
+ * path - MPXIO will then fail all I/Os to the client).
+ * But we still need to call e_ddi_retire_finalize so
+ * the contract barriers can be cleared. Therefore we
+ * temporarily set constraint = 0 so that the client
+ * dip is not retired.
*/
- constraint = 0;
- (void) e_ddi_retire_finalize(cdip, &constraint);
+ tmp_constraint = 0;
+ (void) e_ddi_retire_finalize(cdip, &tmp_constraint);
MDI_PHCI_LOCK(ph);
pip = next;
} else {
@@ -5454,6 +5461,11 @@ mdi_phci_retire_finalize(dev_info_t *dip, int phci_only)
}
}
+ if (!phci_only && *((int *)constraint) == 0) {
+ MDI_PHCI_UNLOCK(ph);
+ return;
+ }
+
/*
* Cannot offline pip(s)
*/
diff --git a/usr/src/uts/common/sys/sunmdi.h b/usr/src/uts/common/sys/sunmdi.h
index a670d0b2b8..d1e65a2a44 100644
--- a/usr/src/uts/common/sys/sunmdi.h
+++ b/usr/src/uts/common/sys/sunmdi.h
@@ -19,8 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
*/
#ifndef _SYS_SUNMDI_H
@@ -145,7 +144,7 @@ int mdi_devi_offline(dev_info_t *, uint_t);
*/
void mdi_phci_mark_retiring(dev_info_t *dip, char **cons_array);
void mdi_phci_retire_notify(dev_info_t *dip, int *constraint);
-void mdi_phci_retire_finalize(dev_info_t *dip, int phci_only);
+void mdi_phci_retire_finalize(dev_info_t *dip, int phci_only, void *constraint);
void mdi_phci_unretire(dev_info_t *dip);
/*