summaryrefslogtreecommitdiffstats
path: root/target/linux/brcm2708/patches-3.10/0057-dwc_otg-implement-tasklet-for-returning-URBs-to-usbc.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.10/0057-dwc_otg-implement-tasklet-for-returning-URBs-to-usbc.patch')
-rw-r--r--target/linux/brcm2708/patches-3.10/0057-dwc_otg-implement-tasklet-for-returning-URBs-to-usbc.patch244
1 files changed, 0 insertions, 244 deletions
diff --git a/target/linux/brcm2708/patches-3.10/0057-dwc_otg-implement-tasklet-for-returning-URBs-to-usbc.patch b/target/linux/brcm2708/patches-3.10/0057-dwc_otg-implement-tasklet-for-returning-URBs-to-usbc.patch
deleted file mode 100644
index b39634cf0f..0000000000
--- a/target/linux/brcm2708/patches-3.10/0057-dwc_otg-implement-tasklet-for-returning-URBs-to-usbc.patch
+++ /dev/null
@@ -1,244 +0,0 @@
-From f5908d1de6a9231622ebe7ae174749305a69878f Mon Sep 17 00:00:00 2001
-From: P33M <P33M@github.com>
-Date: Thu, 21 Mar 2013 19:36:17 +0000
-Subject: [PATCH 057/196] dwc_otg: implement tasklet for returning URBs to
- usbcore hcd layer
-
-The dwc_otg driver interrupt handler for transfer completion will spend
-a very long time with interrupts disabled when a URB is completed -
-this is because usb_hcd_giveback_urb is called from within the handler
-which for a USB device driver with complicated processing (e.g. webcam)
-will take an exorbitant amount of time to complete. This results in
-missed completion interrupts for other USB packets which lead to them
-being dropped due to microframe overruns.
-
-This patch splits returning the URB to the usb hcd layer into a
-high-priority tasklet. This will have most benefit for isochronous IN
-transfers but will also have incidental benefit where multiple periodic
-devices are active at once.
----
- .../usb/host/dwc_common_port/dwc_common_linux.c | 5 ++++
- drivers/usb/host/dwc_common_port/dwc_list.h | 14 ++++-----
- drivers/usb/host/dwc_common_port/dwc_os.h | 2 ++
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 34 +++++++++++++++++++++-
- drivers/usb/host/dwc_otg/dwc_otg_hcd.h | 10 +++++++
- drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c | 25 ++++++++++------
- 6 files changed, 73 insertions(+), 17 deletions(-)
-
-diff --git a/drivers/usb/host/dwc_common_port/dwc_common_linux.c b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
-index f00a9ff..6814e51 100644
---- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c
-+++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
-@@ -991,6 +991,11 @@ void DWC_TASK_SCHEDULE(dwc_tasklet_t *task)
- tasklet_schedule(&task->t);
- }
-
-+void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task)
-+{
-+ tasklet_hi_schedule(&task->t);
-+}
-+
-
- /* workqueues
- - run in process context (can sleep)
-diff --git a/drivers/usb/host/dwc_common_port/dwc_list.h b/drivers/usb/host/dwc_common_port/dwc_list.h
-index 89cc325..4ce560d 100644
---- a/drivers/usb/host/dwc_common_port/dwc_list.h
-+++ b/drivers/usb/host/dwc_common_port/dwc_list.h
-@@ -384,17 +384,17 @@ struct { \
- #define DWC_TAILQ_PREV(elm, headname, field) \
- (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
- #define DWC_TAILQ_EMPTY(head) \
-- (TAILQ_FIRST(head) == TAILQ_END(head))
-+ (DWC_TAILQ_FIRST(head) == DWC_TAILQ_END(head))
-
- #define DWC_TAILQ_FOREACH(var, head, field) \
-- for((var) = TAILQ_FIRST(head); \
-- (var) != TAILQ_END(head); \
-- (var) = TAILQ_NEXT(var, field))
-+ for ((var) = DWC_TAILQ_FIRST(head); \
-+ (var) != DWC_TAILQ_END(head); \
-+ (var) = DWC_TAILQ_NEXT(var, field))
-
- #define DWC_TAILQ_FOREACH_REVERSE(var, head, headname, field) \
-- for((var) = TAILQ_LAST(head, headname); \
-- (var) != TAILQ_END(head); \
-- (var) = TAILQ_PREV(var, headname, field))
-+ for ((var) = DWC_TAILQ_LAST(head, headname); \
-+ (var) != DWC_TAILQ_END(head); \
-+ (var) = DWC_TAILQ_PREV(var, headname, field))
-
- /*
- * Tail queue functions.
-diff --git a/drivers/usb/host/dwc_common_port/dwc_os.h b/drivers/usb/host/dwc_common_port/dwc_os.h
-index 308ddd5..8eb24ea 100644
---- a/drivers/usb/host/dwc_common_port/dwc_os.h
-+++ b/drivers/usb/host/dwc_common_port/dwc_os.h
-@@ -981,6 +981,8 @@ extern void DWC_TASK_FREE(dwc_tasklet_t *task);
- extern void DWC_TASK_SCHEDULE(dwc_tasklet_t *task);
- #define dwc_task_schedule DWC_TASK_SCHEDULE
-
-+extern void DWC_TASK_HI_SCHEDULE(dwc_tasklet_t *task);
-+#define dwc_task_hi_schedule DWC_TASK_HI_SCHEDULE
-
- /** @name Timer
- *
-diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-index fcec97f..91eefec 100644
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -40,6 +40,9 @@
- * header file.
- */
-
-+#include <linux/usb.h>
-+#include <linux/usb/hcd.h>
-+
- #include "dwc_otg_hcd.h"
- #include "dwc_otg_regs.h"
-
-@@ -694,6 +697,31 @@ static void reset_tasklet_func(void *data)
- dwc_otg_hcd->flags.b.port_reset_change = 1;
- }
-
-+static void completion_tasklet_func(void *ptr)
-+{
-+ dwc_otg_hcd_t *hcd = (dwc_otg_hcd_t *) ptr;
-+ struct urb *urb;
-+ urb_tq_entry_t *item;
-+ dwc_irqflags_t flags;
-+
-+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
-+ while (!DWC_TAILQ_EMPTY(&hcd->completed_urb_list)) {
-+ item = DWC_TAILQ_FIRST(&hcd->completed_urb_list);
-+ urb = item->urb;
-+ DWC_TAILQ_REMOVE(&hcd->completed_urb_list, item,
-+ urb_tq_entries);
-+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
-+ DWC_FREE(item);
-+
-+ usb_hcd_unlink_urb_from_ep(hcd->priv, urb);
-+ usb_hcd_giveback_urb(hcd->priv, urb, urb->status);
-+
-+ DWC_SPINLOCK_IRQSAVE(hcd->lock, &flags);
-+ }
-+ DWC_SPINUNLOCK_IRQRESTORE(hcd->lock, flags);
-+ return;
-+}
-+
- static void qh_list_free(dwc_otg_hcd_t * hcd, dwc_list_link_t * qh_list)
- {
- dwc_list_link_t *item;
-@@ -833,6 +861,7 @@ static void dwc_otg_hcd_free(dwc_otg_hcd_t * dwc_otg_hcd)
-
- DWC_TIMER_FREE(dwc_otg_hcd->conn_timer);
- DWC_TASK_FREE(dwc_otg_hcd->reset_tasklet);
-+ DWC_TASK_FREE(dwc_otg_hcd->completion_tasklet);
-
- #ifdef DWC_DEV_SRPCAP
- if (dwc_otg_hcd->core_if->power_down == 2 &&
-@@ -877,7 +906,7 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
- DWC_LIST_INIT(&hcd->periodic_sched_ready);
- DWC_LIST_INIT(&hcd->periodic_sched_assigned);
- DWC_LIST_INIT(&hcd->periodic_sched_queued);
--
-+ DWC_TAILQ_INIT(&hcd->completed_urb_list);
- /*
- * Create a host channel descriptor for each host channel implemented
- * in the controller. Initialize the channel descriptor array.
-@@ -915,6 +944,9 @@ int dwc_otg_hcd_init(dwc_otg_hcd_t * hcd, dwc_otg_core_if_t * core_if)
-
- /* Initialize reset tasklet. */
- hcd->reset_tasklet = DWC_TASK_ALLOC("reset_tasklet", reset_tasklet_func, hcd);
-+
-+ hcd->completion_tasklet = DWC_TASK_ALLOC("completion_tasklet",
-+ completion_tasklet_func, hcd);
- #ifdef DWC_DEV_SRPCAP
- if (hcd->core_if->power_down == 2) {
- /* Initialize Power on timer for Host power up in case hibernation */
-diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
-index 45e44ea..0493dbf 100644
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.h
-@@ -374,6 +374,13 @@ typedef struct dwc_otg_qh {
-
- DWC_CIRCLEQ_HEAD(hc_list, dwc_hc);
-
-+typedef struct urb_tq_entry {
-+ struct urb *urb;
-+ DWC_TAILQ_ENTRY(urb_tq_entry) urb_tq_entries;
-+} urb_tq_entry_t;
-+
-+DWC_TAILQ_HEAD(urb_list, urb_tq_entry);
-+
- /**
- * This structure holds the state of the HCD, including the non-periodic and
- * periodic schedules.
-@@ -551,6 +558,9 @@ struct dwc_otg_hcd {
- /* Tasket to do a reset */
- dwc_tasklet_t *reset_tasklet;
-
-+ dwc_tasklet_t *completion_tasklet;
-+ struct urb_list completed_urb_list;
-+
- /* */
- dwc_spinlock_t *lock;
- dwc_spinlock_t *channel_lock;
-diff --git a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-index 9702f81..7bb133a 100644
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_linux.c
-@@ -271,7 +271,7 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
- dwc_otg_hcd_urb_t * dwc_otg_urb, int32_t status)
- {
- struct urb *urb = (struct urb *)urb_handle;
--
-+ urb_tq_entry_t *new_entry;
- if (CHK_DEBUG_LEVEL(DBG_HCDV | DBG_HCD_URB)) {
- DWC_PRINTF("%s: urb %p, device %d, ep %d %s, status=%d\n",
- __func__, urb, usb_pipedevice(urb->pipe),
-@@ -285,7 +285,7 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
- }
- }
- }
--
-+ new_entry = DWC_ALLOC_ATOMIC(sizeof(urb_tq_entry_t));
- urb->actual_length = dwc_otg_hcd_urb_get_actual_length(dwc_otg_urb);
- /* Convert status value. */
- switch (status) {
-@@ -348,18 +348,25 @@ static int _complete(dwc_otg_hcd_t * hcd, void *urb_handle,
- }
-
- DWC_FREE(dwc_otg_urb);
--
-+ if (!new_entry) {
-+ DWC_ERROR("dwc_otg_hcd: complete: cannot allocate URB TQ entry\n");
-+ urb->status = -EPROTO;
-+ /* don't schedule the tasklet -
-+ * directly return the packet here with error. */
- #if USB_URB_EP_LINKING
-- usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
-+ usb_hcd_unlink_urb_from_ep(dwc_otg_hcd_to_hcd(hcd), urb);
- #endif
-- DWC_SPINUNLOCK(hcd->lock);
- #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-- usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
-+ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb);
- #else
-- usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, status);
-+ usb_hcd_giveback_urb(dwc_otg_hcd_to_hcd(hcd), urb, urb->status);
- #endif
-- DWC_SPINLOCK(hcd->lock);
--
-+ } else {
-+ new_entry->urb = urb;
-+ DWC_TAILQ_INSERT_TAIL(&hcd->completed_urb_list, new_entry,
-+ urb_tq_entries);
-+ DWC_TASK_HI_SCHEDULE(hcd->completion_tasklet);
-+ }
- return 0;
- }
-
---
-1.9.1
-