Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1396415 > unrolled thread
| Started by | Christian Lamparter <chunkeey@googlemail.com> |
|---|---|
| First post | 2016-05-08 13:50 +0200 |
| Last post | 2016-05-09 23:40 +0200 |
| Articles | 20 on this page of 28 — 6 participants |
Back to article view | Back to linux.kernel
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Christian Lamparter <chunkeey@googlemail.com> - 2016-05-08 13:50 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Benjamin Herrenschmidt <benh@au1.ibm.com> - 2016-05-09 02:30 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-09 12:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Felipe Balbi <felipe.balbi@linux.intel.com> - 2016-05-09 12:50 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-09 17:10 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-09 22:20 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2016-05-10 00:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-10 09:30 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Christian Lamparter <chunkeey@googlemail.com> - 2016-05-12 12:00 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-12 14:00 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Christian Lamparter <chunkeey@googlemail.com> - 2016-05-12 15:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 John Youn <John.Youn@synopsys.com> - 2016-05-12 20:50 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Christian Lamparter <chunkeey@googlemail.com> - 2016-05-12 22:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-12 23:00 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 John Youn <John.Youn@synopsys.com> - 2016-05-12 23:00 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-14 21:50 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 John Youn <John.Youn@synopsys.com> - 2016-05-18 02:00 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Christian Lamparter <chunkeey@googlemail.com> - 2016-05-18 21:20 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-18 23:10 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 John Youn <John.Youn@synopsys.com> - 2016-05-19 02:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2016-05-13 00:20 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2016-05-10 00:50 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Benjamin Herrenschmidt <benh@kernel.crashing.org> - 2016-05-10 00:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Benjamin Herrenschmidt <benh@au1.ibm.com> - 2016-05-09 16:10 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 John Youn <John.Youn@synopsys.com> - 2016-05-09 22:30 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-09 22:40 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 John Youn <John.Youn@synopsys.com> - 2016-05-09 23:20 +0200
Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 Arnd Bergmann <arnd@arndb.de> - 2016-05-09 23:40 +0200
Page 1 of 2 [1] 2 Next page →
| From | Christian Lamparter <chunkeey@googlemail.com> |
|---|---|
| Date | 2016-05-08 13:50 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <rwvnI-6dm-5@gated-at.bofh.it> |
On Sunday, May 08, 2016 08:40:55 PM Benjamin Herrenschmidt wrote:
> On Sun, 2016-05-08 at 00:54 +0200, Christian Lamparter via Linuxppc-dev
> wrote:
> > I've been looking in getting the MyBook Live Duo's USB OTG port
> > to function. The SoC is a APM82181. Which has a PowerPC 464 core
> > and related to the supported canyonlands architecture in
> > arch/powerpc/.
> >
> > Currently in -next the dwc2 module doesn't load:
>
> Smells like the APM implementation is little endian. You might need to
> use a flag to indicate what endian to use instead and set it
> appropriately based on some DT properties.
I tried. As per common-properties[0], I added little-endian; but it has no
effect. I looked in dwc2_driver_probe and found no way of specifying the
endian of the device. It all comes down to the dwc2_readl & dwc2_writel
accessors. These - sadly - have been hardwired to use __raw_readl and
__raw_writel. So, it's always "native-endian". While common-properties
says little-endian should be preferred.
> > dwc2 4bff80000.usbotg: dwc2_core_reset() HANG! AHB Idle GRSTCTL=80
> > dwc2 4bff80000.usbotg: Bad value for GSNPSID: 0x0a29544f
> >
> > Looking at the Bad GSNPSID value: 0x0a29544f. It is obvious that
> > this is an endian problem. git finds this patch:
> >
> > commit 95c8bc3609440af5e4a4f760b8680caea7424396
> > Author: Antti Seppälä <a.seppala@gmail.com>
> > Date: Thu Aug 20 21:41:07 2015 +0300
> >
> > usb: dwc2: Use platform endianness when accessing registers
> >
> > This patch is necessary to access dwc2 registers correctly on
> > big-endian
> > systems such as the mips based SoCs made by Lantiq. Then dwc2 can
> > be
> > used to replace ifx-hcd driver for Lantiq platforms found e.g. in
> > OpenWrt.
> >
> > The patch was autogenerated with the following commands:
> > $EDITOR core.h
> > sed -i "s/\<readl\>/dwc2_readl/g" *.c hcd.h hw.h
> > sed -i "s/\<writel\>/dwc2_writel/g" *.c hcd.h hw.h
> >
> > Some files were then hand-edited to fix checkpatch.pl warnings
> > about
> > too long lines.
> >
> > which unfortunately, broke the USB-OTG port on the MyBook Live Duo.
> > Reverting to the readl / writel:
> >
> > ---
> > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> > index 3c58d63..c021c1f 100644
> > --- a/drivers/usb/dwc2/core.h
> > +++ b/drivers/usb/dwc2/core.h
> > @@ -66,7 +66,7 @@
> >
> > static inline u32 dwc2_readl(const void __iomem *addr)
> > {
> > - u32 value = __raw_readl(addr);
> > + u32 value = readl(addr);
> >
> > /* In order to preserve endianness __raw_* operation is
> > used. Therefore
> > * a barrier is needed to ensure IO access is not re-ordered
> > across
> > @@ -78,7 +78,7 @@ static inline u32 dwc2_readl(const void __iomem
> > *addr)
> >
> > static inline void dwc2_writel(u32 value, void __iomem *addr)
> > {
> > - __raw_writel(value, addr);
> > + writel(value, addr);
> >
> > /*
> > * In order to preserve endianness __raw_* operation is
> > used. Therefore
> >
> > ---
> >
> > restores the dwc-otg port to full working order:
> > dwc2 4bff80000.usbotg: Specified GNPTXFDEP=1024 > 256
> > dwc2 4bff80000.usbotg: EPs: 3, shared fifos, 2042 entries in SPRAM
> > dwc2 4bff80000.usbotg: DWC OTG Controller
> > dwc2 4bff80000.usbotg: new USB bus registered, assigned bus number 1
> > dwc2 4bff80000.usbotg: irq 33, io mem 0x00000000
> > hub 1-0:1.0: USB hub found
> > hub 1-0:1.0: 1 port detected
> > root@mbl:~# usb 1-1: new high-speed USB device number 2 using dwc2
> >
> > So, what to do?
^^^
Regards,
Christian
[0] <http://lxr.free-electrons.com/source/Documentation/devicetree/bindings/common-properties.txt>
[toc] | [next] | [standalone]
| From | Benjamin Herrenschmidt <benh@au1.ibm.com> |
|---|---|
| Date | 2016-05-09 02:30 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <rwHfb-SK-1@gated-at.bofh.it> |
| In reply to | #1396415 |
On Sun, 2016-05-08 at 13:44 +0200, Christian Lamparter wrote:
> On Sunday, May 08, 2016 08:40:55 PM Benjamin Herrenschmidt wrote:
> >
> > On Sun, 2016-05-08 at 00:54 +0200, Christian Lamparter via Linuxppc-dev
> > wrote:
> > >
> > > I've been looking in getting the MyBook Live Duo's USB OTG port
> > > to function. The SoC is a APM82181. Which has a PowerPC 464 core
> > > and related to the supported canyonlands architecture in
> > > arch/powerpc/.
> > >
> > > Currently in -next the dwc2 module doesn't load:
> > Smells like the APM implementation is little endian. You might need to
> > use a flag to indicate what endian to use instead and set it
> > appropriately based on some DT properties.
> I tried. As per common-properties[0], I added little-endian; but it has no
> effect. I looked in dwc2_driver_probe and found no way of specifying the
> endian of the device. It all comes down to the dwc2_readl & dwc2_writel
> accessors. These - sadly - have been hardwired to use __raw_readl and
> __raw_writel. So, it's always "native-endian". While common-properties
> says little-endian should be preferred.
Right, I meant, you should produce a patch adding a runtime test inside
those functions based on a device-tree property, a bit like we do for
some of the HCDs like OHCI, EHCI etc...
Cheers,
Ben.
> >
> > >
> > > dwc2 4bff80000.usbotg: dwc2_core_reset() HANG! AHB Idle GRSTCTL=80
> > > dwc2 4bff80000.usbotg: Bad value for GSNPSID: 0x0a29544f
> > >
> > > Looking at the Bad GSNPSID value: 0x0a29544f. It is obvious that
> > > this is an endian problem. git finds this patch:
> > >
> > > commit 95c8bc3609440af5e4a4f760b8680caea7424396
> > > Author: Antti Seppälä <a.seppala@gmail.com>
> > > Date: Thu Aug 20 21:41:07 2015 +0300
> > >
> > > usb: dwc2: Use platform endianness when accessing registers
> > >
> > > This patch is necessary to access dwc2 registers correctly on
> > > big-endian
> > > systems such as the mips based SoCs made by Lantiq. Then dwc2 can
> > > be
> > > used to replace ifx-hcd driver for Lantiq platforms found e.g. in
> > > OpenWrt.
> > >
> > > The patch was autogenerated with the following commands:
> > > $EDITOR core.h
> > > sed -i "s/\/dwc2_readl/g" *.c hcd.h hw.h
> > > sed -i "s/\/dwc2_writel/g" *.c hcd.h hw.h
> > >
> > > Some files were then hand-edited to fix checkpatch.pl warnings
> > > about
> > > too long lines.
> > >
> > > which unfortunately, broke the USB-OTG port on the MyBook Live Duo.
> > > Reverting to the readl / writel:
> > >
> > > ---
> > > diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
> > > index 3c58d63..c021c1f 100644
> > > --- a/drivers/usb/dwc2/core.h
> > > +++ b/drivers/usb/dwc2/core.h
> > > @@ -66,7 +66,7 @@
> > >
> > > static inline u32 dwc2_readl(const void __iomem *addr)
> > > {
> > > - u32 value = __raw_readl(addr);
> > > + u32 value = readl(addr);
> > >
> > > /* In order to preserve endianness __raw_* operation is
> > > used. Therefore
> > > * a barrier is needed to ensure IO access is not re-ordered
> > > across
> > > @@ -78,7 +78,7 @@ static inline u32 dwc2_readl(const void __iomem
> > > *addr)
> > >
> > > static inline void dwc2_writel(u32 value, void __iomem *addr)
> > > {
> > > - __raw_writel(value, addr);
> > > + writel(value, addr);
> > >
> > > /*
> > > * In order to preserve endianness __raw_* operation is
> > > used. Therefore
> > >
> > > ---
> > >
> > > restores the dwc-otg port to full working order:
> > > dwc2 4bff80000.usbotg: Specified GNPTXFDEP=1024 > 256
> > > dwc2 4bff80000.usbotg: EPs: 3, shared fifos, 2042 entries in SPRAM
> > > dwc2 4bff80000.usbotg: DWC OTG Controller
> > > dwc2 4bff80000.usbotg: new USB bus registered, assigned bus number 1
> > > dwc2 4bff80000.usbotg: irq 33, io mem 0x00000000
> > > hub 1-0:1.0: USB hub found
> > > hub 1-0:1.0: 1 port detected
> > > root@mbl:~# usb 1-1: new high-speed USB device number 2 using dwc2
> > >
> > > So, what to do?
> ^^^
>
> Regards,
> Christian
>
> [0]
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-usb" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-09 12:40 +0200 |
| Message-ID | <rwQLx-3GP-37@gated-at.bofh.it> |
| In reply to | #1396521 |
On Monday 09 May 2016 10:23:22 Benjamin Herrenschmidt wrote:
> On Sun, 2016-05-08 at 13:44 +0200, Christian Lamparter wrote:
> > On Sunday, May 08, 2016 08:40:55 PM Benjamin Herrenschmidt wrote:
> > >
> > > On Sun, 2016-05-08 at 00:54 +0200, Christian Lamparter via Linuxppc-dev
> > > wrote:
> > > >
> > > > I've been looking in getting the MyBook Live Duo's USB OTG port
> > > > to function. The SoC is a APM82181. Which has a PowerPC 464 core
> > > > and related to the supported canyonlands architecture in
> > > > arch/powerpc/.
> > > >
> > > > Currently in -next the dwc2 module doesn't load:
> > > Smells like the APM implementation is little endian. You might need to
> > > use a flag to indicate what endian to use instead and set it
> > > appropriately based on some DT properties.
> > I tried. As per common-properties[0], I added little-endian; but it has no
> > effect. I looked in dwc2_driver_probe and found no way of specifying the
> > endian of the device. It all comes down to the dwc2_readl & dwc2_writel
> > accessors. These - sadly - have been hardwired to use __raw_readl and
> > __raw_writel. So, it's always "native-endian". While common-properties
> > says little-endian should be preferred.
>
> Right, I meant, you should produce a patch adding a runtime test inside
> those functions based on a device-tree property, a bit like we do for
> some of the HCDs like OHCI, EHCI etc...
>
>
The patch that caused the problem had multiple issues:
- it broke big-endian ARM kernels: any machine that was working
correctly with a little-endian kernel is no longer using byteswaps
on big-endian kernels, which clearly breaks them.
- On PowerPC the same thing must be true: if it was working before,
using big-endian kernels is now broken. Unlike ARM, 32-bit PowerPC
usually uses big-endian kernels, so they are likely all broken.
- The barrier for dwc2_writel is on the wrong side of the __raw_writel(),
so the MMIO no longer synchronizes with DMA operations.
- On architectures that require specific CPU instructions for MMIO
access, using the __raw_ variant may turn this into a pointer
dereference that does not have the same effect as the readl/writel.
I think we can simply make this set of accessors architecture-dependent
(MIPS vs. the rest of the world) to revert ARM and PowerPC back to
the working version.
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 3c58d633ce80..1f8ed149a40f 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -64,12 +64,24 @@
DWC2_TRACE_SCHEDULER_VB(pr_fmt("%s: SCH: " fmt), \
dev_name(hsotg->dev), ##__VA_ARGS__)
+
+#ifdef CONFIG_MIPS
+/*
+ * There are some MIPS machines that can run in either big-endian
+ * or little-endian mode and that use the dwc2 register without
+ * a byteswap in both ways.
+ * Unlike other architectures, MIPS does not require a barrier
+ * before the __raw_writel() to synchronize with DMA but does
+ * require the barrier after the writel() to serialize a series
+ * of writes. This set of operations was added specifically for
+ * MIPS and should only be used there.
+ */
static inline u32 dwc2_readl(const void __iomem *addr)
{
u32 value = __raw_readl(addr);
- /* In order to preserve endianness __raw_* operation is used. Therefore
- * a barrier is needed to ensure IO access is not re-ordered across
+ /* in order to preserve endianness __raw_* operation is used. therefore
+ * a barrier is needed to ensure io access is not re-ordered across
* reads or writes
*/
mb();
@@ -81,15 +93,32 @@ static inline void dwc2_writel(u32 value, void __iomem *addr)
__raw_writel(value, addr);
/*
- * In order to preserve endianness __raw_* operation is used. Therefore
- * a barrier is needed to ensure IO access is not re-ordered across
+ * in order to preserve endianness __raw_* operation is used. therefore
+ * a barrier is needed to ensure io access is not re-ordered across
* reads or writes
*/
mb();
-#ifdef DWC2_LOG_WRITES
- pr_info("INFO:: wrote %08x to %p\n", value, addr);
+#ifdef dwc2_log_writes
+ pr_info("info:: wrote %08x to %p\n", value, addr);
#endif
}
+#else
+/* Normal architectures just use readl/write */
+static inline u32 dwc2_readl(const void __iomem *addr)
+{
+ u32 value = readl(addr);
+ return value;
+}
+
+static inline void dwc2_writel(u32 value, void __iomem *addr)
+{
+ writel(value, addr);
+
+#ifdef dwc2_log_writes
+ pr_info("info:: wrote %08x to %p\n", value, addr);
+#endif
+}
+#endif
/* Maximum number of Endpoints/HostChannels */
#define MAX_EPS_CHANNELS 16
[toc] | [prev] | [next] | [standalone]
| From | Felipe Balbi <felipe.balbi@linux.intel.com> |
|---|---|
| Date | 2016-05-09 12:50 +0200 |
| Message-ID | <rwQVc-3Ly-5@gated-at.bofh.it> |
| In reply to | #1396925 |
[Multipart message — attachments visible in raw view] — view raw
Hi, Arnd Bergmann <arnd@arndb.de> writes: > On Monday 09 May 2016 10:23:22 Benjamin Herrenschmidt wrote: >> On Sun, 2016-05-08 at 13:44 +0200, Christian Lamparter wrote: >> > On Sunday, May 08, 2016 08:40:55 PM Benjamin Herrenschmidt wrote: >> > > >> > > On Sun, 2016-05-08 at 00:54 +0200, Christian Lamparter via Linuxppc-dev >> > > wrote: >> > > > >> > > > I've been looking in getting the MyBook Live Duo's USB OTG port >> > > > to function. The SoC is a APM82181. Which has a PowerPC 464 core >> > > > and related to the supported canyonlands architecture in >> > > > arch/powerpc/. >> > > > >> > > > Currently in -next the dwc2 module doesn't load: >> > > Smells like the APM implementation is little endian. You might need to >> > > use a flag to indicate what endian to use instead and set it >> > > appropriately based on some DT properties. >> > I tried. As per common-properties[0], I added little-endian; but it has no >> > effect. I looked in dwc2_driver_probe and found no way of specifying the >> > endian of the device. It all comes down to the dwc2_readl & dwc2_writel >> > accessors. These - sadly - have been hardwired to use __raw_readl and >> > __raw_writel. So, it's always "native-endian". While common-properties >> > says little-endian should be preferred. >> >> Right, I meant, you should produce a patch adding a runtime test inside >> those functions based on a device-tree property, a bit like we do for >> some of the HCDs like OHCI, EHCI etc... >> >> > > The patch that caused the problem had multiple issues: > > - it broke big-endian ARM kernels: any machine that was working > correctly with a little-endian kernel is no longer using byteswaps > on big-endian kernels, which clearly breaks them. > - On PowerPC the same thing must be true: if it was working before, > using big-endian kernels is now broken. Unlike ARM, 32-bit PowerPC > usually uses big-endian kernels, so they are likely all broken. > - The barrier for dwc2_writel is on the wrong side of the __raw_writel(), > so the MMIO no longer synchronizes with DMA operations. > - On architectures that require specific CPU instructions for MMIO > access, using the __raw_ variant may turn this into a pointer > dereference that does not have the same effect as the readl/writel. > > I think we can simply make this set of accessors architecture-dependent > (MIPS vs. the rest of the world) to revert ARM and PowerPC back to > the working version. and patch all drivers similarly? Shouldn't arch/mips itself deal with it and hide it from drivers ? -- balbi
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-09 17:10 +0200 |
| Message-ID | <rwUYO-87h-25@gated-at.bofh.it> |
| In reply to | #1396930 |
On Monday 09 May 2016 13:39:50 Felipe Balbi wrote: > Arnd Bergmann <arnd@arndb.de> writes: > > On Monday 09 May 2016 10:23:22 Benjamin Herrenschmidt wrote: > >> On Sun, 2016-05-08 at 13:44 +0200, Christian Lamparter wrote: > > > > The patch that caused the problem had multiple issues: > > > > - it broke big-endian ARM kernels: any machine that was working > > correctly with a little-endian kernel is no longer using byteswaps > > on big-endian kernels, which clearly breaks them. > > - On PowerPC the same thing must be true: if it was working before, > > using big-endian kernels is now broken. Unlike ARM, 32-bit PowerPC > > usually uses big-endian kernels, so they are likely all broken. > > - The barrier for dwc2_writel is on the wrong side of the __raw_writel(), > > so the MMIO no longer synchronizes with DMA operations. > > - On architectures that require specific CPU instructions for MMIO > > access, using the __raw_ variant may turn this into a pointer > > dereference that does not have the same effect as the readl/writel. > > > > I think we can simply make this set of accessors architecture-dependent > > (MIPS vs. the rest of the world) to revert ARM and PowerPC back to > > the working version. > > and patch all drivers similarly? Shouldn't arch/mips itself deal with it > and hide it from drivers ? > Unfortunately, I don't see any way this could be done in MIPS specific code: There is typically a byteswap between the internal bus and the PCI bus on big-endian MIPS systems, so the PCI MMIO ends up being little-endian, which matches the expected behavior of readl/writel. However, drivers for non-PCI devices often use the same readl/writel accessors because that is how it's done on ARMv6/ARMv7. Doing it hardcoded by architecture is just the simplest way to deal with it, working on the assumption that nothing actually needs the runtime detection that Ben suggested. Detecting the endianess of the device is probably the best future-proof solution, but it's also considerably more work to do in the driver, and comes with a tiny runtime overhead. Arnd
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-09 22:20 +0200 |
| Message-ID | <rwZOP-48t-13@gated-at.bofh.it> |
| In reply to | #1397128 |
On Monday 09 May 2016 21:06:07 Christian Lamparter wrote:
> Uh, Thanks for the participation!
>
> On Monday, May 09, 2016 05:08:48 PM Arnd Bergmann wrote:
> > On Monday 09 May 2016 13:39:50 Felipe Balbi wrote:
> > > Arnd Bergmann <arnd@arndb.de> writes:
> > > > On Monday 09 May 2016 10:23:22 Benjamin Herrenschmidt wrote:
> > > >> On Sun, 2016-05-08 at 13:44 +0200, Christian Lamparter wrote:
> > > >
> > > > The patch that caused the problem had multiple issues:
> > > >
> > > > - it broke big-endian ARM kernels: any machine that was working
> > > > correctly with a little-endian kernel is no longer using byteswaps
> > > > on big-endian kernels, which clearly breaks them.
> > > > - On PowerPC the same thing must be true: if it was working before,
> > > > using big-endian kernels is now broken. Unlike ARM, 32-bit PowerPC
> > > > usually uses big-endian kernels, so they are likely all broken.
> > > > - The barrier for dwc2_writel is on the wrong side of the __raw_writel(),
> > > > so the MMIO no longer synchronizes with DMA operations.
> > > > - On architectures that require specific CPU instructions for MMIO
> > > > access, using the __raw_ variant may turn this into a pointer
> > > > dereference that does not have the same effect as the readl/writel.
> > > >
> > > > I think we can simply make this set of accessors architecture-dependent
> > > > (MIPS vs. the rest of the world) to revert ARM and PowerPC back to
> > > > the working version.
> > >
> > > and patch all drivers similarly? Shouldn't arch/mips itself deal with it
> > > and hide it from drivers ?
> > >
> >
> > Unfortunately, I don't see any way this could be done in MIPS specific
> > code: There is typically a byteswap between the internal bus and the PCI
> > bus on big-endian MIPS systems, so the PCI MMIO ends up being little-endian,
> > which matches the expected behavior of readl/writel. However, drivers
> > for non-PCI devices often use the same readl/writel accessors because
> > that is how it's done on ARMv6/ARMv7.
> >
> > Doing it hardcoded by architecture is just the simplest way to deal
> > with it, working on the assumption that nothing actually needs the
> > runtime detection that Ben suggested. Detecting the endianess of the
> > device is probably the best future-proof solution, but it's also
> > considerably more work to do in the driver, and comes with a
> > tiny runtime overhead.
> >
> Ok, just to have it on the table. I went ahead and implemented the
> "Detect Endian".
>
> I looked in the DWC USB OTG's Databook documents v3.30a (If someone wants
> them too, PM me). If I read the Application Interface Feature list on
> page 30 correctly. The endianess is selectable by a "pin".... That said
> I don't know which one is it in the APM82181 or any other arch. I looked
> around for configuration registers and stuff but unlike DesignWare's AHB
> DMA Controller, there's no Bit in the "User HW Config Registers" that
> would tell us if it was configured as big-endian or little-endian at
> the moment.
>
> One way out would be to detect the endianess automatically by looking at
> the values in the GSNPSID register. This is a read-only register containing
> the release number of the core being used. The "upper" 16-bits of it are
> hardcoded to 0x4f45 (The comment in dwc2_get_hwparams [1] has it backwards
> but not the code below).
Good, that should work.
> I ran into the following issues:
> - gadget.c uses ioread32_rep [0] & iowrite32_rep [1].
> This is interesting because both of these functions actually use
> the __raw_io* on powerpc. This is because powerpc uses the default
> defines of include/asm-generic/io.h [2].
>
> Ideally, this should be done by sth like a writesl_be or writesl(e)
> function. But I found none so for now: Let's make a ugly hack:
> to_correct_endian that will work for testing, but will be replaced.
You must have gotten this wrong: writesl() and the other variants
are used to copy byte streams, which are always in the correct
endianess, i.e. copying them one byte at a time should result in
the same in-memory representation as copying them four bytes at a time.
You should never need an additional swap in here.
> - is_little_endian (do we want a separate is_big_endian?)
> Also, do we want to be able to overwrite the detection code
> if the endian setting was set in the device tree?. For now
> it always does auto detection (see dwc2_detect_endiannes() ).
I'd say that detecting endianess from the register is the safest
approach. We can also parse the standard DT properties to do the
same, but they can easily be stale, especially when the driver
has already gotten this wrong for some users.
> ( - 80 character per line issues, is it possible to drop the
> hsotg->reg + REGISTER from the dwc2_readl/writel since we
> pass the hsotg now anyway and do the reg + REGISTER
> calculation in the accessor? I played around with macros
> as most functions calling the accessors have the hsotg
> variable anyway )
I would definitely recommend doing this. If necessary there can
be an extra set of functions, but this is what a lot of drivers do
when you pass the device structure to an MMIO accessor.
> [0] <http://lxr.free-electrons.com/source/drivers/usb/dwc2/gadget.c#L1488>
> [1] <http://lxr.free-electrons.com/source/drivers/usb/dwc2/gadget.c#L462>
> [2] <http://lxr.free-electrons.com/source/include/asm-generic/io.h#L315>
>
> +void dwc2_detect_endiannes(struct dwc2_hsotg *hsotg)
> +{
> + u32 sid;
> +
> + sid = __raw_readl(hsotg->regs + GSNPSID);
> + if ((le32_to_cpu(sid) & 0xffff0000) == 0x4f540000)
> + hsotg->is_little_endian = 1;
> +}
__raw_readl() might not do what you want here, I'd always use readl()
for the detection without the extra le32_to_cpu().
> +static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg,
> + void __iomem *addr)
> +{
> + u32 value;
> +
> + if (hsotg->is_little_endian)
> + value = ioread32(addr);
> + else
> + value = ioread32be(addr);
> +
> + return value;
> +}
> +
> +static inline void dwc2_writel(struct dwc2_hsotg *hsotg,
> + u32 value, void __iomem *addr)
> +{
> + if (hsotg->is_little_endian)
> + iowrite32(value, addr);
> + else
> + iowrite32be(value, addr);
> +
> +#ifdef DWC2_LOG_WRITES
> + pr_info("INFO:: wrote %08x to %p\n", value, addr);
> +#endif
> +}
In terms of micro-optimizing this, it may be better to use readl/writel
instead of ioread32/iowrite32: On most architectures they are the
same, but notably on x86, ioread32/iowrite32 is slightly slower
because of the indirection.
We probably only need to worry about the big-endian registers on
architectures that have an efficient ioread32be/iowrite32be.
> @@ -292,6 +294,19 @@ static void dwc2_hsotg_unmap_dma(struct dwc2_hsotg *hsotg,
> usb_gadget_unmap_request(&hsotg->gadget, req, hs_ep->dir_in);
> }
>
> +static void to_correct_endian(struct dwc2_hsotg *hsotg, u32 *data, size_t len)
> +{
> + size_t i;
> +
> + if (hsotg->is_little_endian) {
> + for (i = 0; i < len; i++)
> + data[i] = cpu_to_le32(data[i]);
> + } else {
> + for (i = 0; i < len; i++)
> + data[i] = cpu_to_be32(data[i]);
> + }
> +}
> +
> /**
My guess is that this leaves the big-endian powerpc machines broken, you
already have the correct byte stream using readsl/writesl or
ioread32_rep/iowrite32_rep.
If there is any location in the code that accesses the FIFO registers
readl/writel or a loop of those, that code should be changed to
use readsl/writesl so you don't have to double-swap the data.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | Benjamin Herrenschmidt <benh@kernel.crashing.org> |
|---|---|
| Date | 2016-05-10 00:40 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <rx20i-6qo-7@gated-at.bofh.it> |
| In reply to | #1397128 |
On Mon, 2016-05-09 at 17:08 +0200, Arnd Bergmann wrote: > > Unfortunately, I don't see any way this could be done in MIPS specific > code: There is typically a byteswap between the internal bus and the PCI > bus on big-endian MIPS systems, so the PCI MMIO ends up being little-endian, Ugh ... not exactly, re-watch my talk on the matter :-) While there is a specific lane wiring to preserve byte addresss, in the end it's the end device itself that is either BE or LE. Regardless of any "bus endianness". > which matches the expected behavior of readl/writel. However, drivers > for non-PCI devices often use the same readl/writel accessors because > that is how it's done on ARMv6/ARMv7. Even then, you can have on-SoC (non-PCI) devices that also have a different endianness from the main CPU. How does it work on ARM for example ? The device endianness should be fixed, regardless of the endianness of the core, no ? > Doing it hardcoded by architecture is just the simplest way to deal > with it, working on the assumption that nothing actually needs the > runtime detection that Ben suggested. No, it's not an archicture problem. It's a problem specific to that one SoC that the device was synthetized to be a certain endian while it was synthetized differently on another SoC... that also happens to be a different architecture. But doesn't have to. For example, we had in the past cases of both LE and BE EHCI implementations on the same architecture (PowerPC). > Detecting the endianess of the > device is probably the best future-proof solution, but it's also > considerably more work to do in the driver, and comes with a > tiny runtime overhead. The runtime overhead is probably non-measurable compared with the cost of the actual MMIOs. Cheers, Ben.
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-10 09:30 +0200 |
| Message-ID | <rxahc-69M-11@gated-at.bofh.it> |
| In reply to | #1397482 |
On Tuesday 10 May 2016 08:37:52 Benjamin Herrenschmidt wrote: > On Mon, 2016-05-09 at 17:08 +0200, Arnd Bergmann wrote: > > > > Unfortunately, I don't see any way this could be done in MIPS specific > > code: There is typically a byteswap between the internal bus and the PCI > > bus on big-endian MIPS systems, so the PCI MMIO ends up being little-endian, > > Ugh ... not exactly, re-watch my talk on the matter :-) While there is > a specific lane wiring to preserve byte addresss, in the end it's the > end device itself that is either BE or LE. Regardless of any "bus > endianness". I found your slides on http://www.linuxplumbersconf.org/2012/wp-content/uploads/2012/09/2012-lpc-ref-big-little-endian-herrenschmidt.odp but there are at least two more twists that you completely missed here: - Some architectures (e.g. ARMv5 "BE32" mode in IXP4xx, surely some others) do not implement big-endian mode by wiring up the data lines between the bus and the CPU differently between big- and little-endian mode like powerpc and armv7 "BE8" do, but instead they swizzle the *address* lines on 8-bit and 16-bit addresses. The effect of that is that normal RAM accesses work as expected both ways, and devices that are accessed using 32-bit MMIO ops never need any byteswap (you actually get "native endian") while MMIO with 8 and 16 bit width does something completely unexpected and touches the wrong register. Having an explicit byteswap on the PCI host bridge gets you the expected addresses again for 8-bit cycles but it also means that readl()/writel() again need to swap the data. - Some other architectures (e.g. Broadcom MIPS) apparently are even fancier and use a strapping pin on the SoC flips the endianess of the CPU core at the same time as all the peripheral MMIO registers, with the intention of never requiring any byte swaps. I believe they are implemented careful enough to actually get this right, but it confuses the heck out of Linux drivers that don't expect this. > > which matches the expected behavior of readl/writel. However, drivers > > for non-PCI devices often use the same readl/writel accessors because > > that is how it's done on ARMv6/ARMv7. > > Even then, you can have on-SoC (non-PCI) devices that also have a > different endianness from the main CPU. How does it work on ARM for > example ? The device endianness should be fixed, regardless of the > endianness of the core, no ? ARMv6/v7 is uses BE8 mode like powerpc: each peripheral is fixed-endian and you have to know what it is. Only Freescale managed to put identical IP blocks on various (powerpc-derived) SoCs and have a subset of them treat the access as little-endian while others remain big-endian, so all those drivers now require runtime detection. > > Doing it hardcoded by architecture is just the simplest way to deal > > with it, working on the assumption that nothing actually needs the > > runtime detection that Ben suggested. > > No, it's not an archicture problem. It's a problem specific to that one > SoC that the device was synthetized to be a certain endian while it was > synthetized differently on another SoC... that also happens to be a > different architecture. But doesn't have to. > > For example, we had in the past cases of both LE and BE EHCI > implementations on the same architecture (PowerPC). I understand this, but from what I see in this history of this particular driver, all ARM and PowerPC implementations chose to use LE registers for DWC2 because the normal approach for these is to not mess with endianess, while presumably all MIPS users of the same block wired up the endian-select line of the IP block to match that of the CPU core, again because it's what you are expected to do on a MIPS based SoC. So hardcoding it per architecture would make an assumption based on the mindset of the SoC designers rather than strict technical differences, and that can fail as soon as someone does things differently on any of them (see the Freescale example), but I still think it's the easiest workaround for backporting to stable kernels. A revert of the original patch would be even easier, but that would break the one big-endian MIPS machine we know about. > > Detecting the endianess of the > > device is probably the best future-proof solution, but it's also > > considerably more work to do in the driver, and comes with a > > tiny runtime overhead. > > The runtime overhead is probably non-measurable compared with the cost > of the actual MMIOs. Right. The code size increase is probably measurable (but still small), the runtime overhead is not. Arnd
[toc] | [prev] | [next] | [standalone]
| From | Christian Lamparter <chunkeey@googlemail.com> |
|---|---|
| Date | 2016-05-12 12:00 +0200 |
| Message-ID | <rxVzt-30G-13@gated-at.bofh.it> |
| In reply to | #1397760 |
On Tuesday, May 10, 2016 09:23:59 AM Arnd Bergmann wrote: > On Tuesday 10 May 2016 08:37:52 Benjamin Herrenschmidt wrote: > > On Mon, 2016-05-09 at 17:08 +0200, Arnd Bergmann wrote: > > > > > > Unfortunately, I don't see any way this could be done in MIPS specific > > > code: There is typically a byteswap between the internal bus and the PCI > > > bus on big-endian MIPS systems, so the PCI MMIO ends up being little-endian, > > > > Ugh ... not exactly, re-watch my talk on the matter :-) While there is > > a specific lane wiring to preserve byte addresss, in the end it's the > > end device itself that is either BE or LE. Regardless of any "bus > > endianness". > > I found your slides on > > http://www.linuxplumbersconf.org/2012/wp-content/uploads/2012/09/2012-lpc-ref-big-little-endian-herrenschmidt.odp > > but there are at least two more twists that you completely missed here: > > - Some architectures (e.g. ARMv5 "BE32" mode in IXP4xx, surely some others) > do not implement big-endian mode by wiring up the data lines between the > bus and the CPU differently between big- and little-endian mode like > powerpc and armv7 "BE8" do, but instead they swizzle the *address* lines > on 8-bit and 16-bit addresses. The effect of that is that normal RAM > accesses work as expected both ways, and devices that are accessed using > 32-bit MMIO ops never need any byteswap (you actually get "native > endian") while MMIO with 8 and 16 bit width does something completely > unexpected and touches the wrong register. Having an explicit byteswap > on the PCI host bridge gets you the expected addresses again for 8-bit > cycles but it also means that readl()/writel() again need to swap the > data. > > - Some other architectures (e.g. Broadcom MIPS) apparently are even fancier > and use a strapping pin on the SoC flips the endianess of the CPU core > at the same time as all the peripheral MMIO registers, with the intention > of never requiring any byte swaps. I believe they are implemented careful > enough to actually get this right, but it confuses the heck out of > Linux drivers that don't expect this. > > > > which matches the expected behavior of readl/writel. However, drivers > > > for non-PCI devices often use the same readl/writel accessors because > > > that is how it's done on ARMv6/ARMv7. > > > > Even then, you can have on-SoC (non-PCI) devices that also have a > > different endianness from the main CPU. How does it work on ARM for > > example ? The device endianness should be fixed, regardless of the > > endianness of the core, no ? > > ARMv6/v7 is uses BE8 mode like powerpc: each peripheral is fixed-endian > and you have to know what it is. Only Freescale managed to put identical > IP blocks on various (powerpc-derived) SoCs and have a subset of them > treat the access as little-endian while others remain big-endian, so all > those drivers now require runtime detection. > > > > Doing it hardcoded by architecture is just the simplest way to deal > > > with it, working on the assumption that nothing actually needs the > > > runtime detection that Ben suggested. > > > > No, it's not an archicture problem. It's a problem specific to that one > > SoC that the device was synthetized to be a certain endian while it was > > synthetized differently on another SoC... that also happens to be a > > different architecture. But doesn't have to. > > > > For example, we had in the past cases of both LE and BE EHCI > > implementations on the same architecture (PowerPC). > > I understand this, but from what I see in this history of this particular > driver, all ARM and PowerPC implementations chose to use LE registers for > DWC2 because the normal approach for these is to not mess with endianess, > while presumably all MIPS users of the same block wired up the endian-select > line of the IP block to match that of the CPU core, again because it's > what you are expected to do on a MIPS based SoC. > > So hardcoding it per architecture would make an assumption based on > the mindset of the SoC designers rather than strict technical differences, > and that can fail as soon as someone does things differently on any of > them (see the Freescale example), but I still think it's the easiest > workaround for backporting to stable kernels. A revert of the original > patch would be even easier, but that would break the one big-endian > MIPS machine we know about. > > > > Detecting the endianess of the > > > device is probably the best future-proof solution, but it's also > > > considerably more work to do in the driver, and comes with a > > > tiny runtime overhead. > > > > The runtime overhead is probably non-measurable compared with the cost > > of the actual MMIOs. > > Right. The code size increase is probably measurable (but still small), > the runtime overhead is not. Ok, so no rebuts or complains have been posted. I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 and it works: Tested-by: Christian Lamparter <chunkeey@googlemail.com> So, how do we go from here? There is are two small issues with the original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: #ifdef dwc2_log_writes) and I guess a proper subject would be nice. Arnd, can you please respin and post it (cc'd stable as well)? So this is can be picked up? Or what's your plan? Regards, Christian
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-12 14:00 +0200 |
| Message-ID | <rxXrA-4Y2-1@gated-at.bofh.it> |
| In reply to | #1399846 |
On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: > > > > Detecting the endianess of the > > > > device is probably the best future-proof solution, but it's also > > > > considerably more work to do in the driver, and comes with a > > > > tiny runtime overhead. > > > > > > The runtime overhead is probably non-measurable compared with the cost > > > of the actual MMIOs. > > > > Right. The code size increase is probably measurable (but still small), > > the runtime overhead is not. > > Ok, so no rebuts or complains have been posted. > > I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 > and it works: > > Tested-by: Christian Lamparter <chunkeey@googlemail.com> > > So, how do we go from here? There is are two small issues with the > original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: > #ifdef dwc2_log_writes) and I guess a proper subject would be nice. > > Arnd, can you please respin and post it (cc'd stable as well)? > So this is can be picked up? Or what's your plan? (I just realized my reply was stuck in my outbox, so the patch went out first) If I recall correctly, the rough consensus was to go with your longer patch in the future (fixed up for the comments that BenH and I sent), and I'd suggest basing it on top of a fixed version of my patch. Felipe just had another idea, to change the endianess of the dwc2 block by setting a registers (if that exists). That would indeed be preferable, then we can just revert the broken change that went into 4.4 and backport that fix instead. Arnd
[toc] | [prev] | [next] | [standalone]
| From | Christian Lamparter <chunkeey@googlemail.com> |
|---|---|
| Date | 2016-05-12 15:40 +0200 |
| Message-ID | <rxZ0l-6V8-1@gated-at.bofh.it> |
| In reply to | #1399958 |
On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: > On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: > > > > > Detecting the endianess of the > > > > > device is probably the best future-proof solution, but it's also > > > > > considerably more work to do in the driver, and comes with a > > > > > tiny runtime overhead. > > > > > > > > The runtime overhead is probably non-measurable compared with the cost > > > > of the actual MMIOs. > > > > > > Right. The code size increase is probably measurable (but still small), > > > the runtime overhead is not. > > > > Ok, so no rebuts or complains have been posted. > > > > I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 > > and it works: > > > > Tested-by: Christian Lamparter <chunkeey@googlemail.com> > > > > So, how do we go from here? There is are two small issues with the > > original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: > > #ifdef dwc2_log_writes) and I guess a proper subject would be nice. > > > > Arnd, can you please respin and post it (cc'd stable as well)? > > So this is can be picked up? Or what's your plan? > > (I just realized my reply was stuck in my outbox, so the patch > went out first) > > If I recall correctly, the rough consensus was to go with your longer > patch in the future (fixed up for the comments that BenH and > I sent), and I'd suggest basing it on top of a fixed version of > my patch. Well, but it comes with the "overhead"! So this was just as I said: "Let's look at it and see if it's any good"... And I think it isn't since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN archs etc... > Felipe just had another idea, to change the endianess of the dwc2 > block by setting a registers (if that exists). That would indeed > be preferable, then we can just revert the broken change that > went into 4.4 and backport that fix instead. Just a quick reply. I have the docs for the thing. There's something like that in GAHBCFG at Bit 24... BUT it only switches the endiannes for the DMA descriptors (which is not always used, there are devices with PIO only)! It doesn't deal with the MMIO access at all. The pin that would select which endian the device uses is probably connected to a DCR or GPIO but I don't know which or where so this is more or less useless. (Or the selectable endianness was dropped during synth). Regards, Christian
[toc] | [prev] | [next] | [standalone]
| From | John Youn <John.Youn@synopsys.com> |
|---|---|
| Date | 2016-05-12 20:50 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <ry3Qm-2Xu-11@gated-at.bofh.it> |
| In reply to | #1400088 |
On 5/12/2016 6:30 AM, Christian Lamparter wrote: > On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: >> On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: >>>>>> Detecting the endianess of the >>>>>> device is probably the best future-proof solution, but it's also >>>>>> considerably more work to do in the driver, and comes with a >>>>>> tiny runtime overhead. >>>>> >>>>> The runtime overhead is probably non-measurable compared with the cost >>>>> of the actual MMIOs. >>>> >>>> Right. The code size increase is probably measurable (but still small), >>>> the runtime overhead is not. >>> >>> Ok, so no rebuts or complains have been posted. >>> >>> I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 >>> and it works: >>> >>> Tested-by: Christian Lamparter <chunkeey@googlemail.com> >>> >>> So, how do we go from here? There is are two small issues with the >>> original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: >>> #ifdef dwc2_log_writes) and I guess a proper subject would be nice. >>> >>> Arnd, can you please respin and post it (cc'd stable as well)? >>> So this is can be picked up? Or what's your plan? >> >> (I just realized my reply was stuck in my outbox, so the patch >> went out first) >> >> If I recall correctly, the rough consensus was to go with your longer >> patch in the future (fixed up for the comments that BenH and >> I sent), and I'd suggest basing it on top of a fixed version of >> my patch. > Well, but it comes with the "overhead"! So this was just as I said: > "Let's look at it and see if it's any good"... And I think it isn't > since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN > archs etc... I slightly prefer the more general patch for future kernel versions. The overhead will probably be negligible, but we can perform some testing to make sure. Can you resubmit with all gathered feedback? > >> Felipe just had another idea, to change the endianess of the dwc2 >> block by setting a registers (if that exists). That would indeed >> be preferable, then we can just revert the broken change that >> went into 4.4 and backport that fix instead. > Just a quick reply. I have the docs for the thing. There's something > like that in GAHBCFG at Bit 24... BUT it only switches the endiannes > for the DMA descriptors (which is not always used, there are devices > with PIO only)! It doesn't deal with the MMIO access at all. That's correct. It only affects descriptor endianness for DMA descriptor mode of operation. Regards, John
[toc] | [prev] | [next] | [standalone]
| From | Christian Lamparter <chunkeey@googlemail.com> |
|---|---|
| Date | 2016-05-12 22:40 +0200 |
| Message-ID | <ry5yO-4H0-9@gated-at.bofh.it> |
| In reply to | #1400287 |
On Thursday, May 12, 2016 11:40:28 AM John Youn wrote: > On 5/12/2016 6:30 AM, Christian Lamparter wrote: > > On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: > >> On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: > >>>>>> Detecting the endianess of the > >>>>>> device is probably the best future-proof solution, but it's also > >>>>>> considerably more work to do in the driver, and comes with a > >>>>>> tiny runtime overhead. > >>>>> > >>>>> The runtime overhead is probably non-measurable compared with the cost > >>>>> of the actual MMIOs. > >>>> > >>>> Right. The code size increase is probably measurable (but still small), > >>>> the runtime overhead is not. > >>> > >>> Ok, so no rebuts or complains have been posted. > >>> > >>> I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 > >>> and it works: > >>> > >>> Tested-by: Christian Lamparter <chunkeey@googlemail.com> > >>> > >>> So, how do we go from here? There is are two small issues with the > >>> original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: > >>> #ifdef dwc2_log_writes) and I guess a proper subject would be nice. > >>> > >>> Arnd, can you please respin and post it (cc'd stable as well)? > >>> So this is can be picked up? Or what's your plan? > >> > >> (I just realized my reply was stuck in my outbox, so the patch > >> went out first) > >> > >> If I recall correctly, the rough consensus was to go with your longer > >> patch in the future (fixed up for the comments that BenH and > >> I sent), and I'd suggest basing it on top of a fixed version of > >> my patch. > > Well, but it comes with the "overhead"! So this was just as I said: > > "Let's look at it and see if it's any good"... And I think it isn't > > since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN > > archs etc... > > I slightly prefer the more general patch for future kernel versions. > The overhead will probably be negligible, but we can perform some > testing to make sure. > > Can you resubmit with all gathered feedback? Yes I think I can do that. But I would really like to get the regression out of the way. So for that: I back Arnd's patch. It explains the problem much better and doesn't kill MIPS like the revert I was doing in my initial post to the MLs. Also, another bonus: his patch is suited to port to stable. The auto-detection approach is not that easy to get right, given all the stuff that's going on with BE8, LE4, ... So can we have your "blessing" for Arnd's patch for now? since that way, I can base my patch on top of his work about the issues of endiannes? (Just say: ACK :) ) Arnd: do you have a version with the #ifdef lower/uppercase fix? Or should I give it a try (and fail in a different way ;) ) > >> Felipe just had another idea, to change the endianess of the dwc2 > >> block by setting a registers (if that exists). That would indeed > >> be preferable, then we can just revert the broken change that > >> went into 4.4 and backport that fix instead. > > Just a quick reply. I have the docs for the thing. There's something > > like that in GAHBCFG at Bit 24... BUT it only switches the endiannes > > for the DMA descriptors (which is not always used, there are devices > > with PIO only)! It doesn't deal with the MMIO access at all. > > That's correct. It only affects descriptor endianness for DMA > descriptor mode of operation. Ok. The funny thing is that for the MyBook Live Duo this setting might be important since the PLB_DMA engine is not part of the DWC library... Instead it's from IBM and operates in: Big Endian :-D. Regards, Christian
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-12 23:00 +0200 |
| Message-ID | <ry5S9-4Z1-1@gated-at.bofh.it> |
| In reply to | #1400358 |
On Thursday 12 May 2016 22:39:36 Christian Lamparter wrote: > On Thursday, May 12, 2016 11:40:28 AM John Youn wrote: > > On 5/12/2016 6:30 AM, Christian Lamparter wrote: > > > On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: > > >> > > >> If I recall correctly, the rough consensus was to go with your longer > > >> patch in the future (fixed up for the comments that BenH and > > >> I sent), and I'd suggest basing it on top of a fixed version of > > >> my patch. > > > Well, but it comes with the "overhead"! So this was just as I said: > > > "Let's look at it and see if it's any good"... And I think it isn't > > > since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN > > > archs etc... > > > > I slightly prefer the more general patch for future kernel versions. > > The overhead will probably be negligible, but we can perform some > > testing to make sure. > > > > Can you resubmit with all gathered feedback? > Yes I think I can do that. But I would really like to get the > regression out of the way. So for that: I back Arnd's patch. > It explains the problem much better and doesn't kill MIPS > like the revert I was doing in my initial post to the MLs. > Also, another bonus: his patch is suited to port to stable. > > The auto-detection approach is not that easy to get right, > given all the stuff that's going on with BE8, LE4, ... So > can we have your "blessing" for Arnd's patch for now? since > that way, I can base my patch on top of his work about the > issues of endiannes? (Just say: ACK ) > > Arnd: do you have a version with the #ifdef lower/uppercase > fix? Or should I give it a try (and fail in a different way ) I've already fixed it up locally, will send the latest version so it's out there, whether Felipe takes it or not. Arnd
[toc] | [prev] | [next] | [standalone]
| From | John Youn <John.Youn@synopsys.com> |
|---|---|
| Date | 2016-05-12 23:00 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <ry5Sa-4Z1-21@gated-at.bofh.it> |
| In reply to | #1400358 |
On 5/12/2016 1:39 PM, Christian Lamparter wrote: > On Thursday, May 12, 2016 11:40:28 AM John Youn wrote: >> On 5/12/2016 6:30 AM, Christian Lamparter wrote: >>> On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: >>>> On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: >>>>>>>> Detecting the endianess of the >>>>>>>> device is probably the best future-proof solution, but it's also >>>>>>>> considerably more work to do in the driver, and comes with a >>>>>>>> tiny runtime overhead. >>>>>>> >>>>>>> The runtime overhead is probably non-measurable compared with the cost >>>>>>> of the actual MMIOs. >>>>>> >>>>>> Right. The code size increase is probably measurable (but still small), >>>>>> the runtime overhead is not. >>>>> >>>>> Ok, so no rebuts or complains have been posted. >>>>> >>>>> I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 >>>>> and it works: >>>>> >>>>> Tested-by: Christian Lamparter <chunkeey@googlemail.com> >>>>> >>>>> So, how do we go from here? There is are two small issues with the >>>>> original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: >>>>> #ifdef dwc2_log_writes) and I guess a proper subject would be nice. >>>>> >>>>> Arnd, can you please respin and post it (cc'd stable as well)? >>>>> So this is can be picked up? Or what's your plan? >>>> >>>> (I just realized my reply was stuck in my outbox, so the patch >>>> went out first) >>>> >>>> If I recall correctly, the rough consensus was to go with your longer >>>> patch in the future (fixed up for the comments that BenH and >>>> I sent), and I'd suggest basing it on top of a fixed version of >>>> my patch. >>> Well, but it comes with the "overhead"! So this was just as I said: >>> "Let's look at it and see if it's any good"... And I think it isn't >>> since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN >>> archs etc... >> >> I slightly prefer the more general patch for future kernel versions. >> The overhead will probably be negligible, but we can perform some >> testing to make sure. >> >> Can you resubmit with all gathered feedback? > Yes I think I can do that. But I would really like to get the > regression out of the way. So for that: I back Arnd's patch. > It explains the problem much better and doesn't kill MIPS > like the revert I was doing in my initial post to the MLs. > Also, another bonus: his patch is suited to port to stable. > > The auto-detection approach is not that easy to get right, > given all the stuff that's going on with BE8, LE4, ... So > can we have your "blessing" for Arnd's patch for now? since > that way, I can base my patch on top of his work about the > issues of endiannes? (Just say: ACK :) ) > I agree Arnd's patch is best for stable. We can also apply it to mainline until we get the autodection working as well. Unless Felipe has objections. > Arnd: do you have a version with the #ifdef lower/uppercase > fix? Or should I give it a try (and fail in a different way ;) ) > >>>> Felipe just had another idea, to change the endianess of the dwc2 >>>> block by setting a registers (if that exists). That would indeed >>>> be preferable, then we can just revert the broken change that >>>> went into 4.4 and backport that fix instead. >>> Just a quick reply. I have the docs for the thing. There's something >>> like that in GAHBCFG at Bit 24... BUT it only switches the endiannes >>> for the DMA descriptors (which is not always used, there are devices >>> with PIO only)! It doesn't deal with the MMIO access at all. >> >> That's correct. It only affects descriptor endianness for DMA >> descriptor mode of operation. > > Ok. The funny thing is that for the MyBook Live Duo this setting might > be important since the PLB_DMA engine is not part of the DWC library... > Instead it's from IBM and operates in: Big Endian :-D. > Are you sure the controller is using descriptor DMA? It's more likely using buffer DMA which this setting doesn't affect. DWC2 doesn't support Descriptor DMA in device mode on mainline yet. If it's a host then it might be. Regards, John
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-14 21:50 +0200 |
| Message-ID | <ryNJw-7dt-3@gated-at.bofh.it> |
| In reply to | #1400287 |
On Saturday 14 May 2016 15:11:34 Christian Lamparter wrote:
>
> +#ifdef CONFIG_MIPS
> +/*
> + * There are some MIPS machines that can run in either big-endian
> + * or little-endian mode and that use the dwc2 register without
> + * a byteswap in both ways.
> + * Unlike other architectures, MIPS apparently does not require a
> + * barrier before the __raw_writel() to synchronize with DMA but does
> + * require the barrier after the __raw_writel() to serialize a set of
> + * writes. This set of operations was added specifically for MIPS and
> + * should only be used there.
> + */
> +static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg,
> + ptrdiff_t reg)
> +{
> + const void __iomem *addr = hsotg->regs + reg;
> + u32 value = __raw_readl(addr);
> +
>
I see you keep the special case for MIPS here, I'd vote for folding
that back into the architecture-independent version and not treating
MIPS any different from the others. With your endianness detection, MIPS
should have no way of getting the byteorder wrong, and on MIPS the
platform is responsible for adding the appropriate barriers to
readl/writel.
Other than this, the patch looks good to me.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | John Youn <John.Youn@synopsys.com> |
|---|---|
| Date | 2016-05-18 02:00 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <rzX45-2JS-7@gated-at.bofh.it> |
| In reply to | #1400287 |
On 5/14/2016 6:11 AM, Christian Lamparter wrote: > On Thursday, May 12, 2016 11:40:28 AM John Youn wrote: >> On 5/12/2016 6:30 AM, Christian Lamparter wrote: >>> On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: >>>> On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: >>>>>>>> Detecting the endianess of the >>>>>>>> device is probably the best future-proof solution, but it's also >>>>>>>> considerably more work to do in the driver, and comes with a >>>>>>>> tiny runtime overhead. >>>>>>> >>>>>>> The runtime overhead is probably non-measurable compared with the cost >>>>>>> of the actual MMIOs. >>>>>> >>>>>> Right. The code size increase is probably measurable (but still small), >>>>>> the runtime overhead is not. >>>>> >>>>> Ok, so no rebuts or complains have been posted. >>>>> >>>>> I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 >>>>> and it works: >>>>> >>>>> Tested-by: Christian Lamparter <chunkeey@googlemail.com> >>>>> >>>>> So, how do we go from here? There is are two small issues with the >>>>> original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: >>>>> #ifdef dwc2_log_writes) and I guess a proper subject would be nice. >>>>> >>>>> Arnd, can you please respin and post it (cc'd stable as well)? >>>>> So this is can be picked up? Or what's your plan? >>>> >>>> (I just realized my reply was stuck in my outbox, so the patch >>>> went out first) >>>> >>>> If I recall correctly, the rough consensus was to go with your longer >>>> patch in the future (fixed up for the comments that BenH and >>>> I sent), and I'd suggest basing it on top of a fixed version of >>>> my patch. >>> Well, but it comes with the "overhead"! So this was just as I said: >>> "Let's look at it and see if it's any good"... And I think it isn't >>> since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN >>> archs etc... >> >> I slightly prefer the more general patch for future kernel versions. >> The overhead will probably be negligible, but we can perform some >> testing to make sure. >> >> Can you resubmit with all gathered feedback? > > Yes, here are the changes. > > I've tested it on my MyBook Live Duo. The usbotg comes right up: > [12610.540004] dwc2 4bff80000.usbotg: USB bus 1 deregistered > [12612.513934] dwc2 4bff80000.usbotg: Specified GNPTXFDEP=1024 > 256 > [12612.518756] dwc2 4bff80000.usbotg: EPs: 3, shared fifos, 2042 entries in SPRAM > [12612.530112] dwc2 4bff80000.usbotg: DWC OTG Controller > [12612.533948] dwc2 4bff80000.usbotg: new USB bus registered, assigned bus number 1 > [12612.540083] dwc2 4bff80000.usbotg: irq 33, io mem 0x00000000 > > John: Can you run some perf test with it? > > I've based this on: > > commit 6ea2fffc9057a67df1994d85a7c085d899eaa25a > Author: Arnd Bergmann <arnd@arndb.de> > Date: Fri May 13 15:52:27 2016 +0200 > > usb: dwc2: fix regression on big-endian PowerPC/ARM systems > > so naturally, it needs to be applied first. > Most of the conversion work was done by the attached > coccinelle semantic patches. > > I had to edit the __bic32 and __orr32 helpers by hand. > As well as some debugfs code and stuff in gadget.c. > Thanks Christian. I'll keep this in our internal tree and send it to Felipe later. This causes a bunch of conflicts that I have to fix up and I should do a bit of testing as well. And since there is a patch that fixes the regression this is can wait. Regards, John
[toc] | [prev] | [next] | [standalone]
| From | Christian Lamparter <chunkeey@googlemail.com> |
|---|---|
| Date | 2016-05-18 21:20 +0200 |
| Message-ID | <rAfaG-6av-23@gated-at.bofh.it> |
| In reply to | #1402657 |
On Tuesday, May 17, 2016 04:50:48 PM John Youn wrote:
> On 5/14/2016 6:11 AM, Christian Lamparter wrote:
> > On Thursday, May 12, 2016 11:40:28 AM John Youn wrote:
> >> On 5/12/2016 6:30 AM, Christian Lamparter wrote:
> >>> On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote:
> >>>> On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote:
> >>>>>>>> Detecting the endianess of the
> >>>>>>>> device is probably the best future-proof solution, but it's also
> >>>>>>>> considerably more work to do in the driver, and comes with a
> >>>>>>>> tiny runtime overhead.
> >>>>>>>
> >>>>>>> The runtime overhead is probably non-measurable compared with the cost
> >>>>>>> of the actual MMIOs.
> >>>>>>
> >>>>>> Right. The code size increase is probably measurable (but still small),
> >>>>>> the runtime overhead is not.
> >>>>>
> >>>>> Ok, so no rebuts or complains have been posted.
> >>>>>
> >>>>> I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354
> >>>>> and it works:
> >>>>>
> >>>>> Tested-by: Christian Lamparter <chunkeey@googlemail.com>
> >>>>>
> >>>>> So, how do we go from here? There is are two small issues with the
> >>>>> original patch (#ifdef DWC2_LOG_WRITES got converted to lower case:
> >>>>> #ifdef dwc2_log_writes) and I guess a proper subject would be nice.
> >>>>>
> >>>>> Arnd, can you please respin and post it (cc'd stable as well)?
> >>>>> So this is can be picked up? Or what's your plan?
> >>>>
> >>>> (I just realized my reply was stuck in my outbox, so the patch
> >>>> went out first)
> >>>>
> >>>> If I recall correctly, the rough consensus was to go with your longer
> >>>> patch in the future (fixed up for the comments that BenH and
> >>>> I sent), and I'd suggest basing it on top of a fixed version of
> >>>> my patch.
> >>> Well, but it comes with the "overhead"! So this was just as I said:
> >>> "Let's look at it and see if it's any good"... And I think it isn't
> >>> since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN
> >>> archs etc...
> >>
> >> I slightly prefer the more general patch for future kernel versions.
> >> The overhead will probably be negligible, but we can perform some
> >> testing to make sure.
> >>
> >> Can you resubmit with all gathered feedback?
> >
> > Yes, here are the changes.
> >
> > I've tested it on my MyBook Live Duo. The usbotg comes right up:
> > [12610.540004] dwc2 4bff80000.usbotg: USB bus 1 deregistered
> > [12612.513934] dwc2 4bff80000.usbotg: Specified GNPTXFDEP=1024 > 256
> > [12612.518756] dwc2 4bff80000.usbotg: EPs: 3, shared fifos, 2042 entries in SPRAM
> > [12612.530112] dwc2 4bff80000.usbotg: DWC OTG Controller
> > [12612.533948] dwc2 4bff80000.usbotg: new USB bus registered, assigned bus number 1
> > [12612.540083] dwc2 4bff80000.usbotg: irq 33, io mem 0x00000000
> >
> > John: Can you run some perf test with it?
> >
> > I've based this on:
> >
> > commit 6ea2fffc9057a67df1994d85a7c085d899eaa25a
> > Author: Arnd Bergmann <arnd@arndb.de>
> > Date: Fri May 13 15:52:27 2016 +0200
> >
> > usb: dwc2: fix regression on big-endian PowerPC/ARM systems
> >
> > so naturally, it needs to be applied first.
> > Most of the conversion work was done by the attached
> > coccinelle semantic patches.
> >
> > I had to edit the __bic32 and __orr32 helpers by hand.
> > As well as some debugfs code and stuff in gadget.c.
> >
>
> Thanks Christian.
>
> I'll keep this in our internal tree and send it to Felipe later. This
> causes a bunch of conflicts that I have to fix up and I should do a
> bit of testing as well.
>
> And since there is a patch that fixes the regression this is can wait.
>
> Regards,
> John
---
Hey, that's really nice of you to do that :-D. Please keep me in the
loop (Cc) for those then.
Yes, this needs definitely testing on all the affected ARCHs.
I've attached a diff to a updated version of the patch. It
drops the special MIPS case (as requested by Arnd).
BTW, I looked into the ioread32_rep and iowrite32_rep again. I'm
not entirely convinced that the hardware FIFOs are actually endian
neutral. But I can't verify it since my Western Digital My Book Live
only supports the host configuration (forces host mode), so I don't
know what a device in dual-mode or peripheral do here.
The reason why I think it was broken is because there's a PIO copy
to and from the HCFIFO(x) in dwc2_hc_write_packet and
dwc2_hc_read_packet access in the hcd.c file as well... And there,
the code was using the dwc2_readl and dwc2_writel to access the data.
I added special accessors for the FIFOS now:
dwc2_readl_rep and dwc2_writel_rep.
I went all the way and implemented the helpers to do unaligned access
if necessary (not sure if adding likely branches is a good idea, as
this could be either always true or false for a specific driver the
whole time).
NB: it also fixes a "regs variable not used in dwc2_hsotg_dump" warning
if DEBUG isn't selected.
NB2: If it you need a patch against a specific tree, please
let me know.
---
diff --git a/drivers/usb/dwc2/core.h b/drivers/usb/dwc2/core.h
index 2fa57cd..69030bb 100644
--- a/drivers/usb/dwc2/core.h
+++ b/drivers/usb/dwc2/core.h
@@ -42,6 +42,7 @@
#include <linux/usb/gadget.h>
#include <linux/usb/otg.h>
#include <linux/usb/phy.h>
+#include <asm/unaligned.h>
#include "hw.h"
/*
@@ -958,50 +959,6 @@ enum dwc2_halt_status {
DWC2_HC_XFER_URB_DEQUEUE,
};
-#ifdef CONFIG_MIPS
-/*
- * There are some MIPS machines that can run in either big-endian
- * or little-endian mode and that use the dwc2 register without
- * a byteswap in both ways.
- * Unlike other architectures, MIPS apparently does not require a
- * barrier before the __raw_writel() to synchronize with DMA but does
- * require the barrier after the __raw_writel() to serialize a set of
- * writes. This set of operations was added specifically for MIPS and
- * should only be used there.
- */
-static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg,
- ptrdiff_t reg)
-{
- const void __iomem *addr = hsotg->regs + reg;
- u32 value = __raw_readl(addr);
-
- /*
- * In order to preserve endianness __raw_* operation is used. Therefore
- * a barrier is needed to ensure IO access is not re-ordered across
- * reads or writes
- */
- mb();
- return value;
-}
-
-static inline void dwc2_writel(struct dwc2_hsotg *hsotg, u32 value,
- ptrdiff_t reg)
-{
- const void __iomem *addr = hsotg->regs + reg;
- __raw_writel(value, addr);
-
- /*
- * In order to preserve endianness __raw_* operation is used. Therefore
- * a barrier is needed to ensure IO access is not re-ordered across
- * reads or writes
- */
- mb();
-#ifdef DWC2_LOG_WRITES
- pr_info("INFO:: wrote %08x to %p\n", value, addr);
-#endif
-}
-#else
-/* Normal architectures just use readl/write_be */
static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg,
ptrdiff_t reg)
{
@@ -1014,7 +971,8 @@ static inline u32 dwc2_readl(struct dwc2_hsotg *hsotg,
}
-static inline void dwc2_writel(struct dwc2_hsotg *hsotg, u32 value,
+static inline void dwc2_writel(struct dwc2_hsotg *hsotg,
+ const u32 value,
ptrdiff_t reg)
{
void __iomem *addr = hsotg->regs + reg;
@@ -1028,7 +986,103 @@ static inline void dwc2_writel(struct dwc2_hsotg *hsotg, u32 value,
pr_info("info:: wrote %08x to %p\n", value, addr);
#endif
}
-#endif
+
+static inline void dwc2_readl_rep(struct dwc2_hsotg *hsotg,
+ ptrdiff_t reg,
+ u32 *buf, const size_t len)
+{
+ void __iomem *addr = hsotg->regs + reg;
+ size_t i, remaining = len & ~4;
+
+ if (hsotg->is_big_endian) {
+ if (likely(IS_ALIGNED(*buf, 0x4))) {
+ for (i = len >> 2; i > 0; i--)
+ *buf++ = ioread32be(addr);
+ } else {
+ /* xfer_buf is not DWORD aligned */
+ for (i = len >> 2; i > 0; i--) {
+ u32 data = ioread32be(addr);
+
+ put_unaligned(data, buf);
+ buf++;
+ }
+ }
+ } else {
+ /* little-endian accessors */
+ if (likely(IS_ALIGNED(*buf, 0x4))) {
+ for (i = len >> 2; i > 0; i--)
+ *buf++ = ioread32(addr);
+
+ } else {
+ /* xfer_buf is not DWORD aligned */
+ for (i = len >> 2; i > 0; i--) {
+ u32 data = ioread32be(addr);
+
+ put_unaligned(data, buf);
+ buf++;
+ }
+ }
+ }
+
+ if (unlikely(remaining)) {
+ u32 data_u32;
+ u8 *buf_u8 = (u8 *) buf;
+ u8 *data_u8 = (u8 *) &data_u32;
+
+ data_u32 = dwc2_readl(hsotg, reg);
+
+ while (remaining--)
+ *buf_u8++ = *data_u8++;
+ }
+}
+
+static inline void dwc2_writel_rep(struct dwc2_hsotg *hsotg,
+ const ptrdiff_t reg,
+ const u32 *buf, const size_t len)
+{
+ void __iomem *addr = hsotg->regs + reg;
+ size_t i, remaining = len & ~4;
+
+ if (hsotg->is_big_endian) {
+ if (likely(IS_ALIGNED(*buf, 0x4))) {
+ for (i = len >> 2; i > 0; i--)
+ iowrite32be(*buf++, addr);
+ } else {
+ /* xfer_buf is not DWORD aligned */
+ for (i = len >> 2; i > 0; i--) {
+ u32 data = get_unaligned(buf);
+
+ iowrite32be(data, addr);
+ buf++;
+ }
+ }
+ } else {
+ /* little-endian accessors */
+ if (likely(IS_ALIGNED(*buf, 0x4))) {
+ for (i = len >> 2; i > 0; i--)
+ iowrite32(*buf++, addr);
+ } else {
+ /* xfer_buf is not DWORD aligned */
+ for (i = len >> 2; i > 0; i--) {
+ u32 data = get_unaligned(buf);
+
+ iowrite32(data, addr);
+ buf++;
+ }
+ }
+ }
+
+ if (unlikely(remaining)) {
+ u32 data_u32;
+ u8 *buf_u8 = (u8 *) buf;
+ u8 *data_u8 = (u8 *) &data_u32;
+
+ while (remaining--)
+ *data_u8++ = *buf_u8++;
+
+ dwc2_writel(hsotg, data_u32, reg);
+ }
+}
extern int dwc2_detect_endiannes(struct dwc2_hsotg *hsotg);
diff --git a/drivers/usb/dwc2/gadget.c b/drivers/usb/dwc2/gadget.c
index 2c687d9..531b30f 100644
--- a/drivers/usb/dwc2/gadget.c
+++ b/drivers/usb/dwc2/gadget.c
@@ -317,7 +317,7 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
u32 gnptxsts = dwc2_readl(hsotg, GNPTXSTS);
int buf_pos = hs_req->req.actual;
int to_write = hs_ep->size_loaded;
- void *data;
+ u32 *data;
int can_write;
int pkt_round;
int max_transfer;
@@ -457,10 +457,9 @@ static int dwc2_hsotg_write_fifo(struct dwc2_hsotg *hsotg,
if (periodic)
hs_ep->fifo_load += to_write;
- to_write = DIV_ROUND_UP(to_write, 4);
data = hs_req->req.buf + buf_pos;
- iowrite32_rep(hsotg->regs + EPFIFO(hs_ep->index), data, to_write);
+ dwc2_writel_rep(hsotg, EPFIFO(hs_ep->index), data, to_write);
return (to_write >= can_write) ? -ENOSPC : 0;
}
@@ -1439,12 +1438,11 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
{
struct dwc2_hsotg_ep *hs_ep = hsotg->eps_out[ep_idx];
struct dwc2_hsotg_req *hs_req = hs_ep->req;
- void __iomem *fifo = hsotg->regs + EPFIFO(ep_idx);
+ u32 *data;
int to_read;
int max_req;
int read_ptr;
-
if (!hs_req) {
u32 epctl = dwc2_readl(hsotg, DOEPCTL(ep_idx));
int ptr;
@@ -1455,7 +1453,7 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
/* dump the data from the FIFO, we've nothing we can do */
for (ptr = 0; ptr < size; ptr += 4)
- (void)dwc2_readl(hsotg, EPFIFO(ep_idx));
+ (void)__raw_readl(hsotg->regs + EPFIFO(ep_idx));
return;
}
@@ -1479,13 +1477,14 @@ static void dwc2_hsotg_rx_data(struct dwc2_hsotg *hsotg, int ep_idx, int size)
hs_ep->total_data += to_read;
hs_req->req.actual += to_read;
- to_read = DIV_ROUND_UP(to_read, 4);
/*
* note, we might over-write the buffer end by 3 bytes depending on
* alignment of the data.
*/
- ioread32_rep(fifo, hs_req->req.buf + read_ptr, to_read);
+ data = hs_req->req.buf + read_ptr;
+
+ dwc2_readl_rep(hsotg, EPFIFO(ep_idx), data, to_read);
}
/**
@@ -3411,7 +3416,6 @@ static void dwc2_hsotg_dump(struct dwc2_hsotg *hsotg)
{
#ifdef DEBUG
struct device *dev = hsotg->dev;
- void __iomem *regs = hsotg->regs;
u32 val;
int idx;
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index dcd6338..8568ff4 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -567,19 +567,10 @@ u32 dwc2_calc_frame_interval(struct dwc2_hsotg *hsotg)
void dwc2_read_packet(struct dwc2_hsotg *hsotg, u8 *dest, u16 bytes)
{
u32 *data_buf = (u32 *)dest;
- int word_count = (bytes + 3) / 4;
- int i;
-
- /*
- * Todo: Account for the case where dest is not dword aligned. This
- * requires reading data from the FIFO into a u32 temp buffer, then
- * moving it into the data buffer.
- */
dev_vdbg(hsotg->dev, "%s(%p,%p,%d)\n", __func__, hsotg, dest, bytes);
- for (i = 0; i < word_count; i++, data_buf++)
- *data_buf = dwc2_readl(hsotg, HCFIFO(0));
+ dwc2_readl_rep(hsotg, HCFIFO(0), data_buf, bytes);
}
/**
@@ -1236,10 +1227,8 @@ static void dwc2_set_pid_isoc(struct dwc2_host_chan *chan)
static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
struct dwc2_host_chan *chan)
{
- u32 i;
u32 remaining_count;
u32 byte_count;
- u32 dword_count;
u32 *data_buf = (u32 *)chan->xfer_buf;
if (dbg_hc(chan))
@@ -1251,20 +1240,7 @@ static void dwc2_hc_write_packet(struct dwc2_hsotg *hsotg,
else
byte_count = remaining_count;
- dword_count = (byte_count + 3) / 4;
-
- if (((unsigned long)data_buf & 0x3) == 0) {
- /* xfer_buf is DWORD aligned */
- for (i = 0; i < dword_count; i++, data_buf++)
- dwc2_writel(hsotg, *data_buf, HCFIFO(chan->hc_num));
- } else {
- /* xfer_buf is not DWORD aligned */
- for (i = 0; i < dword_count; i++, data_buf++) {
- u32 data = data_buf[0] | data_buf[1] << 8 |
- data_buf[2] << 16 | data_buf[3] << 24;
- dwc2_writel(hsotg, data, HCFIFO(chan->hc_num));
- }
- }
+ dwc2_writel_rep(hsotg, HCFIFO(chan->hc_num), data_buf, byte_count);
chan->xfer_count += byte_count;
chan->xfer_buf += byte_count;
[toc] | [prev] | [next] | [standalone]
| From | Arnd Bergmann <arnd@arndb.de> |
|---|---|
| Date | 2016-05-18 23:10 +0200 |
| Message-ID | <rAgT8-7if-13@gated-at.bofh.it> |
| In reply to | #1403246 |
On Wednesday 18 May 2016 21:14:55 Christian Lamparter wrote:
> On Tuesday, May 17, 2016 04:50:48 PM John Youn wrote:
> > On 5/14/2016 6:11 AM, Christian Lamparter wrote:
> Hey, that's really nice of you to do that :-D. Please keep me in the
> loop (Cc) for those then.
>
> Yes, this needs definitely testing on all the affected ARCHs.
> I've attached a diff to a updated version of the patch. It
> drops the special MIPS case (as requested by Arnd).
Ok, thanks!
> BTW, I looked into the ioread32_rep and iowrite32_rep again. I'm
> not entirely convinced that the hardware FIFOs are actually endian
> neutral. But I can't verify it since my Western Digital My Book Live
> only supports the host configuration (forces host mode), so I don't
> know what a device in dual-mode or peripheral do here.
I think it's highly unlikely that designware would have screwed up
their part in such an unusual way, by intentionally adding a
byte-reversal on something that is not connected to a 32-bit
register.
Note that the reason why ioread32_rep() doesn't swap is not that
the registers are endian neutral, but that they use endianess in
the same way that the memory does: If you want to look at the first
byte of a (theoretical) four-byte USB data packet, we read four
bytes from the FIFO register using __raw_readl() (a pointer dereference)
and store it to memory using a 32-bit write:
*(u32 *)buffer = __raw_readl(FIFO);
Then we expect the first byte of the packet to be at the start:
byte0 = *(u8*)buffer;
If you replace the __raw_readl() with ioread32(), it gets byteswapped
on big-endian *CPUs*, and then written to memory without an extra
swap. This means that now you get the wrong data depending on the
kernel endianess configuration, and independent of the device endianess.
If the big-endian mode of the dwc2 block indeed contains a byteswap
on the FIFO, that would mean not having to use ioread32_be() for
the FIFO, but using
fifo_read32(void *buffer)
{
u32 data = __raw_readl(FIFO_ADDRESS);
if (big_endian_registers)
data = bswap32(data);
*(u32*)buffer = data;
}
so we byteswap the FIFO contents back, regardless of the CPU
endianess. As I said, it's unlikely that the hardware is this broken,
but not impossible.
> The reason why I think it was broken is because there's a PIO copy
> to and from the HCFIFO(x) in dwc2_hc_write_packet and
> dwc2_hc_read_packet access in the hcd.c file as well... And there,
> the code was using the dwc2_readl and dwc2_writel to access the data.
Well, we know for a fact that those functions get endianess wrong,
see dwc2_hc_write_packet:
if (((unsigned long)data_buf & 0x3) == 0) {
/* xfer_buf is DWORD aligned */
for (i = 0; i < dword_count; i++, data_buf++)
dwc2_writel(*data_buf, data_fifo);
} else {
/* xfer_buf is not DWORD aligned */
for (i = 0; i < dword_count; i++, data_buf++) {
u32 data = data_buf[0] | data_buf[1] << 8 |
data_buf[2] << 16 | data_buf[3] << 24;
dwc2_writel(data, data_fifo);
}
}
On big-endian machines, unaligned case performs a byte swap while the
aligned case does not. My best guess is that this function never
got called on either the MIPS machine that first got the fix or
your PowerPC machine.
Another possibility is that you are right that there is a byteswap
on the FIFO register in big-endian mode, and that this function
always gets unaligned buffers, so the byteswap here cancels out
the byteswap on the FIFO when both the CPU and the device are
big-endian.
> - if (((unsigned long)data_buf & 0x3) == 0) {
> - /* xfer_buf is DWORD aligned */
> - for (i = 0; i < dword_count; i++, data_buf++)
> - dwc2_writel(hsotg, *data_buf, HCFIFO(chan->hc_num));
> - } else {
> - /* xfer_buf is not DWORD aligned */
> - for (i = 0; i < dword_count; i++, data_buf++) {
> - u32 data = data_buf[0] | data_buf[1] << 8 |
> - data_buf[2] << 16 | data_buf[3] << 24;
> - dwc2_writel(hsotg, data, HCFIFO(chan->hc_num));
> - }
> - }
> + dwc2_writel_rep(hsotg, HCFIFO(chan->hc_num), data_buf, byte_count);
>
and here you are dropping the byteswap on big-endian.
Arnd
[toc] | [prev] | [next] | [standalone]
| From | John Youn <John.Youn@synopsys.com> |
|---|---|
| Date | 2016-05-19 02:40 +0200 |
| Subject | Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4 |
| Message-ID | <rAkal-Tu-9@gated-at.bofh.it> |
| In reply to | #1403246 |
On 5/18/2016 12:15 PM, Christian Lamparter wrote: > On Tuesday, May 17, 2016 04:50:48 PM John Youn wrote: >> On 5/14/2016 6:11 AM, Christian Lamparter wrote: >>> On Thursday, May 12, 2016 11:40:28 AM John Youn wrote: >>>> On 5/12/2016 6:30 AM, Christian Lamparter wrote: >>>>> On Thursday, May 12, 2016 01:55:44 PM Arnd Bergmann wrote: >>>>>> On Thursday 12 May 2016 11:58:18 Christian Lamparter wrote: >>>>>>>>>> Detecting the endianess of the >>>>>>>>>> device is probably the best future-proof solution, but it's also >>>>>>>>>> considerably more work to do in the driver, and comes with a >>>>>>>>>> tiny runtime overhead. >>>>>>>>> >>>>>>>>> The runtime overhead is probably non-measurable compared with the cost >>>>>>>>> of the actual MMIOs. >>>>>>>> >>>>>>>> Right. The code size increase is probably measurable (but still small), >>>>>>>> the runtime overhead is not. >>>>>>> >>>>>>> Ok, so no rebuts or complains have been posted. >>>>>>> >>>>>>> I've tested the patch you made in: https://lkml.org/lkml/2016/5/9/354 >>>>>>> and it works: >>>>>>> >>>>>>> Tested-by: Christian Lamparter <chunkeey@googlemail.com> >>>>>>> >>>>>>> So, how do we go from here? There is are two small issues with the >>>>>>> original patch (#ifdef DWC2_LOG_WRITES got converted to lower case: >>>>>>> #ifdef dwc2_log_writes) and I guess a proper subject would be nice. >>>>>>> >>>>>>> Arnd, can you please respin and post it (cc'd stable as well)? >>>>>>> So this is can be picked up? Or what's your plan? >>>>>> >>>>>> (I just realized my reply was stuck in my outbox, so the patch >>>>>> went out first) >>>>>> >>>>>> If I recall correctly, the rough consensus was to go with your longer >>>>>> patch in the future (fixed up for the comments that BenH and >>>>>> I sent), and I'd suggest basing it on top of a fixed version of >>>>>> my patch. >>>>> Well, but it comes with the "overhead"! So this was just as I said: >>>>> "Let's look at it and see if it's any good"... And I think it isn't >>>>> since the usb/host/ehci people also opted for #ifdef CONFIG_BIG_ENDIAN >>>>> archs etc... >>>> >>>> I slightly prefer the more general patch for future kernel versions. >>>> The overhead will probably be negligible, but we can perform some >>>> testing to make sure. >>>> >>>> Can you resubmit with all gathered feedback? >>> >>> Yes, here are the changes. >>> >>> I've tested it on my MyBook Live Duo. The usbotg comes right up: >>> [12610.540004] dwc2 4bff80000.usbotg: USB bus 1 deregistered >>> [12612.513934] dwc2 4bff80000.usbotg: Specified GNPTXFDEP=1024 > 256 >>> [12612.518756] dwc2 4bff80000.usbotg: EPs: 3, shared fifos, 2042 entries in SPRAM >>> [12612.530112] dwc2 4bff80000.usbotg: DWC OTG Controller >>> [12612.533948] dwc2 4bff80000.usbotg: new USB bus registered, assigned bus number 1 >>> [12612.540083] dwc2 4bff80000.usbotg: irq 33, io mem 0x00000000 >>> >>> John: Can you run some perf test with it? >>> >>> I've based this on: >>> >>> commit 6ea2fffc9057a67df1994d85a7c085d899eaa25a >>> Author: Arnd Bergmann <arnd@arndb.de> >>> Date: Fri May 13 15:52:27 2016 +0200 >>> >>> usb: dwc2: fix regression on big-endian PowerPC/ARM systems >>> >>> so naturally, it needs to be applied first. >>> Most of the conversion work was done by the attached >>> coccinelle semantic patches. >>> >>> I had to edit the __bic32 and __orr32 helpers by hand. >>> As well as some debugfs code and stuff in gadget.c. >>> >> >> Thanks Christian. >> >> I'll keep this in our internal tree and send it to Felipe later. This >> causes a bunch of conflicts that I have to fix up and I should do a >> bit of testing as well. >> >> And since there is a patch that fixes the regression this is can wait. >> >> Regards, >> John > --- > Hey, that's really nice of you to do that :-D. Please keep me in the > loop (Cc) for those then. Sure no problem. > > Yes, this needs definitely testing on all the affected ARCHs. > I've attached a diff to a updated version of the patch. It > drops the special MIPS case (as requested by Arnd). > > BTW, I looked into the ioread32_rep and iowrite32_rep again. I'm > not entirely convinced that the hardware FIFOs are actually endian > neutral. But I can't verify it since my Western Digital My Book Live > only supports the host configuration (forces host mode), so I don't > know what a device in dual-mode or peripheral do here. > > The reason why I think it was broken is because there's a PIO copy > to and from the HCFIFO(x) in dwc2_hc_write_packet and > dwc2_hc_read_packet access in the hcd.c file as well... And there, > the code was using the dwc2_readl and dwc2_writel to access the data. > I added special accessors for the FIFOS now: > dwc2_readl_rep and dwc2_writel_rep. > Hmmm, you could be right in that case. I'll have to check with the IP engineers and maybe try to run some tests on our platforms. So native access to the host FIFO will fail then? This platform is a BE CPU with the IP connected as LE, right? > I went all the way and implemented the helpers to do unaligned access > if necessary (not sure if adding likely branches is a good idea, as > this could be either always true or false for a specific driver the > whole time). > > NB: it also fixes a "regs variable not used in dwc2_hsotg_dump" warning > if DEBUG isn't selected. > > NB2: If it you need a patch against a specific tree, please > let me know. I can't provide you a tree to rebase on just yet. I'm hoping to get a few things queued for 4.8 and just apply this on top. It would help if you could resend these as proper patches with a commit message and signed-off-by line, and the CONFIG_MIPS removal and compile warning fix merged in. And the fifo accessors in a separate patch. That way I can do any simple fix-ups if needed. Regards, John
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web