⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 driver.c

📁 omap3 linux 2.6 用nocc去除了冗余代码
💻 C
📖 第 1 页 / 共 3 页
字号:
 * The caller must hold @udev->pm_mutex. * * This routine can run only in process context. */static int usb_suspend_both(struct usb_device *udev, pm_message_t msg){	int			status = 0;	int			i = 0;	struct usb_interface	*intf;	struct usb_device	*parent = udev->parent;	if (udev->state == USB_STATE_NOTATTACHED ||			udev->state == USB_STATE_SUSPENDED)		goto done;	udev->do_remote_wakeup = device_may_wakeup(&udev->dev);	if (udev->auto_pm) {		status = autosuspend_check(udev);		if (status < 0)			goto done;	}	/* Suspend all the interfaces and then udev itself */	if (udev->actconfig) {		for (; i < udev->actconfig->desc.bNumInterfaces; i++) {			intf = udev->actconfig->interface[i];			status = usb_suspend_interface(intf, msg);			if (status != 0)				break;		}	}	if (status == 0)		status = usb_suspend_device(udev, msg);	/* If the suspend failed, resume interfaces that did get suspended */	if (status != 0) {		while (--i >= 0) {			intf = udev->actconfig->interface[i];			usb_resume_interface(intf);		}		/* Try another autosuspend when the interfaces aren't busy */		if (udev->auto_pm)			autosuspend_check(udev);	/* If the suspend succeeded, propagate it up the tree */	} else {		cancel_delayed_work(&udev->autosuspend);		if (parent)			usb_autosuspend_device(parent);	} done:	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);	return status;}/** * usb_resume_both - resume a USB device and its interfaces * @udev: the usb_device to resume * * This is the central routine for resuming USB devices.  It calls the * the resume method for @udev and then calls the resume methods for all * the interface drivers in @udev. * * Before starting the resume, the routine calls itself recursively for * the parent device of @udev, thereby propagating the change up the device * tree and assuring that @udev will be able to resume.  If the parent is * unable to resume successfully, the routine fails. * * The resume method calls are subject to mutual exclusion under control * of @udev's pm_mutex.  Many of these calls are also under the protection * of @udev's device lock (including all requests originating outside the * USB subsystem), but autoresume requests generated by a child device or * interface driver may not be.  Usbcore will insure that the method calls * do not arrive during bind, unbind, or reset operations.  However, drivers * must be prepared to handle resume calls arriving at unpredictable times. * The only way to block such calls is to do an autoresume (preventing * other autoresumes) while holding @udev's device lock (preventing outside * resumes). * * The caller must hold @udev->pm_mutex. * * This routine can run only in process context. */static int usb_resume_both(struct usb_device *udev){	int			status = 0;	int			i;	struct usb_interface	*intf;	struct usb_device	*parent = udev->parent;	cancel_delayed_work(&udev->autosuspend);	if (udev->state == USB_STATE_NOTATTACHED) {		status = -ENODEV;		goto done;	}	/* Propagate the resume up the tree, if necessary */	if (udev->state == USB_STATE_SUSPENDED) {		if (udev->auto_pm && udev->autoresume_disabled) {			status = -EPERM;			goto done;		}		if (parent) {			status = usb_autoresume_device(parent);			if (status == 0) {				status = usb_resume_device(udev);				if (status) {					usb_autosuspend_device(parent);					/* It's possible usb_resume_device()					 * failed after the port was					 * unsuspended, causing udev to be					 * logically disconnected.  We don't					 * want usb_disconnect() to autosuspend					 * the parent again, so tell it that					 * udev disconnected while still					 * suspended. */					if (udev->state ==							USB_STATE_NOTATTACHED)						udev->discon_suspended = 1;				}			}		} else {			/* We can't progagate beyond the USB subsystem,			 * so if a root hub's controller is suspended			 * then we're stuck. */			if (udev->dev.parent->power.power_state.event !=					PM_EVENT_ON)				status = -EHOSTUNREACH;			else				status = usb_resume_device(udev); 		}	} else {		/* Needed only for setting udev->dev.power.power_state.event		 * and for possible debugging message. */		status = usb_resume_device(udev);	}	if (status == 0 && udev->actconfig) {		for (i = 0; i < udev->actconfig->desc.bNumInterfaces; i++) {			intf = udev->actconfig->interface[i];			usb_resume_interface(intf);		}	} done:	// dev_dbg(&udev->dev, "%s: status %d\n", __FUNCTION__, status);	return status;}/* Internal routine to adjust a device's usage counter and change * its autosuspend state. */static int usb_autopm_do_device(struct usb_device *udev, int inc_usage_cnt){	int	status = 0;	usb_pm_lock(udev);	udev->auto_pm = 1;	udev->pm_usage_cnt += inc_usage_cnt;	WARN_ON(udev->pm_usage_cnt < 0);	if (inc_usage_cnt >= 0 && udev->pm_usage_cnt > 0) {		if (udev->state == USB_STATE_SUSPENDED)			status = usb_resume_both(udev);		if (status != 0)			udev->pm_usage_cnt -= inc_usage_cnt;		else if (inc_usage_cnt)			udev->last_busy = jiffies;	} else if (inc_usage_cnt <= 0 && udev->pm_usage_cnt <= 0) {		if (inc_usage_cnt)			udev->last_busy = jiffies;		status = usb_suspend_both(udev, PMSG_SUSPEND);	}	usb_pm_unlock(udev);	return status;}/* usb_autosuspend_work - callback routine to autosuspend a USB device */void usb_autosuspend_work(struct work_struct *work){	struct usb_device *udev =		container_of(work, struct usb_device, autosuspend.work);	usb_autopm_do_device(udev, 0);}/** * usb_autosuspend_device - delayed autosuspend of a USB device and its interfaces * @udev: the usb_device to autosuspend * * This routine should be called when a core subsystem is finished using * @udev and wants to allow it to autosuspend.  Examples would be when * @udev's device file in usbfs is closed or after a configuration change. * * @udev's usage counter is decremented.  If it or any of the usage counters * for an active interface is greater than 0, no autosuspend request will be * queued.  (If an interface driver does not support autosuspend then its * usage counter is permanently positive.)  Furthermore, if an interface * driver requires remote-wakeup capability during autosuspend but remote * wakeup is disabled, the autosuspend will fail. * * Often the caller will hold @udev's device lock, but this is not * necessary. * * This routine can run only in process context. */void usb_autosuspend_device(struct usb_device *udev){	int	status;	status = usb_autopm_do_device(udev, -1);	// dev_dbg(&udev->dev, "%s: cnt %d\n",	//		__FUNCTION__, udev->pm_usage_cnt);}/** * usb_try_autosuspend_device - attempt an autosuspend of a USB device and its interfaces * @udev: the usb_device to autosuspend * * This routine should be called when a core subsystem thinks @udev may * be ready to autosuspend. * * @udev's usage counter left unchanged.  If it or any of the usage counters * for an active interface is greater than 0, or autosuspend is not allowed * for any other reason, no autosuspend request will be queued. * * This routine can run only in process context. */void usb_try_autosuspend_device(struct usb_device *udev){	usb_autopm_do_device(udev, 0);	// dev_dbg(&udev->dev, "%s: cnt %d\n",	// 		__FUNCTION__, udev->pm_usage_cnt);}/** * usb_autoresume_device - immediately autoresume a USB device and its interfaces * @udev: the usb_device to autoresume * * This routine should be called when a core subsystem wants to use @udev * and needs to guarantee that it is not suspended.  No autosuspend will * occur until usb_autosuspend_device is called.  (Note that this will not * prevent suspend events originating in the PM core.)  Examples would be * when @udev's device file in usbfs is opened or when a remote-wakeup * request is received. * * @udev's usage counter is incremented to prevent subsequent autosuspends. * However if the autoresume fails then the usage counter is re-decremented. * * Often the caller will hold @udev's device lock, but this is not * necessary (and attempting it might cause deadlock). * * This routine can run only in process context. */int usb_autoresume_device(struct usb_device *udev){	int	status;	status = usb_autopm_do_device(udev, 1);	// dev_dbg(&udev->dev, "%s: status %d cnt %d\n",	//		__FUNCTION__, status, udev->pm_usage_cnt);	return status;}/* Internal routine to adjust an interface's usage counter and change * its device's autosuspend state. */static int usb_autopm_do_interface(struct usb_interface *intf,		int inc_usage_cnt){	struct usb_device	*udev = interface_to_usbdev(intf);	int			status = 0;	usb_pm_lock(udev);	if (intf->condition == USB_INTERFACE_UNBOUND)		status = -ENODEV;	else {		udev->auto_pm = 1;		intf->pm_usage_cnt += inc_usage_cnt;		if (inc_usage_cnt >= 0 && intf->pm_usage_cnt > 0) {			if (udev->state == USB_STATE_SUSPENDED)				status = usb_resume_both(udev);			if (status != 0)				intf->pm_usage_cnt -= inc_usage_cnt;			else if (inc_usage_cnt)				udev->last_busy = jiffies;		} else if (inc_usage_cnt <= 0 && intf->pm_usage_cnt <= 0) {			if (inc_usage_cnt)				udev->last_busy = jiffies;			status = usb_suspend_both(udev, PMSG_SUSPEND);		}	}	usb_pm_unlock(udev);	return status;}/** * usb_autopm_put_interface - decrement a USB interface's PM-usage counter * @intf: the usb_interface whose counter should be decremented * * This routine should be called by an interface driver when it is * finished using @intf and wants to allow it to autosuspend.  A typical * example would be a character-device driver when its device file is * closed. * * The routine decrements @intf's usage counter.  When the counter reaches * 0, a delayed autosuspend request for @intf's device is queued.  When * the delay expires, if @intf->pm_usage_cnt is still <= 0 along with all * the other usage counters for the sibling interfaces and @intf's * usb_device, the device and all its interfaces will be autosuspended. * * Note that @intf->pm_usage_cnt is owned by the interface driver.  The * core will not change its value other than the increment and decrement * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver * may use this simple counter-oriented discipline or may set the value * any way it likes. * * If the driver has set @intf->needs_remote_wakeup then autosuspend will * take place only if the device's remote-wakeup facility is enabled. * * Suspend method calls queued by this routine can arrive at any time * while @intf is resumed and its usage counter is equal to 0.  They are * not protected by the usb_device's lock but only by its pm_mutex. * Drivers must provide their own synchronization. * * This routine can run only in process context. */void usb_autopm_put_interface(struct usb_interface *intf){	int	status;	status = usb_autopm_do_interface(intf, -1);	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",	//		__FUNCTION__, status, intf->pm_usage_cnt);}EXPORT_SYMBOL_GPL(usb_autopm_put_interface);/** * usb_autopm_get_interface - increment a USB interface's PM-usage counter * @intf: the usb_interface whose counter should be incremented * * This routine should be called by an interface driver when it wants to * use @intf and needs to guarantee that it is not suspended.  In addition, * the routine prevents @intf from being autosuspended subsequently.  (Note * that this will not prevent suspend events originating in the PM core.) * This prevention will persist until usb_autopm_put_interface() is called * or @intf is unbound.  A typical example would be a character-device * driver when its device file is opened. * * * The routine increments @intf's usage counter.  (However if the * autoresume fails then the counter is re-decremented.)  So long as the * counter is greater than 0, autosuspend will not be allowed for @intf * or its usb_device.  When the driver is finished using @intf it should * call usb_autopm_put_interface() to decrement the usage counter and * queue a delayed autosuspend request (if the counter is <= 0). * * * Note that @intf->pm_usage_cnt is owned by the interface driver.  The * core will not change its value other than the increment and decrement * in usb_autopm_get_interface and usb_autopm_put_interface.  The driver * may use this simple counter-oriented discipline or may set the value * any way it likes. * * Resume method calls generated by this routine can arrive at any time * while @intf is suspended.  They are not protected by the usb_device's * lock but only by its pm_mutex.  Drivers must provide their own * synchronization. * * This routine can run only in process context. */int usb_autopm_get_interface(struct usb_interface *intf){	int	status;	status = usb_autopm_do_interface(intf, 1);	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",	//		__FUNCTION__, status, intf->pm_usage_cnt);	return status;}EXPORT_SYMBOL_GPL(usb_autopm_get_interface);/** * usb_autopm_set_interface - set a USB interface's autosuspend state * @intf: the usb_interface whose state should be set * * This routine sets the autosuspend state of @intf's device according * to @intf's usage counter, which the caller must have set previously. * If the counter is <= 0, the device is autosuspended (if it isn't * already suspended and if nothing else prevents the autosuspend).  If * the counter is > 0, the device is autoresumed (if it isn't already * awake). */int usb_autopm_set_interface(struct usb_interface *intf){	int	status;	status = usb_autopm_do_interface(intf, 0);	// dev_dbg(&intf->dev, "%s: status %d cnt %d\n",	//		__FUNCTION__, status, intf->pm_usage_cnt);	return status;}EXPORT_SYMBOL_GPL(usb_autopm_set_interface);/** * usb_external_suspend_device - external suspend of a USB device and its interfaces * @udev: the usb_device to suspend * @msg: Power Management message describing this state transition * * This routine handles external suspend requests: ones not generated * internally by a USB driver (autosuspend) but rather coming from the user * (via sysfs) or the PM core (system sleep).  The suspend will be carried * out regardless of @udev's usage counter or those of its interfaces, * and regardless of whether or not remote wakeup is enabled.  Of course, * interface drivers still have the option of failing the suspend (if * there are unsuspended children, for example). * * The caller must hold @udev's device lock. */int usb_external_suspend_device(struct usb_device *udev, pm_message_t msg){	int	status;	usb_pm_lock(udev);	udev->auto_pm = 0;	status = usb_suspend_both(udev, msg);	usb_pm_unlock(udev);	return status;}/** * usb_external_resume_device - external resume of a USB device and its interfaces * @udev: the usb_device to resume * * This routine handles external resume requests: ones not generated * internally by a USB driver (autoresume) but rather coming from the user * (via sysfs), the PM core (system resume), or the device itself (remote * wakeup).  @udev's usage counter is unaffected. * * The caller must hold @udev's device lock. */int usb_external_resume_device(struct usb_device *udev){	int	status;	usb_pm_lock(udev);	udev->auto_pm = 0;	status = usb_resume_both(udev);	udev->last_busy = jiffies;	usb_pm_unlock(udev);	/* Now that the device is awake, we can start trying to autosuspend	 * it again. */	if (status == 0)		usb_try_autosuspend_device(udev);	return status;}static int usb_suspend(struct device *dev, pm_message_t message){	if (!is_usb_device(dev))	/* Ignore PM for interfaces */		return 0;	return usb_external_suspend_device(to_usb_device(dev), message);}static int usb_resume(struct device *dev){	struct usb_device	*udev;	if (!is_usb_device(dev))	/* Ignore PM for interfaces */		return 0;	udev = to_usb_device(dev);	if (udev->autoresume_disabled)		return -EPERM;	return usb_external_resume_device(udev);}struct bus_type usb_bus_type = {	.name =		"usb",	.match =	usb_device_match,	.uevent =	usb_uevent,	.suspend =	usb_suspend,	.resume =	usb_resume,};

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -