static void
wusb_df_pm_busy_component(wusb_df_state_t *wusb_dfp)
{
	ASSERT(!mutex_owned(&wusb_dfp->wusb_df_mutex));

	mutex_enter(&wusb_dfp->wusb_df_mutex);
	if (wusb_dfp->wusb_df_pm == NULL) {
		USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
		    "wusb_df_pm_busy_component: pm = NULL");
		goto done;
	}

	wusb_dfp->wusb_df_pm->wusb_df_pm_busy++;
	USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
	    "wusb_df_pm_busy_component: %d",
	    wusb_dfp->wusb_df_pm->wusb_df_pm_busy);

	mutex_exit(&wusb_dfp->wusb_df_mutex);

	if (pm_busy_component(wusb_dfp->wusb_df_dip, 0) != DDI_SUCCESS) {
		mutex_enter(&wusb_dfp->wusb_df_mutex);
		wusb_dfp->wusb_df_pm->wusb_df_pm_busy--;

		USB_DPRINTF_L4(PRINT_MASK_PM, wusb_dfp->wusb_df_log_hdl,
		    "wusb_df_pm_busy_component: %d",
		    wusb_dfp->wusb_df_pm->wusb_df_pm_busy);
		mutex_exit(&wusb_dfp->wusb_df_mutex);


	}
	return;
done:
		mutex_exit(&wusb_dfp->wusb_df_mutex);

}
Exemple #2
0
static void
usba_async_req_raise_power(void *arg)
{
	usba_pm_req_t *pmrq = (usba_pm_req_t *)arg;
	int rval;

	/*
	 * To eliminate race condition between the call to power entry
	 * point and our call to raise power level, we first mark the
	 * component busy and later idle
	 */
	(void) pm_busy_component(pmrq->dip, pmrq->comp);
	rval = pm_raise_power(pmrq->dip, pmrq->comp, pmrq->level);
	(void) pm_idle_component(pmrq->dip, pmrq->comp);
	pmrq->cb(pmrq->arg, rval);

	/* We are done with pmrq. Free it now */
	kmem_free(pmrq, sizeof (usba_pm_req_t));
}
/*
 * mark device busy and raise power
 */
static int
uftdi_pm_set_busy(uftdi_state_t *uf)
{
	uftdi_pm_t	*pm = uf->uf_pm;
	dev_info_t	*dip = uf->uf_dip;
	int		rval;

	USB_DPRINTF_L4(DPRINT_PM, uf->uf_lh, "uftdi_pm_set_busy");

	if (!pm)
		return (USB_SUCCESS);

	mutex_enter(&uf->uf_lock);
	/* if already marked busy, just increment the counter */
	if (pm->pm_busy_cnt++ > 0) {
		mutex_exit(&uf->uf_lock);
		return (USB_SUCCESS);
	}

	rval = pm_busy_component(dip, 0);
	ASSERT(rval == DDI_SUCCESS);

	if (pm->pm_cur_power == USB_DEV_OS_FULL_PWR) {
		mutex_exit(&uf->uf_lock);
		return (USB_SUCCESS);
	}

	/* need to raise power	*/
	pm->pm_raise_power = B_TRUE;
	mutex_exit(&uf->uf_lock);

	rval = pm_raise_power(dip, 0, USB_DEV_OS_FULL_PWR);
	if (rval != DDI_SUCCESS) {
		USB_DPRINTF_L2(DPRINT_PM, uf->uf_lh, "raising power failed");
	}

	mutex_enter(&uf->uf_lock);
	pm->pm_raise_power = B_FALSE;
	mutex_exit(&uf->uf_lock);

	return (USB_SUCCESS);
}
Exemple #4
0
/*ARGSUSED*/
static int
gen_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *credp, int *rvalp)
{
	struct dstate *dstatep;
	ddi_eventcookie_t cookie;
	int instance;
	int rval = 0;
	char *nodename;
	int i;
	struct devctl_iocdata *dcp;
	uint_t state;
	int ret;
	int level_tmp;

	instance = MINOR_TO_INST(getminor(dev));
	dstatep = ddi_get_soft_state(dstates, instance);
	nodename = dstatep->nodename;

	if (dstatep == NULL)
		return (ENXIO);

	/*
	 * read devctl ioctl data
	 */
	if (ndi_dc_allochdl((void *)arg, &dcp) != NDI_SUCCESS)
		return (EFAULT);

	switch (cmd) {
	case GENDRV_IOFAULT_SIMULATE:
		if (ddi_get_eventcookie(dstatep->dip, DDI_DEVI_FAULT_EVENT,
			    &(cookie)) != NDI_SUCCESS)
			return (DDI_FAILURE);

		return (ndi_post_event(dstatep->dip, dstatep->dip, cookie,
			    NULL));

	case GENDRV_NDI_EVENT_TEST:
		if (ddi_get_eventcookie(dstatep->dip, "pshot_dev_offline",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_dev_reset",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_reset",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_quiesce",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_unquiesce",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		if (ddi_get_eventcookie(dstatep->dip, "pshot_bus_test_post",
		    &cookie) == NDI_SUCCESS) {
			(void) ndi_post_event(dstatep->dip, dstatep->dip,
			    cookie, NULL);
		}

		break;

	case DEVCTL_PM_PWR_HAS_CHANGED_ON_RESUME:
		/*
		 * Issue pm_power_has_changed() call on DDI_RESUME
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag |= PWR_HAS_CHANGED_ON_RESUME_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d:"
		    " DEVCTL_PM_PWR_HAS_CHANGED_ON_RESUME", nodename,
		    instance));

		break;

	case DEVCTL_PM_FAIL_SUSPEND:
		/*
		 * Fail the suspend attempt in DDI_SUSPEND
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag |= FAIL_SUSPEND_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_FAIL_SUSPEND",
		    nodename, instance));

		break;

	case DEVCTL_PM_PUP_WITH_PWR_HAS_CHANGED:
		/*
		 * Use pm_power_has_changed() to power up comp 0 when
		 * enforcing the comp 0 vs comp-not 0 dependency:
		 * Power up comp 0 first, if request for comp-not-0
		 * comes in.
		 * Else, default to pm_raise_power().
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag |= PUP_WITH_PWR_HAS_CHANGED_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_PUP_WITH_PWR_HAS_CHANGED",
		    nodename, instance));

		break;

	case DEVCTL_PM_BUSY_COMP:
		/*
		 * mark component 0 busy via a pm_busy_component() call.
		 * update the busy[] array.
		 */
		mutex_enter(&dstatep->lock);
		++dstatep->busy[0];
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_BUSY_COMP: comp 0:"
		    " busy=%d", nodename, instance, dstatep->busy[0]));
		mutex_exit(&dstatep->lock);
		ret = pm_busy_component(dstatep->dip, 0);
		ASSERT(ret == DDI_SUCCESS);

		break;

	case DEVCTL_PM_BUSY_COMP_TEST:
		/*
		 * test busy state on component 0
		 */
		mutex_enter(&dstatep->lock);
		state = dstatep->busy[0];
		if (copyout(&state, dcp->cpyout_buf,
		    sizeof (uint_t)) != 0) {
			cmn_err(CE_WARN, "%s%d:"
			    " DEVCTL_PM_BUSY_COMP_TEST: copyout failed\n",
			    nodename, instance);
			rval = EINVAL;
		}
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_BUSY_COMP_TEST:"
		    " comp 0 busy %d",
		    nodename, instance, state));
		mutex_exit(&dstatep->lock);

		break;

	case DEVCTL_PM_IDLE_COMP:
		/*
		 * mark component 0 idle via a pm_idle_component() call.
		 * NOP if dstatep->busy[0] == 0.
		 */
		mutex_enter(&dstatep->lock);
		if (dstatep->busy[0] > 0) {
			--dstatep->busy[0];
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_IDLE_COMP:"
			    " comp 0: busy=%d", nodename, instance,
			    dstatep->busy[0]));
			mutex_exit(&dstatep->lock);
			ret = pm_idle_component(dstatep->dip, 0);
			ASSERT(ret == DDI_SUCCESS);
		} else {
			mutex_exit(&dstatep->lock);
		}

		break;

	case DEVCTL_PM_PROM_PRINTF:
		(void) prom_printf("%s%d: PROM_PRINTF FROM GEN_DRV\n",
		    nodename, instance);

		break;

	case DEVCTL_PM_RAISE_PWR:
		/*
		 * power up both components to MAXPWR via
		 * pm_raise_power() calls. this ioctl() cmd
		 * assumes that the current level is 0
		 */
		for (i = 0; i < COMPONENTS; i++) {
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_RAISE_PWR:"
			    " comp %d old 0 new %d",
			    nodename, instance, i, maxpwr[i]));
			if (pm_raise_power(dstatep->dip, 0, maxpwr[i])
			    != DDI_SUCCESS) {
				rval = EINVAL;
			}
		}

		break;

	case DEVCTL_PM_CHANGE_PWR_LOW:
		/*
		 * power off both components via pm_power_has_changed() calls
		 */
		for (i = (COMPONENTS - 1); i >= 0; --i) {
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_CHANGE_PWR_LOW:"
			    " comp %d new 0",
			    nodename, instance, i));
			mutex_enter(&dstatep->lock);
			level_tmp = dstatep->level[i];
			dstatep->level[i] = 0;
			if (pm_power_has_changed(dstatep->dip, i, 0)
			    != DDI_SUCCESS) {
				dstatep->level[i] = level_tmp;
				rval = EINVAL;
			}
			mutex_exit(&dstatep->lock);
		}

		break;

	case DEVCTL_PM_CHANGE_PWR_HIGH:
		/*
		 * power up both components to MAXPWR via
		 * pm_power_has_changed() calls
		 */
		for (i = 0; i < COMPONENTS; i++) {
			GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_CHANGE_PWR_HIGH:"
			    " comp %d new %d",
			    nodename, instance, i, maxpwr[i]));
			mutex_enter(&dstatep->lock);
			level_tmp = dstatep->level[i];
			dstatep->level[i] = maxpwr[i];
			if (pm_power_has_changed(dstatep->dip, i, maxpwr[i])
			    != DDI_SUCCESS) {
				dstatep->level[i] = level_tmp;
				rval = EINVAL;
			}
			mutex_exit(&dstatep->lock);
		}

		break;

	case DEVCTL_PM_POWER:
		/*
		 * test if the gen_drv_power() routine has been called,
		 * then clear
		 */
		mutex_enter(&dstatep->lock);
		state = (dstatep->flag & POWER_FLAG) ? 1 : 0;
		if (copyout(&state, dcp->cpyout_buf,
		    sizeof (uint_t)) != 0) {
			cmn_err(CE_WARN, "%s%d: DEVCTL_PM_POWER:"
			    " copyout failed\n", nodename, instance);
			rval = EINVAL;
		}
		GEN_DEBUG((CE_CONT, "%s%d: %s POWER_FLAG: %d",
		    nodename, instance, "DEVCTL_PM_POWER", state));
		dstatep->flag &= ~POWER_FLAG;
		mutex_exit(&dstatep->lock);
		break;

	case DEVCTL_PM_NO_LOWER_POWER:
		/*
		 * issue to not invoke pm_lower_power() on detach
		 */
		mutex_enter(&dstatep->lock);
		dstatep->flag &= ~LOWER_POWER_FLAG;
		mutex_exit(&dstatep->lock);
		GEN_DEBUG((CE_CONT, "%s%d: DEVCTL_PM_NO_LOWER_POWER",
			    nodename, instance));
		break;

	default:
		return (ENOTTY);
	}

	return (rval);
}