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,
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to