Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1396415 > unrolled thread

Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

Started byChristian Lamparter <chunkeey@googlemail.com>
First post2016-05-08 13:50 +0200
Last post2016-05-09 23:40 +0200
Articles 17 — 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.


Contents

  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 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

#1396415 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromChristian Lamparter <chunkeey@googlemail.com>
Date2016-05-08 13:50 +0200
SubjectRe: 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]


#1396521 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromBenjamin Herrenschmidt <benh@au1.ibm.com>
Date2016-05-09 02:30 +0200
SubjectRe: 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]


#1396925

FromArnd Bergmann <arnd@arndb.de>
Date2016-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]


#1396930

FromFelipe Balbi <felipe.balbi@linux.intel.com>
Date2016-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]


#1397128

FromArnd Bergmann <arnd@arndb.de>
Date2016-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]


#1397339

FromArnd Bergmann <arnd@arndb.de>
Date2016-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]


#1397482 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromBenjamin Herrenschmidt <benh@kernel.crashing.org>
Date2016-05-10 00:40 +0200
SubjectRe: 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]


#1397760

FromArnd Bergmann <arnd@arndb.de>
Date2016-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]


#1399846

FromChristian Lamparter <chunkeey@googlemail.com>
Date2016-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]


#1399958

FromArnd Bergmann <arnd@arndb.de>
Date2016-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]


#1397490 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromBenjamin Herrenschmidt <benh@kernel.crashing.org>
Date2016-05-10 00:50 +0200
SubjectRe: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4
Message-ID<rx29Y-6uv-7@gated-at.bofh.it>
In reply to#1397128
On Mon, 2016-05-09 at 21:06 +0200, Christian Lamparter via Linuxppc-dev wrote:
> 
> 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.

No. The _rep variants always must use native endian. If for some reason
your device requires something different then the device is more broken
than I thought. IE. even with a BE core and an LE device, we use non-
byeswap _rep versions, this isn't just because we use "defaults" on
powerpc for example, it's necessary to work.

Here too, I could suggest you google for my talk on the subject :-) But
if you think closely about it, you'll figure out that FIFOs don't have
an endian per-se, thus what matters is which byte is first in ascending
address order, and that byte must land in memory in the first address
as well.

Interpreting the resulting data might require endian swaps, but
actually transferring to/from the fifo doesn't.

>    - dwc2_readl, dwc2_writel. I have no insight in the craziness that's
>           going on with MIPS and the memory barrier. But it got me thinking
>           rather than CONFIG_MIPS, isn't there a umbrella
>           "ARCH_HAS_NEED_MEMORY_BARRIER_FOR_MMIO" config symbol?
> 
>         - 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() ).

If auto-detect always work, no need to bother with the device-tree. A
single flag is enough, either is_big or is_little, doesn't matter.

"readl" should always be little, readl_be should always be big, though
the latter isn't supported on all archs. However the new accessors in
iomap.h should provide a "be" variant on all archs so switching to
these might be a good idea.

>         ( - 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 )

Or just use a temp variable, the compiler should deal with it the same
way.

Ben.
 
> Regards,
> Christian

[toc] | [prev] | [next] | [standalone]


#1397486 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromBenjamin Herrenschmidt <benh@kernel.crashing.org>
Date2016-05-10 00:40 +0200
SubjectRe: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4
Message-ID<rx20i-6qo-27@gated-at.bofh.it>
In reply to#1396930
On Mon, 2016-05-09 at 13:39 +0300, Felipe Balbi wrote:
> and patch all drivers similarly? Shouldn't arch/mips itself deal with
> it and hide it from drivers ?

Not sure what you mean, but we never had "endian neutral" accessors. It
would be a bit of an endeavour and we already have so many accessors
that adding more need a very strong justification.

Most IP blocks have a fixed endian...

Ben.

[toc] | [prev] | [next] | [standalone]


#1397081 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromBenjamin Herrenschmidt <benh@au1.ibm.com>
Date2016-05-09 16:10 +0200
SubjectRe: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4
Message-ID<rwU2K-7bS-13@gated-at.bofh.it>
In reply to#1396925
On Mon, 2016-05-09 at 12:36 +0200, Arnd Bergmann wrote:
> 
> 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.

Or use writel_be which mips seems to support...

Really, make it a BE vs. LE device test is a much better solution.

For now, since dwc2_readl() and writel don't take the device as an
argument, you can make it a function of a compile time #define, or
maybe a driver global, but the right way is really something like

	if (device_is_be())
		return readl_be(...)
	else
		return readl(...)

With the device_is_be() being temporarily set to true for MIPS for
example, and later, a second pass, add the device argument and make it
a device-flag initialized from the probe routine, possibly from the DT.

Cheers,
Ben.

> 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]


#1397358 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromJohn Youn <John.Youn@synopsys.com>
Date2016-05-09 22:30 +0200
SubjectRe: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4
Message-ID<rwZYt-4gl-1@gated-at.bofh.it>
In reply to#1396925
On 5/9/2016 3:36 AM, Arnd Bergmann wrote:
> 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.


I'm a bit confused about how this is supposed to work. My
understanding was that the readl() and writel() are defined as little
endian. So byte-swapping was performed if the architecture is big
endian. And the raw versions never swapped, always using the "native"
endianness.

dwc2 is always treating the result of readl/writel as if it was read
in native endian. So it needs to read the registers in big-endian on
big-endian systems.

This was the premise on which this patch was made.

So for big endian systems, isn't what we want is to read in big-endian
without any byteswapping to little-endian? But your saying this breaks
big-endian ARM systems as well. Am I missing something?

The rest of the feedback makes sense. Just confused about this bit.

Regards,
John

[toc] | [prev] | [next] | [standalone]


#1397374

FromArnd Bergmann <arnd@arndb.de>
Date2016-05-09 22:40 +0200
Message-ID<rx08b-4n8-7@gated-at.bofh.it>
In reply to#1397358
On Monday 09 May 2016 13:22:48 John Youn wrote:
> On 5/9/2016 3:36 AM, Arnd Bergmann wrote:
> > 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.
> 
> 
> I'm a bit confused about how this is supposed to work. My
> understanding was that the readl() and writel() are defined as little
> endian. So byte-swapping was performed if the architecture is big
> endian. And the raw versions never swapped, always using the "native"
> endianness.
> 
> dwc2 is always treating the result of readl/writel as if it was read
> in native endian. So it needs to read the registers in big-endian on
> big-endian systems.

The hardware has no idea of what endianess the CPU uses at any
given time, it's fixed by the SoC design, so there is no such
thing as "native" endianess for a random IP block.

The readl/writel accessors accomodate for that by swapping the
data on big-endian kernels, because most SoC designers tend to
pick little-endian device registers by default.

> This was the premise on which this patch was made.
> 
> So for big endian systems, isn't what we want is to read in big-endian
> without any byteswapping to little-endian? But your saying this breaks
> big-endian ARM systems as well. Am I missing something?

The systems are not a particular endianess, only the current state
of the CPU is, and that may change independent of the way the
hardware block got synthesized. We don't support swapping endianess
at runtime in Linux, but the system normally doesn't care what we
run.

The normal behavior is for the register contents to be read as
little-endian, and then swapped on big-endian kernel builds to
match what the kernel expects.

MIPS is a special case here, because the endianess of the CPU
core is fixed in hardware (or using a strapping pin) and is often
tied to the endianess of all the IP blocks. There are a couple
of other architectures like this (e.g. ARM ixp4xx, but none of the
modern ARM systems).

	Arnd

[toc] | [prev] | [next] | [standalone]


#1397403 — Re: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4

FromJohn Youn <John.Youn@synopsys.com>
Date2016-05-09 23:20 +0200
SubjectRe: usb: dwc2: regression on MyBook Live Duo / Canyonlands since 4.3.0-rc4
Message-ID<rx0KT-5bF-9@gated-at.bofh.it>
In reply to#1397374
On 5/9/2016 1:39 PM, Arnd Bergmann wrote:
> On Monday 09 May 2016 13:22:48 John Youn wrote:
>> On 5/9/2016 3:36 AM, Arnd Bergmann wrote:
>>> 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.
>>
>>
>> I'm a bit confused about how this is supposed to work. My
>> understanding was that the readl() and writel() are defined as little
>> endian. So byte-swapping was performed if the architecture is big
>> endian. And the raw versions never swapped, always using the "native"
>> endianness.
>>
>> dwc2 is always treating the result of readl/writel as if it was read
>> in native endian. So it needs to read the registers in big-endian on
>> big-endian systems.
> 
> The hardware has no idea of what endianess the CPU uses at any
> given time, it's fixed by the SoC design, so there is no such
> thing as "native" endianess for a random IP block.
> 
> The readl/writel accessors accomodate for that by swapping the
> data on big-endian kernels, because most SoC designers tend to
> pick little-endian device registers by default.
> 
>> This was the premise on which this patch was made.
>>
>> So for big endian systems, isn't what we want is to read in big-endian
>> without any byteswapping to little-endian? But your saying this breaks
>> big-endian ARM systems as well. Am I missing something?
> 
> The systems are not a particular endianess, only the current state
> of the CPU is, and that may change independent of the way the
> hardware block got synthesized. We don't support swapping endianess
> at runtime in Linux, but the system normally doesn't care what we
> run.
> 
> The normal behavior is for the register contents to be read as
> little-endian, and then swapped on big-endian kernel builds to
> match what the kernel expects.
> 
> MIPS is a special case here, because the endianess of the CPU
> core is fixed in hardware (or using a strapping pin) and is often
> tied to the endianess of all the IP blocks. There are a couple
> of other architectures like this (e.g. ARM ixp4xx, but none of the
> modern ARM systems).

Ok thanks. What you're saying is clear now.

Is there a standard way to handle this? Must all drivers either check
some endianness configuration or do a runtime check?

Regards,
John

[toc] | [prev] | [next] | [standalone]


#1397415

FromArnd Bergmann <arnd@arndb.de>
Date2016-05-09 23:40 +0200
Message-ID<rx14d-5rm-3@gated-at.bofh.it>
In reply to#1397403
On Monday 09 May 2016 14:11:23 John Youn wrote:
> On 5/9/2016 1:39 PM, Arnd Bergmann wrote:
>
> > The systems are not a particular endianess, only the current state
> > of the CPU is, and that may change independent of the way the
> > hardware block got synthesized. We don't support swapping endianess
> > at runtime in Linux, but the system normally doesn't care what we
> > run.
> > 
> > The normal behavior is for the register contents to be read as
> > little-endian, and then swapped on big-endian kernel builds to
> > match what the kernel expects.
> > 
> > MIPS is a special case here, because the endianess of the CPU
> > core is fixed in hardware (or using a strapping pin) and is often
> > tied to the endianess of all the IP blocks. There are a couple
> > of other architectures like this (e.g. ARM ixp4xx, but none of the
> > modern ARM systems).
> 
> Ok thanks. What you're saying is clear now.
> 
> Is there a standard way to handle this? Must all drivers either check
> some endianness configuration or do a runtime check?

There are four common approaches:

1 hardcode a particular endianess because an IP block is always
  used the same way

2 pick the right endianess at compile-time because we know
  what we are building for (typically by CPU architecture, but
  there are some other ways)

3 do runtime configuration based on a DT property or platform data

4 do automatic runtime configuration based on well-known register
  contents

Approach 1 is the most common, in particular as most IP blocks
are not configurable and are not used on big-endian MIPS machines.

Approach 4 as implemented by Christian Lamparter's patch is the
most reliable way, and probably makes most sense for DesignWare
IP blocks in general, because they are configurable and may
get used in all kinds of systems.

Approaches 2 and 3 are somewhat inferior because you have to
rely on everyone else doing it the way you planned, but 2
is particularly easy and 3 is used when there is no obvious
way to detect endianess of the device.

The patch I suggested would be approach 2, and as Felipe correctly
mentioned, it is not ideal, but it may be more appropriate for
backports to the 4.4-longterm, 4.5-stable and 4.6-stable kernels
than the more elaborate patch we are now discussing.

	Arnd

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web