mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-26 17:01:14 +00:00
c56ae22db0
Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
50 lines
1.8 KiB
Diff
50 lines
1.8 KiB
Diff
From b2d43d61a1d6d070664f10d12b3c8b6df11eb21d Mon Sep 17 00:00:00 2001
|
|
From: Jonathan Bell <jonathan@raspberrypi.org>
|
|
Date: Mon, 13 Jan 2020 15:54:55 +0000
|
|
Subject: [PATCH] dwc_otg: fiq_fsm: add a barrier on entry into FIQ
|
|
handler(s)
|
|
|
|
On BCM2835, there is no hardware guarantee that multiple outstanding
|
|
reads to different peripherals will complete in-order. The FIQ code
|
|
uses peripheral reads without barriers for performance, so in the case
|
|
where a read to a slow peripheral was issued immediately prior to FIQ
|
|
entry, the first peripheral read that the FIQ did could end up with
|
|
wrong read data returned.
|
|
|
|
Add dsb(sy) on entry so that all outstanding reads are retired.
|
|
|
|
The FIQ only issues reads to the dwc_otg core, so per-read barriers
|
|
in the handler itself are not required.
|
|
|
|
On BCM2836 and BCM2837 the barrier is not strictly required due to
|
|
differences in how the peripheral bus is implemented, but having
|
|
arch-specific handlers that introduce different latencies is risky.
|
|
|
|
Signed-off-by: Jonathan Bell <jonathan@raspberrypi.org>
|
|
---
|
|
drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c | 6 ++++++
|
|
1 file changed, 6 insertions(+)
|
|
|
|
--- a/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
|
|
+++ b/drivers/usb/host/dwc_otg/dwc_otg_fiq_fsm.c
|
|
@@ -1259,6 +1259,9 @@ void notrace dwc_otg_fiq_fsm(struct fiq_
|
|
haintmsk_data_t haintmsk;
|
|
int kick_irq = 0;
|
|
|
|
+ /* Ensure peripheral reads issued prior to FIQ entry are complete */
|
|
+ dsb(sy);
|
|
+
|
|
gintsts_handled.d32 = 0;
|
|
haint_handled.d32 = 0;
|
|
|
|
@@ -1379,6 +1382,9 @@ void notrace dwc_otg_fiq_nop(struct fiq_
|
|
gintmsk_data_t gintmsk;
|
|
hfnum_data_t hfnum;
|
|
|
|
+ /* Ensure peripheral reads issued prior to FIQ entry are complete */
|
|
+ dsb(sy);
|
|
+
|
|
fiq_fsm_spin_lock(&state->lock);
|
|
hfnum.d32 = FIQ_READ(state->dwc_regs_base + HFNUM);
|
|
gintsts.d32 = FIQ_READ(state->dwc_regs_base + GINTSTS);
|