/*
 * Starting from the root node suspend all devices in the device tree.
 * Assumes that all devices have already been marked busy.
 */
static int
sbdp_suspend_devices_(dev_info_t *dip, sbdp_sr_handle_t *srh)
{
	major_t	major;
	char	*dname;

	for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
		char	d_name[40], d_alias[40], *d_info;

		if (sbdp_suspend_devices_(ddi_get_child(dip), srh)) {
			return (ENXIO);
		}

		if (!sbdp_is_real_device(dip))
			continue;

		major = (major_t)-1;
		if ((dname = DEVI(dip)->devi_binding_name) != NULL)
			major = ddi_name_to_major(dname);

#ifdef DEBUG
		if (sbdp_bypass_device(dname)) {
			SBDP_DBG_QR("bypassed suspend of %s (major# %d)\n",
			    dname, major);
			continue;
		}
#endif

		if ((d_info = ddi_get_name_addr(dip)) == NULL)
			d_info = "<null>";

		d_name[0] = 0;
		if (sbdp_resolve_devname(dip, d_name, d_alias) == 0) {
			if (d_alias[0] != 0) {
				SBDP_DBG_QR("\tsuspending %s@%s (aka %s)\n",
					d_name, d_info, d_alias);
			} else {
				SBDP_DBG_QR("\tsuspending %s@%s\n",
					d_name, d_info);
			}
		} else {
			SBDP_DBG_QR("\tsuspending %s@%s\n", dname, d_info);
		}

		if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
			(void) sprintf(sbdp_get_err_buf(&srh->sep),
			    "%d", major);

			sbdp_set_err(&srh->sep, ESGT_SUSPEND, NULL);
			ndi_hold_devi(dip);
			SR_FAILED_DIP(srh) = dip;
			return (DDI_FAILURE);
		}
	}

	return (DDI_SUCCESS);
}
Beispiel #2
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);
}
Beispiel #3
0
/*
 * The "dip" argument's parent (if it exists) must be held busy.
 */
static int
dr_suspend_devices(dev_info_t *dip, dr_sr_handle_t *srh)
{
	dr_handle_t	*handle;
	major_t		major;
	char		*dname;
	int		circ;

	/*
	 * If dip is the root node, it has no siblings and it is
	 * always held. If dip is not the root node, dr_suspend_devices()
	 * will be invoked with the parent held busy.
	 */
	for (; dip != NULL; dip = ddi_get_next_sibling(dip)) {
		char	d_name[40], d_alias[40], *d_info;

		ndi_devi_enter(dip, &circ);
		if (dr_suspend_devices(ddi_get_child(dip), srh)) {
			ndi_devi_exit(dip, circ);
			return (ENXIO);
		}
		ndi_devi_exit(dip, circ);

		if (!dr_is_real_device(dip))
			continue;

		major = (major_t)-1;
		if ((dname = ddi_binding_name(dip)) != NULL)
			major = ddi_name_to_major(dname);

		if (dr_bypass_device(dname)) {
			PR_QR(" bypassed suspend of %s (major# %d)\n", dname,
				major);
			continue;
		}

		if (drmach_verify_sr(dip, 1)) {
			PR_QR(" bypassed suspend of %s (major# %d)\n", dname,
				major);
			continue;
		}

		if ((d_info = ddi_get_name_addr(dip)) == NULL)
			d_info = "<null>";

		d_name[0] = 0;
		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);
			} else {
				prom_printf("\tsuspending %s@%s\n",
					d_name, d_info);
			}
		} else {
			prom_printf("\tsuspending %s@%s\n", dname, d_info);
		}

		if (devi_detach(dip, DDI_SUSPEND) != DDI_SUCCESS) {
			prom_printf("\tFAILED to suspend %s@%s\n",
				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);

			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);

			return (DDI_FAILURE);
		}
	}

	return (DDI_SUCCESS);
}