svn commit: r212135 - head/sys/dev/usb

Andrew Thompson thompsa at FreeBSD.org
Thu Sep 2 04:05:00 UTC 2010


Author: thompsa
Date: Thu Sep  2 04:05:00 2010
New Revision: 212135
URL: http://svn.freebsd.org/changeset/base/212135

Log:
  Add support for power mode filtering as some USB hardware does not support
  power saving.
  
  Submitted by:	Hans Petter Selasky

Modified:
  head/sys/dev/usb/usb_controller.h
  head/sys/dev/usb/usb_device.c
  head/sys/dev/usb/usb_generic.c
  head/sys/dev/usb/usb_hub.c
  head/sys/dev/usb/usbdi.h

Modified: head/sys/dev/usb/usb_controller.h
==============================================================================
--- head/sys/dev/usb/usb_controller.h	Thu Sep  2 04:01:18 2010	(r212134)
+++ head/sys/dev/usb/usb_controller.h	Thu Sep  2 04:05:00 2010	(r212135)
@@ -102,6 +102,10 @@ struct usb_bus_methods {
 	/* Optional transfer polling support */
 
 	void	(*xfer_poll) (struct usb_bus *);
+
+	/* Optional fixed power mode support */
+
+	void	(*get_power_mode) (struct usb_device *udev, int8_t *pmode);
 };
 
 /*

Modified: head/sys/dev/usb/usb_device.c
==============================================================================
--- head/sys/dev/usb/usb_device.c	Thu Sep  2 04:01:18 2010	(r212134)
+++ head/sys/dev/usb/usb_device.c	Thu Sep  2 04:05:00 2010	(r212135)
@@ -1524,7 +1524,7 @@ usb_alloc_device(device_t parent_dev, st
 	 * of USB devices out there that do not work very well with
 	 * automatic suspend and resume!
 	 */
-	udev->power_mode = USB_POWER_MODE_ON;
+	udev->power_mode = usbd_filter_power_mode(udev, USB_POWER_MODE_ON);
 	udev->pwr_save.last_xfer_time = ticks;
 	/* we are not ready yet */
 	udev->refcount = 1;

Modified: head/sys/dev/usb/usb_generic.c
==============================================================================
--- head/sys/dev/usb/usb_generic.c	Thu Sep  2 04:01:18 2010	(r212134)
+++ head/sys/dev/usb/usb_generic.c	Thu Sep  2 04:05:00 2010	(r212135)
@@ -1791,10 +1791,9 @@ ugen_get_power_mode(struct usb_fifo *f)
 {
 	struct usb_device *udev = f->udev;
 
-	if ((udev == NULL) ||
-	    (udev->parent_hub == NULL)) {
+	if (udev == NULL)
 		return (USB_POWER_MODE_ON);
-	}
+
 	return (udev->power_mode);
 }
 

Modified: head/sys/dev/usb/usb_hub.c
==============================================================================
--- head/sys/dev/usb/usb_hub.c	Thu Sep  2 04:01:18 2010	(r212134)
+++ head/sys/dev/usb/usb_hub.c	Thu Sep  2 04:05:00 2010	(r212135)
@@ -2133,12 +2133,39 @@ usbd_set_power_mode(struct usb_device *u
 {
 	/* filter input argument */
 	if ((power_mode != USB_POWER_MODE_ON) &&
-	    (power_mode != USB_POWER_MODE_OFF)) {
+	    (power_mode != USB_POWER_MODE_OFF))
 		power_mode = USB_POWER_MODE_SAVE;
-	}
+
+	power_mode = usbd_filter_power_mode(udev, power_mode);	
+
 	udev->power_mode = power_mode;	/* update copy of power mode */
 
 #if USB_HAVE_POWERD
 	usb_bus_power_update(udev->bus);
 #endif
 }
+
+/*------------------------------------------------------------------------*
+ *	usbd_filter_power_mode
+ *
+ * This function filters the power mode based on hardware requirements.
+ *------------------------------------------------------------------------*/
+uint8_t
+usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode)
+{
+	struct usb_bus_methods *mtod;
+	int8_t temp;
+
+	mtod = udev->bus->methods;
+	temp = -1;
+
+	if (mtod->get_power_mode != NULL)
+		(mtod->get_power_mode) (udev, &temp);
+
+	/* check if we should not filter */
+	if (temp < 0)
+		return (power_mode);
+
+	/* use fixed power mode given by hardware driver */
+	return (temp);
+}

Modified: head/sys/dev/usb/usbdi.h
==============================================================================
--- head/sys/dev/usb/usbdi.h	Thu Sep  2 04:01:18 2010	(r212134)
+++ head/sys/dev/usb/usbdi.h	Thu Sep  2 04:05:00 2010	(r212135)
@@ -479,6 +479,7 @@ void	usbd_set_parent_iface(struct usb_de
 uint8_t	usbd_get_bus_index(struct usb_device *udev);
 uint8_t	usbd_get_device_index(struct usb_device *udev);
 void	usbd_set_power_mode(struct usb_device *udev, uint8_t power_mode);
+uint8_t	usbd_filter_power_mode(struct usb_device *udev, uint8_t power_mode);
 uint8_t	usbd_device_attached(struct usb_device *udev);
 
 void	usbd_xfer_status(struct usb_xfer *xfer, int *actlen, int *sumlen,


More information about the svn-src-head mailing list