Example #1
0
/* 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);
}
Example #2
0
/*
 * 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;
}
Example #3
0
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);
}
Example #4
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);
}