Ejemplo n.º 1
0
static int wdm_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct wdm_device *desc = usb_get_intfdata(intf);
	int rv = 0;

	dev_dbg(&desc->intf->dev, "wdm%d_suspend\n", intf->minor);

	/* if this is an autosuspend the caller does the locking */
	if (!PMSG_IS_AUTO(message))
		mutex_lock(&desc->lock);
	spin_lock_irq(&desc->iuspin);

	if (PMSG_IS_AUTO(message) &&
			(test_bit(WDM_IN_USE, &desc->flags)
			|| test_bit(WDM_RESPONDING, &desc->flags))) {
		spin_unlock_irq(&desc->iuspin);
		rv = -EBUSY;
	} else {

		set_bit(WDM_SUSPENDING, &desc->flags);
		spin_unlock_irq(&desc->iuspin);
		/* callback submits work - order is essential */
		kill_urbs(desc);
		cancel_work_sync(&desc->rxwork);
	}
	if (!PMSG_IS_AUTO(message))
		mutex_unlock(&desc->lock);

	return rv;
}
Ejemplo n.º 2
0
static int btusb_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct btusb_data *data = usb_get_intfdata(intf);

	BT_DBG("intf %p", intf);

	if (data->suspend_count++)
		return 0;

	spin_lock_irq(&data->txlock);
	if (!(PMSG_IS_AUTO(message) && data->tx_in_flight)) {
		set_bit(BTUSB_SUSPENDING, &data->flags);
		spin_unlock_irq(&data->txlock);
	} else {
		spin_unlock_irq(&data->txlock);
		data->suspend_count--;
		return -EBUSY;
	}

	cancel_work_sync(&data->work);

	btusb_stop_traffic(data);
	usb_kill_anchored_urbs(&data->tx_anchor);

	return 0;
}
Ejemplo n.º 3
0
static int acm_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct acm *acm = usb_get_intfdata(intf);
	int cnt;

	if (PMSG_IS_AUTO(message)) {
		int b;

		spin_lock_irq(&acm->write_lock);
		b = acm->transmitting;
		spin_unlock_irq(&acm->write_lock);
		if (b)
			return -EBUSY;
	}

	spin_lock_irq(&acm->read_lock);
	spin_lock(&acm->write_lock);
	cnt = acm->susp_count++;
	spin_unlock(&acm->write_lock);
	spin_unlock_irq(&acm->read_lock);

	if (cnt)
		return 0;

	if (test_bit(ASYNCB_INITIALIZED, &acm->port.flags))
		stop_data_traffic(acm);

	return 0;
}
Ejemplo n.º 4
0
int usbnet_suspend (struct usb_interface *intf, pm_message_t message)
{
	struct usbnet		*dev = usb_get_intfdata(intf);

	if (!dev->suspend_count++) {
		spin_lock_irq(&dev->txq.lock);
		/* don't autosuspend while transmitting */
		if (dev->txq.qlen && PMSG_IS_AUTO(message)) {
			spin_unlock_irq(&dev->txq.lock);
			return -EBUSY;
		} else {
			set_bit(EVENT_DEV_ASLEEP, &dev->flags);
			spin_unlock_irq(&dev->txq.lock);
		}
		/*
		 * accelerate emptying of the rx and queues, to avoid
		 * having everything error out.
		 */
		netif_device_detach (dev->net);
		usbnet_terminate_urbs(dev);
		usb_kill_urb(dev->interrupt);

		/*
		 * reattach so runtime management can use and
		 * wake the device
		 */
		netif_device_attach (dev->net);
	}
	return 0;
}
Ejemplo n.º 5
0
static int acm_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct acm *acm = usb_get_intfdata(intf);
	int cnt;

	spin_lock_irq(&acm->read_lock);
	spin_lock(&acm->write_lock);
	if (PMSG_IS_AUTO(message)) {
		if (acm->transmitting) {
			spin_unlock(&acm->write_lock);
			spin_unlock_irq(&acm->read_lock);
			return -EBUSY;
		}
	}
	cnt = acm->susp_count++;
	spin_unlock(&acm->write_lock);
	spin_unlock_irq(&acm->read_lock);

	if (cnt)
		return 0;

	stop_data_traffic(acm);

	return 0;
}
Ejemplo n.º 6
0
static int acm_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct acm *acm = usb_get_intfdata(intf);
	int cnt;

	if (PMSG_IS_AUTO(message)) {
		int b;

		spin_lock_irq(&acm->write_lock);
		b = acm->transmitting;
		spin_unlock_irq(&acm->write_lock);
		if (b)
			return -EBUSY;
	}

	spin_lock_irq(&acm->read_lock);
	spin_lock(&acm->write_lock);
	cnt = acm->susp_count++;
	spin_unlock(&acm->write_lock);
	spin_unlock_irq(&acm->read_lock);

	if (cnt)
		return 0;
	/*
	we treat opened interfaces differently,
	we must guard against open
	*/
	mutex_lock(&acm->mutex);

	if (acm->port.count)
		stop_data_traffic(acm);

	mutex_unlock(&acm->mutex);
	return 0;
}
Ejemplo n.º 7
0
/*
 * Get the device ready for USB port or system standby and hibernation
 *
 * USB port and system standby are handled the same.
 *
 * When the system hibernates, the USB device is powered down and then
 * up, so we don't really have to do much here, as it will be seen as
 * a reconnect. Still for simplicity we consider this case the same as
 * suspend, so that the device has a chance to do notify the base
 * station (if connected).
 *
 * So at the end, the three cases require common handling.
 *
 * If at the time of this call the device's firmware is not loaded,
 * nothing has to be done. Note we can be "loose" about not reading
 * i2400m->updown under i2400m->init_mutex. If it happens to change
 * inmediately, other parts of the call flow will fail and effectively
 * catch it.
 *
 * If the firmware is loaded, we need to:
 *
 *  - tell the device to go into host interface power save mode, wait
 *    for it to ack
 *
 *    This is quite more interesting than it is; we need to execute a
 *    command, but this time, we don't want the code in usb-{tx,rx}.c
 *    to call the usb_autopm_get/put_interface() barriers as it'd
 *    deadlock, so we need to decrement i2400mu->do_autopm, that acts
 *    as a poor man's semaphore. Ugly, but it works.
 *
 *    As well, the device might refuse going to sleep for whichever
 *    reason. In this case we just fail. For system suspend/hibernate,
 *    we *can't* fail. We check PMSG_IS_AUTO to see if the
 *    suspend call comes from the USB stack or from the system and act
 *    in consequence.
 *
 *  - stop the notification endpoint polling
 */
static
int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
{
	int result = 0;
	struct device *dev = &iface->dev;
	struct i2400mu *i2400mu = usb_get_intfdata(iface);
	unsigned is_autosuspend = 0;
	struct i2400m *i2400m = &i2400mu->i2400m;

#ifdef CONFIG_PM
	if (PMSG_IS_AUTO(pm_msg))
		is_autosuspend = 1;
#endif

	d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event);
	rmb();		/* see i2400m->updown's documentation  */
	if (i2400m->updown == 0)
		goto no_firmware;
	if (i2400m->state == I2400M_SS_DATA_PATH_CONNECTED && is_autosuspend) {
		/* ugh -- the device is connected and this suspend
		 * request is an autosuspend one (not a system standby
		 * / hibernate).
		 *
		 * The only way the device can go to standby is if the
		 * link with the base station is in IDLE mode; that
		 * were the case, we'd be in status
		 * I2400M_SS_CONNECTED_IDLE. But we are not.
		 *
		 * If we *tell* him to go power save now, it'll reset
		 * as a precautionary measure, so if this is an
		 * autosuspend thing, say no and it'll come back
		 * later, when the link is IDLE
		 */
		result = -EBADF;
		d_printf(1, dev, "fw up, link up, not-idle, autosuspend: "
			 "not entering powersave\n");
		goto error_not_now;
	}
	d_printf(1, dev, "fw up: entering powersave\n");
	atomic_dec(&i2400mu->do_autopm);
	result = i2400m_cmd_enter_powersave(i2400m);
	atomic_inc(&i2400mu->do_autopm);
	if (result < 0 && !is_autosuspend) {
		/* System suspend, can't fail */
		dev_err(dev, "failed to suspend, will reset on resume\n");
		result = 0;
	}
	if (result < 0)
		goto error_enter_powersave;
	i2400mu_notification_release(i2400mu);
	d_printf(1, dev, "powersave requested\n");
error_enter_powersave:
error_not_now:
no_firmware:
	d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n",
		iface, pm_msg.event, result);
	return result;
}
Ejemplo n.º 8
0
static
int i2400mu_suspend(struct usb_interface *iface, pm_message_t pm_msg)
{
	int result = 0;
	struct device *dev = &iface->dev;
	struct i2400mu *i2400mu = usb_get_intfdata(iface);
	unsigned is_autosuspend = 0;
	struct i2400m *i2400m = &i2400mu->i2400m;

#ifdef CONFIG_PM
	if (PMSG_IS_AUTO(pm_msg))
		is_autosuspend = 1;
#endif

	d_fnstart(3, dev, "(iface %p pm_msg %u)\n", iface, pm_msg.event);
	rmb();		/*                                     */
	if (i2400m->updown == 0)
		goto no_firmware;
	if (i2400m->state == I2400M_SS_DATA_PATH_CONNECTED && is_autosuspend) {
		/*                                                
                                                        
                  
    
                                                        
                                                     
                                     
                                              
    
                                                       
                                                 
                                                  
                                 
   */
		result = -EBADF;
		d_printf(1, dev, "fw up, link up, not-idle, autosuspend: "
			 "not entering powersave\n");
		goto error_not_now;
	}
	d_printf(1, dev, "fw up: entering powersave\n");
	atomic_dec(&i2400mu->do_autopm);
	result = i2400m_cmd_enter_powersave(i2400m);
	atomic_inc(&i2400mu->do_autopm);
	if (result < 0 && !is_autosuspend) {
		/*                            */
		dev_err(dev, "failed to suspend, will reset on resume\n");
		result = 0;
	}
	if (result < 0)
		goto error_enter_powersave;
	i2400mu_notification_release(i2400mu);
	d_printf(1, dev, "powersave requested\n");
error_enter_powersave:
error_not_now:
no_firmware:
	d_fnend(3, dev, "(iface %p pm_msg %u) = %d\n",
		iface, pm_msg.event, result);
	return result;
}
Ejemplo n.º 9
0
static int picolcd_suspend(struct hid_device *hdev, pm_message_t message)
{
	if (PMSG_IS_AUTO(message))
		return 0;

	picolcd_suspend_backlight(hid_get_drvdata(hdev));
	dbg_hid(PICOLCD_NAME " device ready for suspend\n");
	return 0;
}
Ejemplo n.º 10
0
static int sierra_suspend(struct usb_serial *serial, pm_message_t message)
{
	struct sierra_intf_private *intfdata = usb_get_serial_data(serial);

	spin_lock_irq(&intfdata->susp_lock);
	if (PMSG_IS_AUTO(message)) {
		if (intfdata->in_flight) {
			spin_unlock_irq(&intfdata->susp_lock);
			return -EBUSY;
		}
	}
	intfdata->suspended = 1;
	spin_unlock_irq(&intfdata->susp_lock);

	stop_read_write_urbs(serial);

	return 0;
}
Ejemplo n.º 11
0
static int nfcmrvl_suspend(struct usb_interface *intf, pm_message_t message)
{
	struct nfcmrvl_usb_drv_data *drv_data = usb_get_intfdata(intf);

	nfc_info(&drv_data->udev->dev, "intf %p", intf);

	if (drv_data->suspend_count++)
		return 0;

	spin_lock_irq(&drv_data->txlock);
	if (!(PMSG_IS_AUTO(message) && drv_data->tx_in_flight)) {
		set_bit(NFCMRVL_USB_SUSPENDING, &drv_data->flags);
		spin_unlock_irq(&drv_data->txlock);
	} else {
		spin_unlock_irq(&drv_data->txlock);
		drv_data->suspend_count--;
		return -EBUSY;
	}

	nfcmrvl_usb_stop_traffic(drv_data);
	usb_kill_anchored_urbs(&drv_data->tx_anchor);

	return 0;
}
Ejemplo n.º 12
0
static int dwc3_resume_common(struct dwc3 *dwc, pm_message_t msg)
{
	unsigned long	flags;
	int		ret;
	u32		reg;

	/* Bring core to D0 state */
	dwc3_set_usb_core_power(dwc, true);

	ret = dwc3_core_init(dwc);
	if (ret)
		return ret;

	switch (dwc->current_dr_role) {
	case DWC3_GCTL_PRTCAP_DEVICE:
		ret = dwc3_core_init_for_resume(dwc);
		if (ret)
			return ret;

		dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_DEVICE);
		spin_lock_irqsave(&dwc->lock, flags);
		dwc3_gadget_resume(dwc);
		spin_unlock_irqrestore(&dwc->lock, flags);
		break;
	case DWC3_GCTL_PRTCAP_HOST:
		if (!PMSG_IS_AUTO(msg)) {
			ret = dwc3_core_init_for_resume(dwc);
			if (ret)
				return ret;
			dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_HOST);
			break;
		}
		/* Restore GUSB2PHYCFG bits that were modified in suspend */
		reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
		if (dwc->dis_u2_susphy_quirk)
			reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;

		if (dwc->dis_enblslpm_quirk)
			reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;

		dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);

		phy_pm_runtime_get_sync(dwc->usb2_generic_phy);
		phy_pm_runtime_get_sync(dwc->usb3_generic_phy);
		break;
	case DWC3_GCTL_PRTCAP_OTG:
		/* nothing to do on runtime_resume */
		if (PMSG_IS_AUTO(msg))
			break;

		ret = dwc3_core_init(dwc);
		if (ret)
			return ret;

		dwc3_set_prtcap(dwc, dwc->current_dr_role);

		dwc3_otg_init(dwc);
		if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST) {
			dwc3_otg_host_init(dwc);
		} else if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
			spin_lock_irqsave(&dwc->lock, flags);
			dwc3_gadget_resume(dwc);
			spin_unlock_irqrestore(&dwc->lock, flags);
		}

		break;
	default:
		/* do nothing */
		break;
	}

	return 0;
}
Ejemplo n.º 13
0
static int dwc3_suspend_common(struct dwc3 *dwc, pm_message_t msg)
{
	unsigned long	flags;
	u32 reg;

	switch (dwc->current_dr_role) {
	case DWC3_GCTL_PRTCAP_DEVICE:
		spin_lock_irqsave(&dwc->lock, flags);
		dwc3_gadget_suspend(dwc);
		spin_unlock_irqrestore(&dwc->lock, flags);
		dwc3_core_exit(dwc);
		break;
	case DWC3_GCTL_PRTCAP_HOST:
		if (!PMSG_IS_AUTO(msg)) {
			dwc3_core_exit(dwc);
			break;
		}

		/* Let controller to suspend HSPHY before PHY driver suspends */
		if (dwc->dis_u2_susphy_quirk ||
		    dwc->dis_enblslpm_quirk) {
			reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
			reg |=  DWC3_GUSB2PHYCFG_ENBLSLPM |
				DWC3_GUSB2PHYCFG_SUSPHY;
			dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);

			/* Give some time for USB2 PHY to suspend */
			usleep_range(5000, 6000);
		}

		phy_pm_runtime_put_sync(dwc->usb2_generic_phy);
		phy_pm_runtime_put_sync(dwc->usb3_generic_phy);
		break;
	case DWC3_GCTL_PRTCAP_OTG:
		/* do nothing during runtime_suspend */
		if (PMSG_IS_AUTO(msg))
			break;

		if (dwc->current_otg_role == DWC3_OTG_ROLE_DEVICE) {
			spin_lock_irqsave(&dwc->lock, flags);
			dwc3_gadget_suspend(dwc);
			spin_unlock_irqrestore(&dwc->lock, flags);
		}

		dwc3_otg_exit(dwc);
		dwc3_core_exit(dwc);
		break;
	default:
		/* do nothing */
		break;
	}

	dwc3_event_buffers_cleanup(dwc);

	/* Put the core into D3 state */
	dwc3_set_usb_core_power(dwc, false);

	/*
	 * To avoid reinit of phy during resume, prevent calling the
	 * dwc3_core_exit() when in D3 state
	 */
	if (!dwc->is_d3)
		dwc3_core_exit(dwc);

	return 0;
}