changeset 12618:0e5eaf4bf546

6935604 io-retire should prevent attach of faulty persistent devices 6930157 Remove fmadm's reliance on taking topo snapshots 6881991 SMART faults could preserve asc/ascq in fault payload 6955664 eversholt matching should not be performed for scsi-device nodes 6958085 defect.sunos.fmd.module not visible via fmadm faulty 6958856 fmd performance issue if "fmstat -m" called while disgnosis going on
author Stephen Hanson <Stephen.Hanson@Sun.COM>
date Mon, 14 Jun 2010 02:22:19 -0700
parents d82a7bcb6fed
children 60877912fc2d
files usr/src/cmd/fm/eversholt/files/common/disk.esc usr/src/cmd/fm/fmadm/common/faulty.c usr/src/cmd/fm/fmd/common/fmd_module.c usr/src/cmd/fm/fmd/common/fmd_scheme.c usr/src/cmd/fm/modules/common/eversholt/config.c usr/src/lib/fm/topo/libtopo/common/dev.c usr/src/lib/fm/topo/libtopo/common/topo_hc.h usr/src/lib/fm/topo/modules/common/ses/ses.h usr/src/uts/common/os/devcfg.c
diffstat 9 files changed, 99 insertions(+), 201 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/fm/eversholt/files/common/disk.esc	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/cmd/fm/eversholt/files/common/disk.esc	Mon Jun 14 02:22:19 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #pragma dictionary "DISK"
@@ -204,4 +203,6 @@
     ereport.io.scsi.disk.self-test-failure@P;
 
 prop fault.io.disk.predictive-failure@P ->
-    ereport.io.scsi.disk.predictive-failure@P;
+    ereport.io.scsi.disk.predictive-failure@P {
+    setpayloadprop("asc", payloadprop("additional-sense-code")) &&
+    setpayloadprop("ascq", payloadprop("additional-sense-code-qualifier")) };
--- a/usr/src/cmd/fm/fmadm/common/faulty.c	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/cmd/fm/fmadm/common/faulty.c	Mon Jun 14 02:22:19 2010 -0700
@@ -19,8 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -234,11 +233,6 @@
 	uint8_t max_pct;
 } resource_list_t;
 
-typedef struct tgetlabel_data {
-	char *label;
-	char *fru;
-} tgetlabel_data_t;
-
 sr_list_t *status_rec_list;
 resource_list_t *status_fru_list;
 resource_list_t *status_asru_list;
@@ -246,7 +240,6 @@
 static int max_display;
 static int max_fault = 0;
 static topo_hdl_t *topo_handle;
-static char *topo_handle_uuid;
 static host_id_list_t *host_list;
 static int n_server;
 static int opt_g;
@@ -342,116 +335,6 @@
 	return (rt);
 }
 
-/*
- * compare two fru strings which are made up of substrings seperated by '/'
- * return true if every substring is the same in the two strings, or if a
- * substring is null in one.
- */
-
-static int
-frucmp(char *f1, char *f2)
-{
-	char c1, c2;
-	int i = 0;
-
-	for (;;) {
-		c1 = *f1;
-		c2 = *f2;
-		if (c1 == c2) {
-			i = (c1 == '/') ? 0 : i + 1;
-		} else if (i == 0) {
-			if (c1 == '/') {
-				do {
-					f2++;
-				} while ((c2 = *f2) != 0 && c2 != '/');
-				if (c2 == NULL)
-					break;
-			} else if (c2 == '/') {
-				do {
-					f1++;
-				} while ((c1 = *f1) != 0 && c1 != '/');
-				if (c1 == NULL)
-					break;
-			} else
-				break;
-		} else
-			break;
-		if (c1 == NULL)
-			return (0);
-		f1++;
-		f2++;
-	}
-	return (1);
-}
-
-static int
-tgetlabel(topo_hdl_t *thp, tnode_t *node, void *arg)
-{
-	int err;
-	char *fru_name, *lname;
-	nvlist_t *fru = NULL;
-	int rt = TOPO_WALK_NEXT;
-	tgetlabel_data_t *tdp = (tgetlabel_data_t *)arg;
-
-	if (topo_node_fru(node, &fru, NULL, &err) == 0) {
-		if (topo_fmri_nvl2str(thp, fru, &fru_name, &err) == 0) {
-			if (frucmp(tdp->fru, fru_name) == 0 &&
-			    topo_node_label(node, &lname, &err) == 0) {
-				tdp->label = strdup(lname);
-				topo_hdl_strfree(thp, lname);
-				rt = TOPO_WALK_TERMINATE;
-			}
-			topo_hdl_strfree(thp, fru_name);
-		}
-		nvlist_free(fru);
-	}
-	return (rt);
-}
-
-static void
-label_get_topo(void)
-{
-	int err;
-
-	topo_handle = topo_open(TOPO_VERSION, 0, &err);
-	if (topo_handle) {
-		topo_handle_uuid = topo_snap_hold(topo_handle, NULL, &err);
-	}
-}
-
-static void
-label_release_topo(void)
-{
-	if (topo_handle_uuid)
-		topo_hdl_strfree(topo_handle, topo_handle_uuid);
-	if (topo_handle) {
-		topo_snap_release(topo_handle);
-		topo_close(topo_handle);
-	}
-}
-
-static char *
-get_fmri_label(char *fru)
-{
-	topo_walk_t *twp;
-	tgetlabel_data_t td;
-	int err;
-
-	td.label = NULL;
-	td.fru = fru;
-	if (topo_handle == NULL)
-		label_get_topo();
-	if (topo_handle_uuid) {
-		twp = topo_walk_init(topo_handle, FM_FMRI_SCHEME_HC,
-		    tgetlabel, &td, &err);
-		if (twp) {
-			(void) topo_walk_step(twp, TOPO_WALK_CHILD);
-			topo_walk_fini(twp);
-		}
-	}
-	return (td.label);
-}
-
 static char *
 get_nvl2str_topo(nvlist_t *nvl)
 {
@@ -463,7 +346,7 @@
 	char buf[128];
 
 	if (topo_handle == NULL)
-		label_get_topo();
+		topo_handle = topo_open(TOPO_VERSION, 0, &err);
 	if (topo_fmri_nvl2str(topo_handle, nvl, &tname, &err) == 0) {
 		name = strdup(tname);
 		topo_hdl_strfree(topo_handle, tname);
@@ -1073,19 +956,14 @@
 }
 
 static void
-print_name(name_list_t *list, char *(func)(char *), char *padding, int *np,
-    int pct, int full)
+print_name(name_list_t *list, char *padding, int *np, int pct, int full)
 {
-	char *name, *fru_label = NULL;
+	char *name;
 
 	name = list->name;
 	if (list->label) {
 		(void) printf("%s \"%s\" (%s)", padding, list->label, name);
 		*np += 1;
-	} else if (func && (fru_label = func(list->name)) != NULL) {
-		(void) printf("%s \"%s\" (%s)", padding, fru_label, name);
-		*np += 1;
-		free(fru_label);
 	} else {
 		(void) printf("%s %s", padding, name);
 		*np += 1;
@@ -1192,10 +1070,10 @@
 }
 
 static void
-print_name_list(name_list_t *list, char *label, char *(func)(char *),
+print_name_list(name_list_t *list, char *label,
     int limit, int pct, void (func1)(int, char *), int full)
 {
-	char *name, *fru_label = NULL;
+	char *name;
 	char *padding;
 	int i, j, l, n;
 	name_list_t *end = list;
@@ -1209,10 +1087,7 @@
 	name = list->name;
 	if (list->label)
 		(void) printf(" \"%s\" (%s)", list->label, name);
-	else if (func && (fru_label = func(list->name)) != NULL) {
-		(void) printf(" \"%s\" (%s)", fru_label, name);
-		free(fru_label);
-	} else
+	else
 		(void) printf(" %s", name);
 	if (list->pct && pct > 0 && pct < 100) {
 		if (list->count > 1) {
@@ -1235,14 +1110,14 @@
 	j = 0;
 	while ((list = list->next) != end) {
 		if (limit == 0 || n < limit) {
-			print_name(list, func, padding, &n, pct, full);
+			print_name(list, padding, &n, pct, full);
 			if (func1)
 				func1(list->status, padding);
 		} else
 			j++;
 	}
 	if (j == 1) {
-		print_name(list->prev, func, padding, &n, pct, full);
+		print_name(list->prev, padding, &n, pct, full);
 	} else if (j > 1) {
 		(void) printf("%s... %d %s\n", padding, j,
 		    dgettext("FMD", "more entries suppressed,"
@@ -1352,18 +1227,18 @@
 	    srp->host->product_sn? srp->host->product_sn : "");
 	if (srp->class)
 		print_name_list(srp->class,
-		    dgettext("FMD", "Fault class :"), NULL, 0, srp->class->pct,
+		    dgettext("FMD", "Fault class :"), 0, srp->class->pct,
 		    NULL, full);
 	if (srp->asru) {
 		status = asru_same_status(srp->asru);
 		if (status != -1) {
 			print_name_list(srp->asru,
-			    dgettext("FMD", "Affects     :"), NULL,
+			    dgettext("FMD", "Affects     :"),
 			    full ? 0 : max_display, 0, NULL, full);
 			print_asru_status(status, "             ");
 		} else
 			print_name_list(srp->asru,
-			    dgettext("FMD", "Affects     :"), NULL,
+			    dgettext("FMD", "Affects     :"),
 			    full ? 0 : max_display, 0, print_asru_status, full);
 	}
 	if (full || srp->fru == NULL || srp->asru == NULL) {
@@ -1371,13 +1246,13 @@
 			status = asru_same_status(srp->resource);
 			if (status != -1) {
 				print_name_list(srp->resource,
-				    dgettext("FMD", "Problem in  :"), NULL,
+				    dgettext("FMD", "Problem in  :"),
 				    full ? 0 : max_display, 0, NULL, full);
 				print_rsrc_status(status, "             ");
 			} else
 				print_name_list(srp->resource,
 				    dgettext("FMD", "Problem in  :"),
-				    NULL, full ? 0 : max_display, 0,
+				    full ? 0 : max_display, 0,
 				    print_rsrc_status, full);
 		}
 	}
@@ -1385,20 +1260,20 @@
 		status = asru_same_status(srp->fru);
 		if (status != -1) {
 			print_name_list(srp->fru, dgettext("FMD",
-			    "FRU         :"), get_fmri_label, 0,
+			    "FRU         :"), 0,
 			    srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
 			    NULL, full);
 			print_fru_status(status, "             ");
 		} else
 			print_name_list(srp->fru, dgettext("FMD",
-			    "FRU         :"), get_fmri_label, 0,
+			    "FRU         :"), 0,
 			    srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
 			    print_fru_status, full);
 	}
 	if (srp->serial && !serial_in_fru(srp->fru, srp->serial) &&
 	    !serial_in_fru(srp->asru, srp->serial)) {
 		print_name_list(srp->serial, dgettext("FMD", "Serial ID.  :"),
-		    NULL, 0, 0, NULL, full);
+		    0, 0, NULL, full);
 	}
 	print_dict_info(srp->uurec->event);
 	(void) printf("\n");
@@ -1516,7 +1391,6 @@
 	resource_list_t *tp = status_fru_list;
 	status_record_t *srp;
 	sr_list_t *slp, *end;
-	char *fru_label;
 	uurec_t *uurp;
 	name_list_t *fru;
 	int status;
@@ -1543,12 +1417,7 @@
 					if (fru->label)
 						(void) printf("\"%s\" (%s) ",
 						    fru->label, fru->name);
-					else if ((fru_label = get_fmri_label(
-					    fru->name)) != NULL) {
-						(void) printf("\"%s\" (%s) ",
-						    fru_label, fru->name);
-						free(fru_label);
-					} else
+					else
 						(void) printf("%s ",
 						    fru->name);
 					break;
@@ -1635,7 +1504,7 @@
 						print_name_list(srp->serial,
 						    dgettext("FMD",
 						    "Serial ID.  :"),
-						    NULL, 0, 0, NULL, 1);
+						    0, 0, NULL, 1);
 						break;
 					}
 					slp = slp->next;
@@ -1864,7 +1733,8 @@
 	if (opt_f == 0 && opt_r == 0)
 		print_catalog(opt_s, opt_a, opt_v, opt_i, opt_p && !opt_s);
 	fmd_msg_fini(fmadm_msghdl);
-	label_release_topo();
+	if (topo_handle)
+		topo_close(topo_handle);
 	if (opt_p) {
 		(void) fclose(stdout);
 		(void) wait(&stat);
--- a/usr/src/cmd/fm/fmd/common/fmd_module.c	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/cmd/fm/fmd/common/fmd_module.c	Mon Jun 14 02:22:19 2010 -0700
@@ -1314,8 +1314,16 @@
 	 */
 	(void) pthread_mutex_lock(&mp->mod_lock);
 
-	while (mp->mod_error == 0 && !(mp->mod_flags & FMD_MOD_STPUB))
+	while (mp->mod_error == 0 && !(mp->mod_flags & FMD_MOD_STPUB)) {
+		struct timespec tms;
+
 		(void) pthread_cond_wait(&mp->mod_cv, &mp->mod_lock);
+		(void) pthread_mutex_unlock(&mp->mod_lock);
+		tms.tv_sec = 0;
+		tms.tv_nsec = 10000000;
+		(void) nanosleep(&tms, NULL);
+		(void) pthread_mutex_lock(&mp->mod_lock);
+	}
 
 	if (mp->mod_error != 0) {
 		(void) pthread_mutex_unlock(&mp->mod_lock);
--- a/usr/src/cmd/fm/fmd/common/fmd_scheme.c	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/cmd/fm/fmd/common/fmd_scheme.c	Mon Jun 14 02:22:19 2010 -0700
@@ -20,12 +20,9 @@
  */
 
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <limits.h>
 #include <stddef.h>
 #include <unistd.h>
@@ -62,7 +59,7 @@
 {
 	char *name, *version;
 	fmd_module_t *mp;
-	int rv = 0;
+	int rv = 1;
 
 	if (nvlist_lookup_string(nvl, FM_FMRI_FMD_NAME, &name) != 0 ||
 	    nvlist_lookup_string(nvl, FM_FMRI_FMD_VERSION, &version) != 0)
@@ -82,7 +79,7 @@
 {
 	char *name, *version;
 	fmd_module_t *mp;
-	int rv = 0;
+	int rv = 1;
 
 	if (nvlist_lookup_string(nvl, FM_FMRI_FMD_NAME, &name) != 0 ||
 	    nvlist_lookup_string(nvl, FM_FMRI_FMD_VERSION, &version) != 0)
@@ -94,7 +91,7 @@
 		fmd_module_rele(mp);
 	}
 
-	return (rv ? FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_NOT_PRESENT);
+	return (rv ? FMD_OBJ_STATE_STILL_PRESENT : FMD_OBJ_STATE_REPLACED);
 }
 
 static int
--- a/usr/src/cmd/fm/modules/common/eversholt/config.c	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/cmd/fm/modules/common/eversholt/config.c	Mon Jun 14 02:22:19 2010 -0700
@@ -353,12 +353,22 @@
 		 * If this property is a device path, tp or devid, cache it
 		 * for quick lookup.
 		 */
-		if (pn == stable(TOPO_IO_DEV)) {
+		if (config_lastcomp == stable(SCSI_DEVICE) ||
+		    config_lastcomp == stable(SMP_DEVICE)) {
+			/*
+			 * we can't get ereports on SCSI_DEVICE or SMP_DEVICE
+			 * nodes, so don't cache.
+			 */
+			out(O_ALTFP|O_VERB3, "not caching %s for %s",
+			    pn, config_lastcomp);
+		} else if (pn == stable(TOPO_IO_DEV)) {
 			sv = stable(equals + 1);
 			out(O_ALTFP|O_VERB3, "caching dev %s", sv);
 			cdata->devcache = lut_add(cdata->devcache,
 			    (void *)sv, (void *)newnode, NULL);
-		} else if (pn == stable(TOPO_IO_DEVID)) {
+		} else if (pn == stable(TOPO_IO_DEVID) ||
+		    pn == stable(TOPO_PROP_SES_DEVID) ||
+		    pn == stable(TOPO_PROP_SMP_DEVID)) {
 			sv = stable(equals + 1);
 			out(O_ALTFP|O_VERB3, "caching devid %s", sv);
 			cdata->devidcache = lut_add(cdata->devidcache,
--- a/usr/src/lib/fm/topo/libtopo/common/dev.c	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/dev.c	Mon Jun 14 02:22:19 2010 -0700
@@ -485,19 +485,19 @@
 		if (stat(path, &sb) != -1)
 			rval = FMD_OBJ_STATE_UNKNOWN;
 		else if ((dnode = di_init("/", DINFOCACHE)) == DI_NODE_NIL)
-			rval = FMD_OBJ_STATE_NOT_PRESENT;
+			rval = FMD_OBJ_STATE_UNKNOWN;
 		else {
 			if (di_lookup_node(dnode, devpath) == DI_NODE_NIL)
-				rval = FMD_OBJ_STATE_NOT_PRESENT;
+				rval = FMD_OBJ_STATE_UNKNOWN;
 			else
 				rval = FMD_OBJ_STATE_UNKNOWN;
 			di_fini(dnode);
 		}
 	} else {
 		if (stat(path, &sb) == -1)
-			rval = FMD_OBJ_STATE_NOT_PRESENT;
+			rval = FMD_OBJ_STATE_UNKNOWN;
 		else if ((dnode = di_init(devpath, DINFOCPYONE)) == DI_NODE_NIL)
-			rval = FMD_OBJ_STATE_NOT_PRESENT;
+			rval = FMD_OBJ_STATE_UNKNOWN;
 		else {
 			if ((id = di_devid(dnode)) == NULL ||
 			    devid_str_decode(devid, &matchid, NULL) != 0)
--- a/usr/src/lib/fm/topo/libtopo/common/topo_hc.h	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/lib/fm/topo/libtopo/common/topo_hc.h	Mon Jun 14 02:22:19 2010 -0700
@@ -131,6 +131,28 @@
 #define	TOPO_STORAGE_SAS_PHY_MASK	"receptacle-pm"
 #define	TOPO_STORAGE_SAS_CONNECTOR_TYPE	"sas-connector-type"
 
+#define	TOPO_PGROUP_SES		"ses"
+/* Applied  any SES standard related topo node. */
+#define	TOPO_PROP_NODE_ID	"node-id"
+#define	TOPO_PROP_TARGET_PATH	"target-path"
+#define	TOPO_PROP_SES_DEVID	"ses-devid"
+#define	TOPO_PROP_SES_DEV_PATH	"ses-devfs-path"
+#define	TOPO_PROP_SES_PHYS_PATH	"ses-phys-path"
+#define	TOPO_PROP_SES_TARGET_PORT "ses-target-port"
+
+#define	TOPO_PGROUP_SMP		"smp"
+/* host SMP target related info for an expander node. */
+#define	TOPO_PROP_SMP_DEVID	"smp-devid"
+#define	TOPO_PROP_SMP_DEV_PATH	"smp-devfs-path"
+#define	TOPO_PROP_SMP_PHYS_PATH	"smp-phys-path"
+#define	TOPO_PROP_SMP_TARGET_PORT	"smp-target-port"
+#define	TOPO_PROP_SAS_ADDR	"sas-address"
+#define	TOPO_PROP_PHY_COUNT	"phy-count"
+#define	TOPO_PROP_PATHS		"paths"
+#define	TOPO_PROP_CHASSIS_TYPE	"chassis-type"
+#define	TOPO_PROP_SAS_PHY_MASK	"phy-mask"
+#define	TOPO_PROP_SAS_CONNECTOR_TYPE	"sas-connector-type"
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/lib/fm/topo/modules/common/ses/ses.h	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/lib/fm/topo/modules/common/ses/ses.h	Mon Jun 14 02:22:19 2010 -0700
@@ -57,35 +57,6 @@
 	ctid_t			set_ctid;
 } ses_enum_target_t;
 
-#define	TOPO_PGROUP_SES		"ses"
-/* Applied  any SES standard related topo node. */
-#define	TOPO_PROP_NODE_ID	"node-id"
-#define	TOPO_PROP_TARGET_PATH	"target-path"
-/*
- * Applied to host SES target related info on an expander node.
- * In oder to avoid the same prop name across different property groups
- * in the expander node, property group prefix is added to the names of
- * individual properties.
- */
-#define	TOPO_PROP_SES_DEVID	"ses-devid"
-#define	TOPO_PROP_SES_DEV_PATH	"ses-devfs-path"
-#define	TOPO_PROP_SES_PHYS_PATH	"ses-phys-path"
-#define	TOPO_PROP_SES_TARGET_PORT "ses-target-port"
-
-#define	TOPO_PGROUP_SMP		"smp"
-/* host SMP target related info for an expander node. */
-#define	TOPO_PROP_SMP_DEVID	"smp-devid"
-#define	TOPO_PROP_SMP_DEV_PATH	"smp-devfs-path"
-#define	TOPO_PROP_SMP_PHYS_PATH	"smp-phys-path"
-#define	TOPO_PROP_SMP_TARGET_PORT	"smp-target-port"
-
-#define	TOPO_PROP_SAS_ADDR	"sas-address"
-#define	TOPO_PROP_PHY_COUNT	"phy-count"
-#define	TOPO_PROP_PATHS		"paths"
-#define	TOPO_PROP_CHASSIS_TYPE	"chassis-type"
-#define	TOPO_PROP_SAS_PHY_MASK	"phy-mask"
-#define	TOPO_PROP_SAS_CONNECTOR_TYPE	"sas-connector-type"
-
 #ifndef	NDEBUG
 #define	verify(x)	assert(x)
 #else
--- a/usr/src/uts/common/os/devcfg.c	Mon Jun 14 02:08:23 2010 -0700
+++ b/usr/src/uts/common/os/devcfg.c	Mon Jun 14 02:22:19 2010 -0700
@@ -166,6 +166,12 @@
  */
 int identify_9e = 0;
 
+/*
+ * Add flag so behaviour of preventing attach for retired persistant nodes
+ * can be disabled.
+ */
+int retire_prevents_attach = 1;
+
 int mtc_off;					/* turn off mt config */
 
 int quiesce_debug = 0;
@@ -213,7 +219,7 @@
     int circular, clock_t end_time);
 static int ndi_devi_unbind_driver(dev_info_t *dip);
 
-static void i_ddi_check_retire(dev_info_t *dip);
+static int i_ddi_check_retire(dev_info_t *dip);
 
 static void quiesce_one_device(dev_info_t *, void *);
 
@@ -1560,7 +1566,17 @@
 				i_ddi_set_node_state(dip, DS_PROBED);
 			break;
 		case DS_PROBED:
-			i_ddi_check_retire(dip);
+			/*
+			 * If node is retired and persistent, then prevent
+			 * attach. We can't do this for non-persistent nodes
+			 * as we would lose evidence that the node existed.
+			 */
+			if (i_ddi_check_retire(dip) == 1 &&
+			    ndi_dev_is_persistent_node(dip) &&
+			    retire_prevents_attach == 1) {
+				rv = DDI_FAILURE;
+				break;
+			}
 			atomic_add_long(&devinfo_attach_detach, 1);
 			if ((rv = attach_node(dip)) == DDI_SUCCESS)
 				i_ddi_set_node_state(dip, DS_ATTACHED);
@@ -8579,7 +8595,7 @@
  * To be called only by framework attach code on first attach attempt.
  *
  */
-static void
+static int
 i_ddi_check_retire(dev_info_t *dip)
 {
 	char		*path;
@@ -8611,8 +8627,10 @@
 	 */
 	if (e_ddi_device_retired(path) == 0) {
 		RIO_VERBOSE((CE_NOTE, "device is NOT retired: path=%s", path));
+		if (DEVI(dip)->devi_flags & DEVI_RETIRED)
+			(void) e_ddi_unretire_device(path);
 		kmem_free(path, MAXPATHLEN);
-		return;
+		return (0);
 	}
 
 	RIO_DEBUG((CE_NOTE, "attach: device is retired: path=%s", path));
@@ -8638,6 +8656,7 @@
 	constraint = 1;
 	if (MDI_PHCI(dip))
 		mdi_phci_retire_finalize(dip, phci_only, &constraint);
+	return (1);
 }