/* ARGSUSED */ static int dr_check_dip(dev_info_t *dip, void *arg, uint_t ref) { major_t major; char *dname; struct dr_ref *rp = (struct dr_ref *)arg; if (dip == NULL) return (DDI_WALK_CONTINUE); if (!dr_is_real_device(dip)) return (DDI_WALK_CONTINUE); dname = ddi_binding_name(dip); if (dr_bypass_device(dname)) return (DDI_WALK_CONTINUE); if (dname && ((major = ddi_name_to_major(dname)) != (major_t)-1)) { if (ref && rp->refcount) { *rp->refcount += ref; PR_QR("\n %s (major# %d) is referenced(%u)\n", dname, major, ref); } if (dr_is_unsafe_major(major) && i_ddi_devi_attached(dip)) { PR_QR("\n %s (major# %d) not hotpluggable\n", dname, major); if (rp->arr != NULL && rp->idx != NULL) *rp->idx = dr_add_int(rp->arr, *rp->idx, rp->len, (uint64_t)major); } } return (DDI_WALK_CONTINUE); }
/* * Build a list of dev_t's for a device/devid * * The effect of this function is cumulative, adding dev_t's * for the device to the list of all dev_t's for a given * devid. */ static void e_devid_minor_to_devlist( dev_info_t *dip, char *minor_name, int ndevts_alloced, int *devtcntp, dev_t *devtsp) { struct ddi_minor_data *dmdp; int minor_all = 0; int ndevts = *devtcntp; ASSERT(i_ddi_devi_attached(dip)); /* are we looking for a set of minor nodes? */ if ((minor_name == DEVID_MINOR_NAME_ALL) || (minor_name == DEVID_MINOR_NAME_ALL_CHR) || (minor_name == DEVID_MINOR_NAME_ALL_BLK)) minor_all = 1; mutex_enter(&(DEVI(dip)->devi_lock)); /* Find matching minor names */ for (dmdp = DEVI(dip)->devi_minor; dmdp; dmdp = dmdp->next) { /* Skip non-minors, and non matching minor names */ if ((dmdp->type != DDM_MINOR) || ((minor_all == 0) && strcmp(dmdp->ddm_name, minor_name))) continue; /* filter out minor_all mismatches */ if (minor_all && (((minor_name == DEVID_MINOR_NAME_ALL_CHR) && (dmdp->ddm_spec_type != S_IFCHR)) || ((minor_name == DEVID_MINOR_NAME_ALL_BLK) && (dmdp->ddm_spec_type != S_IFBLK)))) continue; if (ndevts < ndevts_alloced) devtsp[ndevts] = dmdp->ddm_dev; ndevts++; } mutex_exit(&(DEVI(dip)->devi_lock)); *devtcntp = ndevts; }
int xen_suspend_devices(dev_info_t *dip) { int error; char buf[XPV_BUFSIZE]; SUSPEND_DEBUG("xen_suspend_devices\n"); for (; dip != NULL; dip = ddi_get_next_sibling(dip)) { if (xen_suspend_devices(ddi_get_child(dip))) return (ENXIO); if (ddi_get_driver(dip) == NULL) continue; SUSPEND_DEBUG("Suspending device %s\n", ddi_deviname(dip, buf)); ASSERT((DEVI(dip)->devi_cpr_flags & DCF_CPR_SUSPENDED) == 0); if (!i_ddi_devi_attached(dip)) { error = DDI_FAILURE; } else { error = devi_detach(dip, DDI_SUSPEND); } if (error == DDI_SUCCESS) { DEVI(dip)->devi_cpr_flags |= DCF_CPR_SUSPENDED; } else { SUSPEND_DEBUG("WARNING: Unable to suspend device %s\n", ddi_deviname(dip, buf)); cmn_err(CE_WARN, "Unable to suspend device %s.", ddi_deviname(dip, buf)); cmn_err(CE_WARN, "Device is busy or does not " "support suspend/resume."); return (ENXIO); } } return (0); }
int xen_resume_devices(dev_info_t *start, int resume_failed) { dev_info_t *dip, *next, *last = NULL; int did_suspend; int error = resume_failed; char buf[XPV_BUFSIZE]; SUSPEND_DEBUG("xen_resume_devices\n"); while (last != start) { dip = start; next = ddi_get_next_sibling(dip); while (next != last) { dip = next; next = ddi_get_next_sibling(dip); } /* * cpr is the only one that uses this field and the device * itself hasn't resumed yet, there is no need to use a * lock, even though kernel threads are active by now. */ did_suspend = DEVI(dip)->devi_cpr_flags & DCF_CPR_SUSPENDED; if (did_suspend) DEVI(dip)->devi_cpr_flags &= ~DCF_CPR_SUSPENDED; /* * There may be background attaches happening on devices * that were not originally suspended by cpr, so resume * only devices that were suspended by cpr. Also, stop * resuming after the first resume failure, but traverse * the entire tree to clear the suspend flag. */ if (did_suspend && !error) { SUSPEND_DEBUG("Resuming device %s\n", ddi_deviname(dip, buf)); /* * If a device suspended by cpr gets detached during * the resume process (for example, due to hotplugging) * before cpr gets around to issuing it a DDI_RESUME, * we'll have problems. */ if (!i_ddi_devi_attached(dip)) { cmn_err(CE_WARN, "Skipping %s, device " "not ready for resume", ddi_deviname(dip, buf)); } else { if (devi_attach(dip, DDI_RESUME) != DDI_SUCCESS) { error = ENXIO; } } } if (error == ENXIO) { cmn_err(CE_WARN, "Unable to resume device %s", ddi_deviname(dip, buf)); } error = xen_resume_devices(ddi_get_child(dip), error); last = dip; } return (error); }