summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVijay S Balakrishna <Vijay.Balakrishna@Sun.COM>2010-02-12 13:23:04 -0800
committerVijay S Balakrishna <Vijay.Balakrishna@Sun.COM>2010-02-12 13:23:04 -0800
commitdf3cd224ef765c29101e4110546062199562f757 (patch)
treedc062d474df3b7d13175fae13272769645e7c247
parent2dea4eed7ad1c66ae4770263aa2911815a8b86eb (diff)
downloadillumos-gate-df3cd224ef765c29101e4110546062199562f757.tar.gz
6894307 cfgadm disconnect operation on SF6900 I/O boat failed with "Hardware specific failure" error
-rw-r--r--usr/src/uts/sun4u/io/sbd_io.c23
-rw-r--r--usr/src/uts/sun4u/ngdr/io/dr_io.c19
-rw-r--r--usr/src/uts/sun4u/ngdr/io/dr_quiesce.c92
-rw-r--r--usr/src/uts/sun4u/ngdr/sys/dr.h8
-rw-r--r--usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c15
-rw-r--r--usr/src/uts/sun4u/sys/sbd.h11
6 files changed, 99 insertions, 69 deletions
diff --git a/usr/src/uts/sun4u/io/sbd_io.c b/usr/src/uts/sun4u/io/sbd_io.c
index c8a9ea27f7..0a4451ca0e 100644
--- a/usr/src/uts/sun4u/io/sbd_io.c
+++ b/usr/src/uts/sun4u/io/sbd_io.c
@@ -19,12 +19,10 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/debug.h>
#include <sys/types.h>
#include <sys/errno.h>
@@ -268,7 +266,7 @@ sbd_io_status(sbd_handle_t *hp, sbd_devset_t devset, sbd_dev_stat_t *dsp)
* We use a dummy handle in which to collect
* the major numbers of unsafe devices.
*/
- sbdp_check_devices(dip, &refcount, sep);
+ sbdp_check_devices(dip, &refcount, sep, NULL);
isp->is_referenced = (refcount == 0) ? 0 : 1;
@@ -338,18 +336,29 @@ sbd_check_io_refs(sbd_handle_t *hp, sbd_devlist_t devlist[], int devnum)
for (i = 0; i < devnum; i++) {
dev_info_t *dip;
int ref;
+ int refcount_non_gldv3;
dip = devlist[i].dv_dip;
ref = 0;
- sbdp_check_devices(dip, &ref, sep);
+ refcount_non_gldv3 = 0;
+ sbdp_check_devices(dip, &ref, sep, &refcount_non_gldv3);
+ ASSERT(refcount_non_gldv3 >= 0);
+ ASSERT(ref >= refcount_non_gldv3);
+ /*
+ * Ignore reference counts of non-gldv3 network devices
+ * as Crossbow creates reference counts for non-active
+ * (unplumbed) instances. Reference count check in
+ * detach() known to prevent device from detaching
+ * as necessary.
+ */
+ ref -= refcount_non_gldv3;
if (ref) {
if (SBD_GET_ERR(ep) == 0) {
SBD_GET_PERR(sep, ep);
}
SBD_GET_PERR(sep, &devlist[i].dv_error);
}
- PR_IO("%s: dip(%s) ref = %d\n",
- f, ddi_get_name(dip), ref);
+ PR_IO("%s: dip(%s) ref = %d\n", f, ddi_get_name(dip), ref);
reftotal += ref;
}
diff --git a/usr/src/uts/sun4u/ngdr/io/dr_io.c b/usr/src/uts/sun4u/ngdr/io/dr_io.c
index 68639308dc..2853d6ef74 100644
--- a/usr/src/uts/sun4u/ngdr/io/dr_io.c
+++ b/usr/src/uts/sun4u/ngdr/io/dr_io.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -167,6 +167,7 @@ dr_check_io_refs(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
dr_io_unit_t *ip = (dr_io_unit_t *)devlist[i];
dev_info_t *dip;
int ref;
+ int refcount_non_gldv3;
sbd_error_t *err;
err = drmach_get_dip(ip->sbi_cm.sbdev_id, &dip);
@@ -174,8 +175,20 @@ dr_check_io_refs(dr_handle_t *hp, dr_common_unit_t **devlist, int devnum)
DRERR_SET_C(&ip->sbi_cm.sbdev_error, &err);
else if (dip != NULL) {
ref = 0;
+ refcount_non_gldv3 = 0;
ASSERT(e_ddi_branch_held(dip));
- dr_check_devices(dip, &ref, hp, NULL, NULL, 0);
+ dr_check_devices(dip, &ref, hp, NULL, NULL,
+ 0, &refcount_non_gldv3);
+ ASSERT(refcount_non_gldv3 >= 0);
+ ASSERT(ref >= refcount_non_gldv3);
+ /*
+ * Ignore reference counts of non-gldv3 network devices
+ * as Crossbow creates reference counts for non-active
+ * (unplumbed) instances. Reference count check in
+ * detach() known to prevent device from detaching
+ * as necessary.
+ */
+ ref -= refcount_non_gldv3;
hp->h_err = NULL;
if (ref) {
dr_dev_err(CE_WARN, &ip->sbi_cm, ESBD_BUSY);
@@ -380,7 +393,7 @@ dr_io_status(dr_handle_t *hp, dr_devset_t devset, sbd_dev_stat_t *dsp)
/* check reference and unsafe counts on devices */
isp->is_unsafe_count = 0;
dr_check_devices(dip, &refcount, hp, unsafe_devs,
- &idx, SBD_MAX_UNSAFE);
+ &idx, SBD_MAX_UNSAFE, NULL);
while (idx > 0) {
isp->is_unsafe_list[idx-1] = unsafe_devs[idx-1];
--idx;
diff --git a/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c b/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c
index abdc5fe8b6..392d1ed75c 100644
--- a/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c
+++ b/usr/src/uts/sun4u/ngdr/io/dr_quiesce.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -188,7 +188,7 @@ dr_is_real_device(dev_info_t *dip)
* now the general case
*/
rc = ddi_getlongprop(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "reg",
- (caddr_t)&regbuf, &length);
+ (caddr_t)&regbuf, &length);
ASSERT(rc != DDI_PROP_NO_MEMORY);
if (rc != DDI_PROP_SUCCESS) {
return (0);
@@ -262,6 +262,7 @@ dr_resolve_devname(dev_info_t *dip, char *buffer, char *alias)
struct dr_ref {
int *refcount;
+ int *refcount_non_gldv3;
uint64_t *arr;
int *idx;
int len;
@@ -290,14 +291,18 @@ dr_check_dip(dev_info_t *dip, void *arg, uint_t ref)
if (ref && rp->refcount) {
*rp->refcount += ref;
PR_QR("\n %s (major# %d) is referenced(%u)\n",
- dname, major, ref);
+ dname, major, ref);
+ }
+ if (ref && rp->refcount_non_gldv3) {
+ if (NETWORK_PHYSDRV(major) && !GLDV3_DRV(major))
+ *rp->refcount_non_gldv3 += ref;
}
if (dr_is_unsafe_major(major) && i_ddi_devi_attached(dip)) {
PR_QR("\n %s (major# %d) not hotpluggable\n",
- dname, major);
+ dname, major);
if (rp->arr != NULL && rp->idx != NULL)
*rp->idx = dr_add_int(rp->arr, *rp->idx,
- rp->len, (uint64_t)major);
+ rp->len, (uint64_t)major);
}
}
return (DDI_WALK_CONTINUE);
@@ -313,7 +318,7 @@ dr_check_unsafe_major(dev_info_t *dip, void *arg)
/*ARGSUSED*/
void
dr_check_devices(dev_info_t *dip, int *refcount, dr_handle_t *handle,
- uint64_t *arr, int *idx, int len)
+ uint64_t *arr, int *idx, int len, int *refcount_non_gldv3)
{
struct dr_ref bref = {0};
@@ -321,6 +326,7 @@ dr_check_devices(dev_info_t *dip, int *refcount, dr_handle_t *handle,
return;
bref.refcount = refcount;
+ bref.refcount_non_gldv3 = refcount_non_gldv3;
bref.arr = arr;
bref.idx = idx;
bref.len = len;
@@ -364,13 +370,13 @@ dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh)
if (dr_bypass_device(dname)) {
PR_QR(" bypassed suspend of %s (major# %d)\n", dname,
- major);
+ major);
continue;
}
if (drmach_verify_sr(dip, 1)) {
PR_QR(" bypassed suspend of %s (major# %d)\n", dname,
- major);
+ major);
continue;
}
@@ -381,10 +387,10 @@ dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh)
if (dr_resolve_devname(dip, d_name, d_alias) == 0) {
if (d_alias[0] != 0) {
prom_printf("\tsuspending %s@%s (aka %s)\n",
- d_name, d_info, d_alias);
+ d_name, d_info, d_alias);
} else {
prom_printf("\tsuspending %s@%s\n",
- d_name, d_info);
+ d_name, d_info);
}
} else {
prom_printf("\tsuspending %s@%s\n", dname, d_info);
@@ -392,18 +398,17 @@ dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh)
if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
prom_printf("\tFAILED to suspend %s@%s\n",
- d_name[0] ? d_name : dname, d_info);
+ d_name[0] ? d_name : dname, d_info);
srh->sr_err_idx = dr_add_int(srh->sr_err_ints,
- srh->sr_err_idx, DR_MAX_ERR_INT,
- (uint64_t)major);
+ srh->sr_err_idx, DR_MAX_ERR_INT, (uint64_t)major);
ndi_hold_devi(dip);
srh->sr_failed_dip = dip;
handle = srh->sr_dr_handlep;
dr_op_err(CE_IGNORE, handle, ESBD_SUSPEND, "%s@%s",
- d_name[0] ? d_name : dname, d_info);
+ d_name[0] ? d_name : dname, d_info);
return (DDI_FAILURE);
}
@@ -435,8 +440,8 @@ dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
/* release hold acquired in dr_suspend_devices() */
srh->sr_failed_dip = NULL;
ndi_rele_devi(dip);
- } else if (dr_is_real_device(dip) &&
- srh->sr_failed_dip == NULL) {
+ } else
+ if (dr_is_real_device(dip) && srh->sr_failed_dip == NULL) {
if ((bn = ddi_binding_name(dip)) != NULL) {
major = ddi_name_to_major(bn);
@@ -444,7 +449,7 @@ dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
bn = "<null>";
}
if (!dr_bypass_device(bn) &&
- !drmach_verify_sr(dip, 0)) {
+ !drmach_verify_sr(dip, 0)) {
char d_name[40], d_alias[40], *d_info;
d_name[0] = 0;
@@ -453,24 +458,22 @@ dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
d_info = "<null>";
if (!dr_resolve_devname(dip, d_name,
- d_alias)) {
+ d_alias)) {
if (d_alias[0] != 0) {
prom_printf("\tresuming "
- "%s@%s (aka %s)\n",
- d_name, d_info,
- d_alias);
+ "%s@%s (aka %s)\n",
+ d_name, d_info, d_alias);
} else {
prom_printf("\tresuming "
- "%s@%s\n",
- d_name, d_info);
+ "%s@%s\n", d_name, d_info);
}
} else {
prom_printf("\tresuming %s@%s\n",
- bn, d_info);
+ bn, d_info);
}
if (devi_attach(dip, DDI_RESUME) !=
- DDI_SUCCESS) {
+ DDI_SUCCESS) {
/*
* Print a console warning,
* set an e_code of ESBD_RESUME,
@@ -481,9 +484,9 @@ dr_resume_devices(dev_info_t *start, dr_sr_handle_t *srh)
d_name[0] ? d_name : bn, d_info);
srh->sr_err_idx =
- dr_add_int(srh->sr_err_ints,
- srh->sr_err_idx, DR_MAX_ERR_INT,
- (uint64_t)major);
+ dr_add_int(srh->sr_err_ints,
+ srh->sr_err_idx, DR_MAX_ERR_INT,
+ (uint64_t)major);
handle = srh->sr_dr_handlep;
@@ -641,7 +644,7 @@ dr_stop_user_threads(dr_sr_handle_t *srh)
/* were we unable to stop all threads after a few tries? */
if (bailout) {
handle->h_err = drerr_int(ESBD_UTHREAD, srh->sr_err_ints,
- srh->sr_err_idx, 0);
+ srh->sr_err_idx, 0);
return (ESRCH);
}
@@ -755,7 +758,7 @@ dr_resume(dr_sr_handle_t *srh)
if (srh->sr_flags & (SR_FLAG_WATCHDOG)) {
mutex_enter(&tod_lock);
tod_ops.tod_set_watchdog_timer(
- watchdog_timeout_seconds);
+ watchdog_timeout_seconds);
mutex_exit(&tod_lock);
}
@@ -780,7 +783,7 @@ dr_resume(dr_sr_handle_t *srh)
if (srh->sr_err_idx && srh->sr_dr_handlep) {
(srh->sr_dr_handlep)->h_err = drerr_int(ESBD_RESUME,
- srh->sr_err_ints, srh->sr_err_idx, 1);
+ srh->sr_err_ints, srh->sr_err_idx, 1);
}
/*
@@ -866,7 +869,7 @@ dr_suspend(dr_sr_handle_t *srh)
ddi_walk_devs(ddi_root_node(), dr_check_unsafe_major, &drc);
if (dev_errs_idx) {
handle->h_err = drerr_int(ESBD_UNSAFE, dev_errs,
- dev_errs_idx, 1);
+ dev_errs_idx, 1);
dr_resume(srh);
return (DDI_FAILURE);
}
@@ -904,7 +907,7 @@ dr_suspend(dr_sr_handle_t *srh)
if ((rc = dr_suspend_devices(ddi_root_node(), srh)) != DDI_SUCCESS) {
if (srh->sr_err_idx && srh->sr_dr_handlep) {
(srh->sr_dr_handlep)->h_err = drerr_int(ESBD_SUSPEND,
- srh->sr_err_ints, srh->sr_err_idx, 1);
+ srh->sr_err_ints, srh->sr_err_idx, 1);
}
dr_resume(srh);
return (rc);
@@ -962,7 +965,7 @@ dr_pt_test_suspend(dr_handle_t *hp)
switch (psmerr) {
case ESBD_RESUME:
PR_QR("Couldn't resume devices: %s\n",
- DR_GET_E_RSC(hp->h_err));
+ DR_GET_E_RSC(hp->h_err));
break;
case ESBD_KTHREAD:
@@ -970,38 +973,38 @@ dr_pt_test_suspend(dr_handle_t *hp)
break;
default:
PR_ALL("Resume error unknown = %d\n",
- psmerr);
+ psmerr);
break;
}
}
} else {
PR_ALL("%s: dr_suspend() failed, err = 0x%x\n",
- f, err);
+ f, err);
psmerr = hp->h_err ? hp->h_err->e_code : ESBD_NOERROR;
switch (psmerr) {
case ESBD_UNSAFE:
PR_ALL("Unsafe devices (major #): %s\n",
- DR_GET_E_RSC(hp->h_err));
+ DR_GET_E_RSC(hp->h_err));
break;
case ESBD_RTTHREAD:
PR_ALL("RT threads (PIDs): %s\n",
- DR_GET_E_RSC(hp->h_err));
+ DR_GET_E_RSC(hp->h_err));
break;
case ESBD_UTHREAD:
PR_ALL("User threads (PIDs): %s\n",
- DR_GET_E_RSC(hp->h_err));
+ DR_GET_E_RSC(hp->h_err));
break;
case ESBD_SUSPEND:
PR_ALL("Non-suspendable devices (major #): %s\n",
- DR_GET_E_RSC(hp->h_err));
+ DR_GET_E_RSC(hp->h_err));
break;
case ESBD_RESUME:
PR_ALL("Could not resume devices (major #): %s\n",
- DR_GET_E_RSC(hp->h_err));
+ DR_GET_E_RSC(hp->h_err));
break;
case ESBD_KTHREAD:
@@ -1081,14 +1084,13 @@ drerr_int(int e_code, uint64_t *arr, int idx, int majors)
dname = ddi_major_to_name(arr[i]);
if (dname) {
n = snprintf(&buf[buf_idx], buf_avail,
- "%s, ", dname);
+ "%s, ", dname);
} else {
n = snprintf(&buf[buf_idx], buf_avail,
- "major %lu, ", arr[i]);
+ "major %lu, ", arr[i]);
}
} else {
- n = snprintf(&buf[buf_idx], buf_avail, "%lu, ",
- arr[i]);
+ n = snprintf(&buf[buf_idx], buf_avail, "%lu, ", arr[i]);
}
/* An ellipsis gets appended when no more values fit */
diff --git a/usr/src/uts/sun4u/ngdr/sys/dr.h b/usr/src/uts/sun4u/ngdr/sys/dr.h
index c34c744120..96ac53c3c9 100644
--- a/usr/src/uts/sun4u/ngdr/sys/dr.h
+++ b/usr/src/uts/sun4u/ngdr/sys/dr.h
@@ -19,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SYS_DR_H
#define _SYS_DR_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -375,8 +373,8 @@ extern void dr_release_sr_handle(dr_sr_handle_t *srh);
extern int dr_suspend(dr_sr_handle_t *srh);
extern void dr_resume(dr_sr_handle_t *srh);
extern void dr_check_devices(dev_info_t *dip, int *refcount,
- dr_handle_t *handle, uint64_t *arr,
- int *idx, int len);
+ dr_handle_t *handle, uint64_t *arr, int *idx,
+ int len, int *refcount_non_gldv3);
extern int dr_pt_test_suspend(dr_handle_t *hp);
/*
diff --git a/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c b/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c
index fc2363df31..05cb27e648 100644
--- a/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c
+++ b/usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -234,6 +234,7 @@ sbdp_resolve_devname(dev_info_t *dip, char *buffer, char *alias)
typedef struct sbdp_ref {
int *refcount;
+ int *refcount_non_gldv3;
sbd_error_t *sep;
} sbdp_ref_t;
@@ -268,10 +269,18 @@ sbdp_check_dip(dev_info_t *dip, void *arg, uint_t ref)
#endif
if (ref) {
+ major_t major;
+
(*sbrp->refcount)++;
SBDP_DBG_QR("\n%s (major# %d) is referenced\n",
dname, ddi_name_to_major(dname));
(void) ddi_pathname(dip, sbdp_get_err_buf(sbrp->sep));
+ major = ddi_driver_major(dip);
+ if (sbrp->refcount_non_gldv3 && NETWORK_PHYSDRV(major) &&
+ !GLDV3_DRV(major)) {
+ (*sbrp->refcount_non_gldv3)++;
+ return (DDI_WALK_CONTINUE);
+ }
sbdp_set_err(sbrp->sep, ESBD_BUSY, NULL);
return (DDI_WALK_TERMINATE);
}
@@ -279,11 +288,13 @@ sbdp_check_dip(dev_info_t *dip, void *arg, uint_t ref)
}
void
-sbdp_check_devices(dev_info_t *dip, int *refcount, sbd_error_t *sep)
+sbdp_check_devices(dev_info_t *dip, int *refcount, sbd_error_t *sep,
+ int *refcount_non_gldv3)
{
sbdp_ref_t sbr;
sbr.refcount = refcount;
+ sbr.refcount_non_gldv3 = refcount_non_gldv3;
sbr.sep = sep;
ASSERT(e_ddi_branch_held(dip));
diff --git a/usr/src/uts/sun4u/sys/sbd.h b/usr/src/uts/sun4u/sys/sbd.h
index 44e075e4be..0c60380e7b 100644
--- a/usr/src/uts/sun4u/sys/sbd.h
+++ b/usr/src/uts/sun4u/sys/sbd.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,15 +19,13 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#ifndef _SBD_H
#define _SBD_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -112,7 +109,7 @@ int sbdphw_get_base_physaddr(sbdp_handle_t *hp, dev_info_t *dip, uint64_t *pa);
int sbdp_isbootproc(processorid_t cpuid);
int sbdp_ioctl(sbdp_handle_t *, sbdp_ioctl_arg_t *);
int sbdp_isinterleaved(sbdp_handle_t *, dev_info_t *);
-void sbdp_check_devices(dev_info_t *, int *refcount, sbd_error_t *);
+void sbdp_check_devices(dev_info_t *, int *refcount, sbd_error_t *, int *);
int sbdp_dr_avail(void);
extern int sbdp_cpu_get_impl(sbdp_handle_t *hp, dev_info_t *dip);