diff options
author | Stephen Hanson <Stephen.Hanson@Sun.COM> | 2010-04-09 02:48:25 -0700 |
---|---|---|
committer | Stephen Hanson <Stephen.Hanson@Sun.COM> | 2010-04-09 02:48:25 -0700 |
commit | bf002425f517afdc1d8b6a9602e59910eeee05aa (patch) | |
tree | 00eb38800c281e0718b3b0f7ce9515482dc2cf20 /usr/src/uts | |
parent | 44ed9dbbfa620821ecf59a131462082f628dd0f3 (diff) | |
download | illumos-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.c | 19 | ||||
-rw-r--r-- | usr/src/uts/common/os/modctl.c | 7 | ||||
-rw-r--r-- | usr/src/uts/common/os/sunmdi.c | 40 | ||||
-rw-r--r-- | usr/src/uts/common/sys/sunmdi.h | 5 |
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); /* |