summaryrefslogtreecommitdiff
path: root/target/linux/brcm2708/patches-3.18/0092-dwc_otg-introduce-fiq_fsm_spin-un-lock.patch
diff options
context:
space:
mode:
Diffstat (limited to 'target/linux/brcm2708/patches-3.18/0092-dwc_otg-introduce-fiq_fsm_spin-un-lock.patch')
-rw-r--r--target/linux/brcm2708/patches-3.18/0092-dwc_otg-introduce-fiq_fsm_spin-un-lock.patch307
1 files changed, 0 insertions, 307 deletions
diff --git a/target/linux/brcm2708/patches-3.18/0092-dwc_otg-introduce-fiq_fsm_spin-un-lock.patch b/target/linux/brcm2708/patches-3.18/0092-dwc_otg-introduce-fiq_fsm_spin-un-lock.patch
deleted file mode 100644
index 19bb50a..0000000
--- a/target/linux/brcm2708/patches-3.18/0092-dwc_otg-introduce-fiq_fsm_spin-un-lock.patch
+++ /dev/null
@@ -1,307 +0,0 @@
-From 424f79f35a94611f73182f19a7711174b756b052 Mon Sep 17 00:00:00 2001
-From: P33M <P33M@github.com>
-Date: Fri, 26 Sep 2014 11:32:09 +0100
-Subject: [PATCH 092/114] dwc_otg: introduce fiq_fsm_spin(un|)lock()
-
-SMP safety for the FIQ relies on register read-modify write cycles being
-completed in the correct order. Several places in the DWC code modify
-registers also touched by the FIQ. Protect these by a bare-bones lock
-mechanism.
-
-This also makes it possible to run the FIQ and IRQ handlers on different
-cores.
----
- .../usb/host/dwc_common_port/dwc_common_linux.c | 6 ---
- drivers/usb/host/dwc_otg/dwc_otg_cil.c | 10 -----
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 46 +++++++++++++++++++++-
- drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h | 16 +++++++-
- drivers/usb/host/dwc_otg/dwc_otg_hcd.c | 23 ++++++++++-
- drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c | 9 ++++-
- 6 files changed, 88 insertions(+), 22 deletions(-)
-
---- a/drivers/usb/host/dwc_common_port/dwc_common_linux.c
-+++ b/drivers/usb/host/dwc_common_port/dwc_common_linux.c
-@@ -580,13 +580,7 @@ void DWC_WRITE_REG64(uint64_t volatile *
-
- void DWC_MODIFY_REG32(uint32_t volatile *reg, uint32_t clear_mask, uint32_t set_mask)
- {
-- unsigned long flags;
--
-- local_irq_save(flags);
-- local_fiq_disable();
- writel((readl(reg) & ~clear_mask) | set_mask, reg);
-- local_fiq_enable();
-- local_irq_restore(flags);
- }
-
- #if 0
---- a/drivers/usb/host/dwc_otg/dwc_otg_cil.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_cil.c
-@@ -2244,9 +2244,7 @@ void dwc_otg_core_host_init(dwc_otg_core
- */
- void dwc_otg_hc_init(dwc_otg_core_if_t * core_if, dwc_hc_t * hc)
- {
-- uint32_t intr_enable;
- hcintmsk_data_t hc_intr_mask;
-- gintmsk_data_t gintmsk = {.d32 = 0 };
- hcchar_data_t hcchar;
- hcsplt_data_t hcsplt;
-
-@@ -2348,14 +2346,6 @@ void dwc_otg_hc_init(dwc_otg_core_if_t *
- }
- DWC_WRITE_REG32(&hc_regs->hcintmsk, hc_intr_mask.d32);
-
-- /* Enable the top level host channel interrupt. */
-- intr_enable = (1 << hc_num);
-- DWC_MODIFY_REG32(&host_if->host_global_regs->haintmsk, 0, intr_enable);
--
-- /* Make sure host channel interrupts are enabled. */
-- gintmsk.b.hcintr = 1;
-- DWC_MODIFY_REG32(&core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
--
- /*
- * Program the HCCHARn register with the endpoint characteristics for
- * the current transfer.
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
-@@ -75,6 +75,46 @@ void notrace _fiq_print(enum fiq_debug_l
- }
-
- /**
-+ * fiq_fsm_spin_lock() - ARMv6+ bare bones spinlock
-+ * Must be called with local interrupts and FIQ disabled.
-+ */
-+inline void fiq_fsm_spin_lock(fiq_lock_t *lock)
-+{
-+ unsigned long tmp;
-+ uint32_t newval;
-+ fiq_lock_t lockval;
-+ smp_mb__before_spinlock();
-+ /* Nested locking, yay. If we are on the same CPU as the fiq, then the disable
-+ * will be sufficient. If we are on a different CPU, then the lock protects us. */
-+ prefetchw(&lock->slock);
-+ asm volatile (
-+ "1: ldrex %0, [%3]\n"
-+ " add %1, %0, %4\n"
-+ " strex %2, %1, [%3]\n"
-+ " teq %2, #0\n"
-+ " bne 1b"
-+ : "=&r" (lockval), "=&r" (newval), "=&r" (tmp)
-+ : "r" (&lock->slock), "I" (1 << 16)
-+ : "cc");
-+
-+ while (lockval.tickets.next != lockval.tickets.owner) {
-+ wfe();
-+ lockval.tickets.owner = ACCESS_ONCE(lock->tickets.owner);
-+ }
-+ smp_mb();
-+}
-+
-+/**
-+ * fiq_fsm_spin_unlock() - ARMv6+ bare bones spinunlock
-+ */
-+inline void fiq_fsm_spin_unlock(fiq_lock_t *lock)
-+{
-+ smp_mb();
-+ lock->tickets.owner++;
-+ dsb_sev();
-+}
-+
-+/**
- * fiq_fsm_restart_channel() - Poke channel enable bit for a split transaction
- * @channel: channel to re-enable
- */
-@@ -1142,6 +1182,7 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
- gintsts_handled.d32 = 0;
- haint_handled.d32 = 0;
-
-+ fiq_fsm_spin_lock(&state->lock);
- gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS);
- gintmsk.d32 = FIQ_READ(state->dwc_regs_base + GINTMSK);
- gintsts.d32 &= gintmsk.d32;
-@@ -1231,7 +1272,7 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
-
- }
- state->fiq_done++;
-- mb();
-+ fiq_fsm_spin_unlock(&state->lock);
- }
-
-
-@@ -1253,6 +1294,7 @@ void notrace dwc_otg_fiq_nop(struct fiq_
- gintmsk_data_t gintmsk;
- hfnum_data_t hfnum;
-
-+ fiq_fsm_spin_lock(&state->lock);
- hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
- gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS);
- gintmsk.d32 = FIQ_READ(state->dwc_regs_base + GINTMSK);
-@@ -1290,5 +1332,5 @@ void notrace dwc_otg_fiq_nop(struct fiq_
-
- }
- state->fiq_done++;
-- mb();
-+ fiq_fsm_spin_unlock(&state->lock);
- }
---- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.h
-@@ -120,7 +120,6 @@ typedef struct {
- volatile void* intstat;
- } mphi_regs_t;
-
--
- enum fiq_debug_level {
- FIQDBG_SCHED = (1 << 0),
- FIQDBG_INT = (1 << 1),
-@@ -128,6 +127,16 @@ enum fiq_debug_level {
- FIQDBG_PORTHUB = (1 << 3),
- };
-
-+typedef struct {
-+ union {
-+ uint32_t slock;
-+ struct _tickets {
-+ uint16_t owner;
-+ uint16_t next;
-+ } tickets;
-+ };
-+} fiq_lock_t;
-+
- struct fiq_state;
-
- extern void _fiq_print (enum fiq_debug_level dbg_lvl, volatile struct fiq_state *state, char *fmt, ...);
-@@ -324,6 +333,7 @@ struct fiq_channel_state {
- * It contains top-level state information.
- */
- struct fiq_state {
-+ fiq_lock_t lock;
- mphi_regs_t mphi_regs;
- void *dwc_regs_base;
- dma_addr_t dma_base;
-@@ -342,6 +352,10 @@ struct fiq_state {
- struct fiq_channel_state channel[0];
- };
-
-+extern void fiq_fsm_spin_lock(fiq_lock_t *lock);
-+
-+extern void fiq_fsm_spin_unlock(fiq_lock_t *lock);
-+
- extern int fiq_fsm_too_late(struct fiq_state *st, int n);
-
- extern int fiq_fsm_tt_in_use(struct fiq_state *st, int num_channels, int n);
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd.c
-@@ -1184,6 +1184,9 @@ static void assign_and_init_hc(dwc_otg_h
- dwc_otg_qtd_t *qtd;
- dwc_otg_hcd_urb_t *urb;
- void* ptr = NULL;
-+ uint32_t intr_enable;
-+ unsigned long flags;
-+ gintmsk_data_t gintmsk = { .d32 = 0, };
-
- qtd = DWC_CIRCLEQ_FIRST(&qh->qtd_list);
-
-@@ -1409,6 +1412,20 @@ static void assign_and_init_hc(dwc_otg_h
- hc->desc_list_addr = qh->desc_list_dma;
-
- dwc_otg_hc_init(hcd->core_if, hc);
-+
-+ local_irq_save(flags);
-+ local_fiq_disable();
-+ fiq_fsm_spin_lock(&hcd->fiq_state->lock);
-+ /* Enable the top level host channel interrupt. */
-+ intr_enable = (1 << hc->hc_num);
-+ DWC_MODIFY_REG32(&hcd->core_if->host_if->host_global_regs->haintmsk, 0, intr_enable);
-+
-+ /* Make sure host channel interrupts are enabled. */
-+ gintmsk.b.hcintr = 1;
-+ DWC_MODIFY_REG32(&hcd->core_if->core_global_regs->gintmsk, 0, gintmsk.d32);
-+ fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
-+ local_fiq_enable();
-+ local_irq_restore(flags);
- hc->qh = qh;
- }
-
-@@ -1659,6 +1676,7 @@ int fiq_fsm_queue_isoc_transaction(dwc_o
- fiq_print(FIQDBG_INT, hcd->fiq_state, "%08x", st->hcdma_copy.d32);
- hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
- local_fiq_disable();
-+ fiq_fsm_spin_lock(&hcd->fiq_state->lock);
- DWC_WRITE_REG32(&hc_regs->hctsiz, st->hctsiz_copy.d32);
- DWC_WRITE_REG32(&hc_regs->hcsplt, st->hcsplt_copy.d32);
- DWC_WRITE_REG32(&hc_regs->hcdma, st->hcdma_copy.d32);
-@@ -1676,6 +1694,7 @@ int fiq_fsm_queue_isoc_transaction(dwc_o
- }
- mb();
- st->hcchar_copy.b.chen = 0;
-+ fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
- local_fiq_enable();
- return 0;
- }
-@@ -1811,7 +1830,7 @@ int fiq_fsm_queue_split_transaction(dwc_
- DWC_WRITE_REG32(&hc_regs->hcintmsk, st->hcintmsk_copy.d32);
-
- local_fiq_disable();
-- mb();
-+ fiq_fsm_spin_lock(&hcd->fiq_state->lock);
-
- if (hc->ep_type & 0x1) {
- hfnum.d32 = DWC_READ_REG32(&hcd->core_if->host_if->host_global_regs->hfnum);
-@@ -1909,7 +1928,7 @@ int fiq_fsm_queue_split_transaction(dwc_
- st->hcchar_copy.b.chen = 1;
- DWC_WRITE_REG32(&hc_regs->hcchar, st->hcchar_copy.d32);
- }
-- mb();
-+ fiq_fsm_spin_unlock(&hcd->fiq_state->lock);
- local_fiq_enable();
- return 0;
- }
---- a/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
-+++ b/drivers/usb/host/dwc_otg/dwc_otg_hcd_intr.c
-@@ -101,6 +101,7 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
- if (dwc_otg_is_host_mode(core_if)) {
- if (fiq_enable) {
- local_fiq_disable();
-+ fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
- /* Pull in from the FIQ's disabled mask */
- gintmsk.d32 = gintmsk.d32 | ~(dwc_otg_hcd->fiq_state->gintmsk_saved.d32);
- dwc_otg_hcd->fiq_state->gintmsk_saved.d32 = ~0;
-@@ -116,8 +117,10 @@ int32_t dwc_otg_hcd_handle_intr(dwc_otg_
- }
- gintsts.d32 &= gintmsk.d32;
-
-- if (fiq_enable)
-+ if (fiq_enable) {
-+ fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
- local_fiq_enable();
-+ }
-
- if (!gintsts.d32) {
- goto exit_handler_routine;
-@@ -200,6 +203,7 @@ exit_handler_routine:
- gintmsk_data_t gintmsk_new;
- haintmsk_data_t haintmsk_new;
- local_fiq_disable();
-+ fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
- gintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->gintmsk_saved.d32;
- if(fiq_fsm_enable)
- haintmsk_new.d32 = *(volatile uint32_t *)&dwc_otg_hcd->fiq_state->haintmsk_saved.d32;
-@@ -222,6 +226,7 @@ exit_handler_routine:
- haintmsk.d32 = DWC_READ_REG32(&core_if->host_if->host_global_regs->haintmsk);
- /* Re-enable interrupts that the FIQ masked (first time round) */
- FIQ_WRITE(dwc_otg_hcd->fiq_state->dwc_regs_base + GINTMSK, gintmsk.d32);
-+ fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
- local_fiq_enable();
-
- if ((jiffies / HZ) > last_time) {
-@@ -633,8 +638,10 @@ int32_t dwc_otg_hcd_handle_hc_intr(dwc_o
- {
- /* check the mask? */
- local_fiq_disable();
-+ fiq_fsm_spin_lock(&dwc_otg_hcd->fiq_state->lock);
- haint.b2.chint |= ~(dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint);
- dwc_otg_hcd->fiq_state->haintmsk_saved.b2.chint = ~0;
-+ fiq_fsm_spin_unlock(&dwc_otg_hcd->fiq_state->lock);
- local_fiq_enable();
- }
-