Commit 0cfbd328 authored by Michal Sojka's avatar Michal Sojka Committed by Greg Kroah-Hartman

usb: Add LED triggers for USB activity

With this patch, USB activity can be signaled by blinking a LED. There
are two triggers, one for activity on USB host and one for USB gadget.

Both triggers should work with all host/device controllers. Tested only
with musb.

Performace: I measured performance overheads on ARM Cortex-A8 (TI
AM335x) running on 600 MHz.

Duration of usb_led_activity():
- with no LED attached to the trigger:        2 ± 1 µs
- with one GPIO LED attached to the trigger:  2 ± 1 µs or 8 ± 2 µs (two peaks in histogram)

Duration of functions calling usb_led_activity() (with this patch
applied and no LED attached to the trigger):
- __usb_hcd_giveback_urb():    10 - 25 µs
- usb_gadget_giveback_request(): 2 - 6 µs
Signed-off-by: default avatarMichal Sojka <sojka@merica.cz>
Acked-by: default avatarFelipe Balbi <balbi@ti.com>
Tested-by: default avatarFelipe Balbi <balbi@ti.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent aa923ef1
...@@ -149,4 +149,14 @@ source "drivers/usb/phy/Kconfig" ...@@ -149,4 +149,14 @@ source "drivers/usb/phy/Kconfig"
source "drivers/usb/gadget/Kconfig" source "drivers/usb/gadget/Kconfig"
config USB_LED_TRIG
bool "USB LED Triggers"
depends on LEDS_CLASS && USB_COMMON && LEDS_TRIGGERS
help
This option adds LED triggers for USB host and/or gadget activity.
Say Y here if you are working on a system with led-class supported
LEDs and you want to use them as activity indicators for USB host or
gadget.
endif # USB_SUPPORT endif # USB_SUPPORT
...@@ -4,5 +4,6 @@ ...@@ -4,5 +4,6 @@
obj-$(CONFIG_USB_COMMON) += usb-common.o obj-$(CONFIG_USB_COMMON) += usb-common.o
usb-common-y += common.o usb-common-y += common.o
usb-common-$(CONFIG_USB_LED_TRIG) += led.o
obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o obj-$(CONFIG_USB_OTG_FSM) += usb-otg-fsm.o
/*
* LED Triggers for USB Activity
*
* Copyright 2014 Michal Sojka <sojka@merica.cz>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/leds.h>
#include <linux/usb.h>
#define BLINK_DELAY 30
static unsigned long usb_blink_delay = BLINK_DELAY;
DEFINE_LED_TRIGGER(ledtrig_usb_gadget);
DEFINE_LED_TRIGGER(ledtrig_usb_host);
void usb_led_activity(enum usb_led_event ev)
{
struct led_trigger *trig = NULL;
switch (ev) {
case USB_LED_EVENT_GADGET:
trig = ledtrig_usb_gadget;
break;
case USB_LED_EVENT_HOST:
trig = ledtrig_usb_host;
break;
}
/* led_trigger_blink_oneshot() handles trig == NULL gracefully */
led_trigger_blink_oneshot(trig, &usb_blink_delay, &usb_blink_delay, 0);
}
EXPORT_SYMBOL_GPL(usb_led_activity);
static int __init ledtrig_usb_init(void)
{
led_trigger_register_simple("usb-gadget", &ledtrig_usb_gadget);
led_trigger_register_simple("usb-host", &ledtrig_usb_host);
return 0;
}
static void __exit ledtrig_usb_exit(void)
{
led_trigger_unregister_simple(ledtrig_usb_gadget);
led_trigger_unregister_simple(ledtrig_usb_host);
}
module_init(ledtrig_usb_init);
module_exit(ledtrig_usb_exit);
...@@ -1664,6 +1664,8 @@ static void __usb_hcd_giveback_urb(struct urb *urb) ...@@ -1664,6 +1664,8 @@ static void __usb_hcd_giveback_urb(struct urb *urb)
usbmon_urb_complete(&hcd->self, urb, status); usbmon_urb_complete(&hcd->self, urb, status);
usb_anchor_suspend_wakeups(anchor); usb_anchor_suspend_wakeups(anchor);
usb_unanchor_urb(urb); usb_unanchor_urb(urb);
if (likely(status == 0))
usb_led_activity(USB_LED_EVENT_HOST);
/* pass ownership to the completion handler */ /* pass ownership to the completion handler */
urb->status = status; urb->status = status;
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <linux/usb/ch9.h> #include <linux/usb/ch9.h>
#include <linux/usb/gadget.h> #include <linux/usb/gadget.h>
#include <linux/usb.h>
/** /**
* struct usb_udc - describes one usb device controller * struct usb_udc - describes one usb device controller
...@@ -116,6 +117,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request); ...@@ -116,6 +117,9 @@ EXPORT_SYMBOL_GPL(usb_gadget_unmap_request);
void usb_gadget_giveback_request(struct usb_ep *ep, void usb_gadget_giveback_request(struct usb_ep *ep,
struct usb_request *req) struct usb_request *req)
{ {
if (likely(req->status == 0))
usb_led_activity(USB_LED_EVENT_GADGET);
req->complete(ep, req); req->complete(ep, req);
} }
EXPORT_SYMBOL_GPL(usb_gadget_giveback_request); EXPORT_SYMBOL_GPL(usb_gadget_giveback_request);
......
...@@ -1862,6 +1862,18 @@ extern void usb_unregister_notify(struct notifier_block *nb); ...@@ -1862,6 +1862,18 @@ extern void usb_unregister_notify(struct notifier_block *nb);
/* debugfs stuff */ /* debugfs stuff */
extern struct dentry *usb_debug_root; extern struct dentry *usb_debug_root;
/* LED triggers */
enum usb_led_event {
USB_LED_EVENT_HOST = 0,
USB_LED_EVENT_GADGET = 1,
};
#ifdef CONFIG_USB_LED_TRIG
extern void usb_led_activity(enum usb_led_event ev);
#else
static inline void usb_led_activity(enum usb_led_event ev) {}
#endif
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment