USB: Export URB statistics for powertop
authorSarah Sharp <sarah.a.sharp@intel.com>
Wed, 3 Oct 2007 21:56:03 +0000 (14:56 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 12 Oct 2007 21:55:30 +0000 (14:55 -0700)
powertop currently tracks interrupts generated by uhci, ehci, and ohci,
but it has no way of telling which USB device to blame USB bus activity on.
This patch exports the number of URBs that are submitted for a given device.
Cat the file 'urbnum' in /sys/bus/usb/devices/.../

Signed-off-by: Sarah Sharp <sarah.a.sharp@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/core/hcd.c
drivers/usb/core/sysfs.c
drivers/usb/core/usb.c
include/linux/usb.h

index 2c79aa6ca2b42ba0d67bfeb71b65bf131c4de3ff..3dd997df8505bf3b2f64c7210f71b466b7101746 100644 (file)
@@ -1176,6 +1176,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
         */
        usb_get_urb(urb);
        atomic_inc(&urb->use_count);
+       atomic_inc(&urb->dev->urbnum);
        usbmon_urb_submit(&hcd->self, urb);
 
        /* NOTE requirements on root-hub callers (usbfs and the hub
@@ -1197,6 +1198,7 @@ int usb_hcd_submit_urb (struct urb *urb, gfp_t mem_flags)
                urb->hcpriv = NULL;
                INIT_LIST_HEAD(&urb->urb_list);
                atomic_dec(&urb->use_count);
+               atomic_dec(&urb->dev->urbnum);
                if (urb->reject)
                        wake_up(&usb_kill_urb_queue);
                usb_put_urb(urb);
index e02590297d31599ee739c359ff2626ea2a67141e..b04afd06e502131f97024360fd5e1ad3279af9f4 100644 (file)
@@ -169,6 +169,16 @@ show_quirks(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(quirks, S_IRUGO, show_quirks, NULL);
 
+static ssize_t
+show_urbnum(struct device *dev, struct device_attribute *attr, char *buf)
+{
+       struct usb_device *udev;
+
+       udev = to_usb_device(dev);
+       return sprintf(buf, "%d\n", atomic_read(&udev->urbnum));
+}
+static DEVICE_ATTR(urbnum, S_IRUGO, show_urbnum, NULL);
+
 
 #if defined(CONFIG_USB_PERSIST) || defined(CONFIG_USB_SUSPEND)
 static const char power_group[] = "power";
@@ -458,6 +468,7 @@ static struct attribute *dev_attrs[] = {
        &dev_attr_bConfigurationValue.attr,
        &dev_attr_bmAttributes.attr,
        &dev_attr_bMaxPower.attr,
+       &dev_attr_urbnum.attr,
        /* device attributes */
        &dev_attr_idVendor.attr,
        &dev_attr_idProduct.attr,
index 8121edbd1494022fc734e34c8c345da3adb772dd..c99938d5f78e6299ffacf7c732e20959c94ffc47 100644 (file)
@@ -266,6 +266,7 @@ usb_alloc_dev(struct usb_device *parent, struct usb_bus *bus, unsigned port1)
        dev->dev.dma_mask = bus->controller->dma_mask;
        set_dev_node(&dev->dev, dev_to_node(bus->controller));
        dev->state = USB_STATE_ATTACHED;
+       atomic_set(&dev->urbnum, 0);
 
        INIT_LIST_HEAD(&dev->ep0.urb_list);
        dev->ep0.desc.bLength = USB_DT_ENDPOINT_SIZE;
index e5b35e0dca23bd2916ba697088cdbcc6e0574436..c10935fdc03a4264c894aeef84157e7645b7e201 100644 (file)
@@ -415,6 +415,7 @@ struct usb_device {
 
        int pm_usage_cnt;               /* usage counter for autosuspend */
        u32 quirks;                     /* quirks of the whole device */
+       atomic_t urbnum;                /* number of URBs submitted for the whole device */
 
 #ifdef CONFIG_PM
        struct delayed_work autosuspend; /* for delayed autosuspends */