diff options
author | Vijay S Balakrishna <Vijay.Balakrishna@Sun.COM> | 2010-02-12 13:23:04 -0800 |
---|---|---|
committer | Vijay S Balakrishna <Vijay.Balakrishna@Sun.COM> | 2010-02-12 13:23:04 -0800 |
commit | df3cd224ef765c29101e4110546062199562f757 (patch) | |
tree | dc062d474df3b7d13175fae13272769645e7c247 | |
parent | 2dea4eed7ad1c66ae4770263aa2911815a8b86eb (diff) | |
download | illumos-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.c | 23 | ||||
-rw-r--r-- | usr/src/uts/sun4u/ngdr/io/dr_io.c | 19 | ||||
-rw-r--r-- | usr/src/uts/sun4u/ngdr/io/dr_quiesce.c | 92 | ||||
-rw-r--r-- | usr/src/uts/sun4u/ngdr/sys/dr.h | 8 | ||||
-rw-r--r-- | usr/src/uts/sun4u/serengeti/io/sbdp_quiesce.c | 15 | ||||
-rw-r--r-- | usr/src/uts/sun4u/sys/sbd.h | 11 |
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)®buf, &length); + (caddr_t)®buf, &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); |