* [PATCH] powerpc: ARCH_PFN_OFFSET should be unsigned long
From: Scott Wood @ 2011-03-24 21:51 UTC (permalink / raw)
To: benh; +Cc: linuxppc-dev
pfns are unsigned long, but MEMORY_START is phys_addr_t. This leads
to page_to_pfn() returning phys_addr_t, and thus type mismatches in a few
print statements.
Signed-off-by: Scott Wood <scottwood@freescale.com>
---
arch/powerpc/include/asm/page.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/include/asm/page.h b/arch/powerpc/include/asm/page.h
index da4b200..2cd664e 100644
--- a/arch/powerpc/include/asm/page.h
+++ b/arch/powerpc/include/asm/page.h
@@ -100,7 +100,7 @@ extern phys_addr_t kernstart_addr;
#endif
#ifdef CONFIG_FLATMEM
-#define ARCH_PFN_OFFSET (MEMORY_START >> PAGE_SHIFT)
+#define ARCH_PFN_OFFSET ((unsigned long)(MEMORY_START >> PAGE_SHIFT))
#define pfn_valid(pfn) ((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
#endif
--
1.7.1
^ permalink raw reply related
* [BUG] pgprot_noncached() is -NOT- safe for mapping vmalloc buffers into userspace
From: Benjamin Herrenschmidt @ 2011-03-24 22:16 UTC (permalink / raw)
To: tiwai; +Cc: linux-arch, linuxppc-dev, linux-kernel@vger.kernel.org,
Matthew Evans
Hi Takashi !
While working on endian-fixing xHCI with Matt (CC), we discovered the
source of our problems with usb-audio on a board we were working on.
c32d977b8157bf67cdf47729ce7dd054a26eb534
"ALSA: pcm - Call pgprot_noncached() for vmalloc'ed buffers"
I'm afraid that this is totally bogus :-)
I don't know on what arch it is safe to have the same memory be mapped
cachable in the kernel (and accessed via this cached mapping) and
non-cachable in userspace, but I can confidently say that wherever it
works it does so by accident.
In the case of usb-audio, what we observed is that the user application
was writing samples using an uncached mapping, so directly to memory,
which does -not- invalidate conflicting cache lines on the way, an the
kernel would then memcpy those data to the USB buffers using a cached
mapping (vmalloc) and essentially get stale stuff from the cache instead
of the real samples.
Worse, on some processors, it's actually -illegal- to create (and even
more to -access-) a conflicting mapping of a page of memory, ie, have it
mapped cached somewhere and uncached somewhere else. It will lockup some
processors and afaik, some x86 as well.
In fact, cache coherent architectures often don't support mapping memory
uncached -at-all- so something like snd_pcm_lib_mmap_noncached()
shouldn't exist, or at least be under arch control. There's no case
where it's "always safe". There will almost always be a cache alias in
the linear mapping unless special arch specific sauce has been applied.
Now, there's another problem on top of that, which is that
snd_pcm_default_mmap() will not work properly the "other way around" on
powerpc, where the mapping -needs- to be uncached bcs you are running on
a non cache coherent embedded CPU and trying to mmap DMA memory, but
that's something that needs fixing inside powerpc by properly defining
dma_mmap_coherent() & ARCH_HAS_DMA_MMAP_COHERENT (I thought we had added
it a while back but it's not upstream, patch must have got lost). We
must also make sure we don't go down that path for vmalloc memory
though.
Cheers,
Ben.
^ permalink raw reply
* Re: Query: PCIe range entry at pcie@0 in dts files
From: Kumar Gala @ 2011-03-25 4:20 UTC (permalink / raw)
To: Kushwaha Prabhakar-B32579; +Cc: linuxppc-dev@lists.ozlabs.org
In-Reply-To: <071A08F2C6A57E4E94D980ECA553F874154CD3@039-SN1MPN1-004.039d.mgd.msft.net>
On Mar 23, 2011, at 10:20 PM, Kushwaha Prabhakar-B32579 wrote:
>=20
> Hi all,
>=20
> I have query about usage of range field at pcie@0 under PCIe =
controller. Please find snap shot from mpc8536_36.dts..
>=20
> pci3: pcie@fffe0b000 {
> compatible =3D "fsl,mpc8548-pcie";
> device_type =3D "pci";
> #interrupt-cells =3D <1>;
> #size-cells =3D <2>;
> #address-cells =3D <3>;
> reg =3D <0xf 0xffe0b000 0 0x1000>;
> bus-range =3D <0 0xff>;
> ranges =3D <0x02000000 0 0xe0000000 0xc 0x20000000 0 =
0x20000000
> 0x01000000 0 0x00000000 0xf 0xffc30000 0 =
0x00010000>;
> clock-frequency =3D <33333333>;
> interrupt-parent =3D <&mpic>;
> interrupts =3D <27 0x2>;
> interrupt-map-mask =3D <0xf800 0 0 7>;
> interrupt-map =3D <
> /* IDSEL 0x0 */
> 0000 0 0 1 &mpic 8 1
> 0000 0 0 2 &mpic 9 1
> 0000 0 0 3 &mpic 10 1
> 0000 0 0 4 &mpic 11 1
> >;
>=20
> pcie@0 {
> reg =3D <0 0 0 0 0>;
> #size-cells =3D <2>;
> #address-cells =3D <3>;
> device_type =3D "pci";
> ranges =3D <0x02000000 0 0xe0000000 --> =
child/port start address
> 0x02000000 0 0xe0000000 --> Parent bus =
address
> 0 0x20000000
>=20
> 0x01000000 0 0x00000000
> 0x01000000 0 0x00000000
> 0 0x00100000>;
> };
> };
>=20
> Question:
> A) is ranges filed of pcie@0 really required?
> I just went through the code and found scan_OF_for_pci_dev() =
called from pci_busdev_to_OF_node() touches pcie@0 node. But, It does =
not even uses range filed.=20
>=20
> static struct device_node *scan_OF_for_pci_dev(struct =
device_node *parent,unsigned int devfn) {
> ---
> ---
> for_each_child_of_node(parent, np) {
> reg =3D of_get_property(np, "reg", &psize);=20
>=20
> ---
> ---
> if (!strcmp(np->name, "multifunc-device")) {=20
> =20
> }
>=20
> I also checked "Power_ePAPR_APPROVED_v1.0.pdf". It never say range =
filed required for child bus.
Part of the reason for the range is to match PCIe semantics of RC having =
a transparent bridge.
>=20
> B) if range field of pcie@0 required. why does child/port start =
address same as Parent bus address? Range property provides mapping of =
port address to parent address space.
> So the value should be 0x00000000. Means port's address starting from =
0x00000000 to size 0x20000000 is mapped parent's 0xe0000000.
>=20
> ranges =3D <0x02000000 0 0x00000000 --> =
Child/port's start address
> 0x02000000 0 0xe0000000 --> Parent =
bus address
> 0 0x20000000
>=20
> 0x01000000 0 0x00000000
> 0x01000000 0 0x00000000
> 0 0x00100000>;
because the bridge is transparent.
- k=
^ permalink raw reply
* [PATCH] powerpc/dts:Update PCIe memory maps to match u-boot of Px020RDB
From: Prabhakar Kushwaha @ 2011-03-25 4:47 UTC (permalink / raw)
To: linuxppc-dev; +Cc: meet2prabhu, Prabhakar Kushwaha
PCIe memory address space is 1:1 mapped with u-boot.
Update dts of Px020RDB i.e. P1020RDB and P2020RDB to match the address map
changes in u-boot.
Signed-off-by: Prabhakar Kushwaha <prabhakar@freescale.com>
Acked-by: Kumar Gala <kumar.gala@freescale.com>
---
Based upon git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6.git (Branch master)
arch/powerpc/boot/dts/p1020rdb.dts | 12 ++++++------
arch/powerpc/boot/dts/p2020rdb.dts | 12 ++++++------
arch/powerpc/boot/dts/p2020rdb_camp_core0.dts | 4 ++--
arch/powerpc/boot/dts/p2020rdb_camp_core1.dts | 10 +++++-----
4 files changed, 19 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/boot/dts/p1020rdb.dts b/arch/powerpc/boot/dts/p1020rdb.dts
index 22f64b6..e0668f8 100644
--- a/arch/powerpc/boot/dts/p1020rdb.dts
+++ b/arch/powerpc/boot/dts/p1020rdb.dts
@@ -1,7 +1,7 @@
/*
* P1020 RDB Device Tree Source
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -553,7 +553,7 @@
reg = <0 0xffe09000 0 0x1000>;
bus-range = <0 255>;
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
- 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <16 2>;
@@ -580,8 +580,8 @@
#address-cells = <3>;
reg = <0 0xffe0a000 0 0x1000>;
bus-range = <0 255>;
- ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
- 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <16 2>;
@@ -590,8 +590,8 @@
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
- ranges = <0x2000000 0x0 0xc0000000
- 0x2000000 0x0 0xc0000000
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
diff --git a/arch/powerpc/boot/dts/p2020rdb.dts b/arch/powerpc/boot/dts/p2020rdb.dts
index da4cb0d..e2d48fd 100644
--- a/arch/powerpc/boot/dts/p2020rdb.dts
+++ b/arch/powerpc/boot/dts/p2020rdb.dts
@@ -1,7 +1,7 @@
/*
* P2020 RDB Device Tree Source
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -537,7 +537,7 @@
reg = <0 0xffe09000 0 0x1000>;
bus-range = <0 255>;
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
- 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <25 2>;
@@ -564,8 +564,8 @@
#address-cells = <3>;
reg = <0 0xffe0a000 0 0x1000>;
bus-range = <0 255>;
- ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
- 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <26 2>;
@@ -574,8 +574,8 @@
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
- ranges = <0x2000000 0x0 0xc0000000
- 0x2000000 0x0 0xc0000000
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
index 0fe93d0..b69c3a5 100644
--- a/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
+++ b/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
@@ -6,7 +6,7 @@
* This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb,
* eth1, eth2, sdhc, crypto, global-util, pci0.
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -342,7 +342,7 @@
reg = <0 0xffe09000 0 0x1000>;
bus-range = <0 255>;
ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
- 0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
+ 0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <25 2>;
diff --git a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
index e95a512..7a31d46c 100644
--- a/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
+++ b/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
@@ -7,7 +7,7 @@
*
* Please note to add "-b 1" for core1's dts compiling.
*
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 Freescale Semiconductor Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -162,8 +162,8 @@
#address-cells = <3>;
reg = <0 0xffe0a000 0 0x1000>;
bus-range = <0 255>;
- ranges = <0x2000000 0x0 0xc0000000 0 0xc0000000 0x0 0x20000000
- 0x1000000 0x0 0x00000000 0 0xffc20000 0x0 0x10000>;
+ ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+ 0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
clock-frequency = <33333333>;
interrupt-parent = <&mpic>;
interrupts = <26 2>;
@@ -172,8 +172,8 @@
#size-cells = <2>;
#address-cells = <3>;
device_type = "pci";
- ranges = <0x2000000 0x0 0xc0000000
- 0x2000000 0x0 0xc0000000
+ ranges = <0x2000000 0x0 0x80000000
+ 0x2000000 0x0 0x80000000
0x0 0x20000000
0x1000000 0x0 0x0
--
1.7.3
^ permalink raw reply related
* [PATCH] powerpc: Implement dma_mmap_coherent()
From: Benjamin Herrenschmidt @ 2011-03-25 6:50 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Takashi Iwai
This is used by Alsa to mmap buffers allocated with dma_alloc_coherent()
into userspace. We need a special variant to handle machines with
non-coherent DMAs as those buffers have "special" virt addresses and
require non-cachable mappings
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Dunno if anybody with CONFIG_NOT_COHERENT_CACHE has some audio device
that uses dma buffers (ie not usb-audio) and wants to try that out...
should fix a long standing problem.
arch/powerpc/include/asm/dma-mapping.h | 7 +++++++
arch/powerpc/kernel/dma.c | 18 ++++++++++++++++++
arch/powerpc/mm/dma-noncoherent.c | 20 ++++++++++++++++++++
3 files changed, 45 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 6d2416a..41e0eb7 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -42,6 +42,7 @@ extern void __dma_free_coherent(size_t size, void *vaddr);
extern void __dma_sync(void *vaddr, size_t size, int direction);
extern void __dma_sync_page(struct page *page, unsigned long offset,
size_t size, int direction);
+extern unsigned long __dma_get_coherent_pfn(void *cpu_addr);
#else /* ! CONFIG_NOT_COHERENT_CACHE */
/*
@@ -52,6 +53,7 @@ extern void __dma_sync_page(struct page *page, unsigned long offset,
#define __dma_free_coherent(size, addr) ((void)0)
#define __dma_sync(addr, size, rw) ((void)0)
#define __dma_sync_page(pg, off, sz, rw) ((void)0)
+#define __dma_get_coherent_pfn(cpu_addr) (0)
#endif /* ! CONFIG_NOT_COHERENT_CACHE */
@@ -198,6 +200,11 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
#define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
+extern int dma_mmap_coherent(struct device *, struct vm_area_struct *,
+ void *, dma_addr_t, size_t);
+#define ARCH_HAS_DMA_MMAP_COHERENT
+
+
static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction direction)
{
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index cf02cad..0f52235 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -179,3 +179,21 @@ static int __init dma_init(void)
return 0;
}
fs_initcall(dma_init);
+
+int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
+ void *cpu_addr, dma_addr_t handle, size_t size)
+{
+ unsigned long pfn;
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+ vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+ pfn = __dma_get_coherent_pfn(cpu_addr);
+#else
+ pfn = page_to_pfn(virt_to_page(cpu_addr));
+#endif
+ return remap_pfn_range(vma, vma->vm_start,
+ pfn + vma->vm_pgoff,
+ vma->vm_end - vma->vm_start,
+ vma->vm_page_prot);
+}
+
diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c
index 757c0be..174b10a 100644
--- a/arch/powerpc/mm/dma-noncoherent.c
+++ b/arch/powerpc/mm/dma-noncoherent.c
@@ -399,3 +399,23 @@ void __dma_sync_page(struct page *page, unsigned long offset,
#endif
}
EXPORT_SYMBOL(__dma_sync_page);
+
+/*
+ * Return the PFN for a given cpu virtual address returned by
+ * __dma_alloc_coherent. This is used by dma_mmap_coherent()
+ */
+unsigned long __dma_get_coherent_pfn(void *cpu_addr)
+{
+ /* This should always be populated, so we don't test every
+ * level. If that fails, we'll have a nice crash which
+ * will be as good as a BUG_ON()
+ */
+ pgd_t *pgd = pgd_offset_k(cpu_addr);
+ pud_t *pud = pud_offset(pgd, cpu_addr);
+ pmd_t *pmd = pmd_offset(pud, cpu_addr);
+ pte_t *ptep = pte_offset_kernel(pmd, cpu_addr);
+
+ if (pte_none(*ptep) || !pte_present(*ptep))
+ return 0;
+ return pte_pfn(*ptep);
+}
^ permalink raw reply related
* ALSA: vmalloc buffers should use normal mmap
From: Benjamin Herrenschmidt @ 2011-03-25 6:51 UTC (permalink / raw)
To: Takashi Iwai; +Cc: linuxppc-dev, linux-kernel@vger.kernel.org
It's a big no-no to use pgprot_noncached() when mmap'ing such buffers
into userspace since they are mapped cachable in kernel space.
This can cause all sort of interesting things ranging from to garbled
sound to lockups on various architectures. I've observed that usb-audio
is broken on powerpc 4xx for example because of that.
Also remove the now unused snd_pcm_lib_mmap_noncached(). It's
an arch business to know when to use uncached mappings, there's
already hacks for MIPS inside snd_pcm_default_mmap() and other
archs are supposed to use dma_mmap_coherent().
(See my separate patch that adds dma_mmap_coherent() to powerpc)
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CC: Takashi Iwai <tiwai@suse.de>
---
include/sound/pcm.h | 4 +---
sound/core/pcm_native.c | 9 ---------
2 files changed, 1 insertions(+), 12 deletions(-)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 430a9cc..e1bad11 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -1031,9 +1031,7 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s
#define snd_pcm_lib_mmap_iomem NULL
#endif
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
- struct vm_area_struct *area);
-#define snd_pcm_lib_mmap_vmalloc snd_pcm_lib_mmap_noncached
+#define snd_pcm_lib_mmap_vmalloc NULL
static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
{
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 2d99c37..7639407 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3194,15 +3194,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
#endif /* SNDRV_PCM_INFO_MMAP */
-/* mmap callback with pgprot_noncached */
-int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
-{
- area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
- return snd_pcm_default_mmap(substream, area);
-}
-EXPORT_SYMBOL(snd_pcm_lib_mmap_noncached);
-
/*
* mmap DMA buffer
*/
^ permalink raw reply related
* [PATCH 0/5] Make xHCI driver endian-safe, add a barrier, some debug
From: Matt Evans @ 2011-03-25 7:43 UTC (permalink / raw)
To: sarah.a.sharp; +Cc: linuxppc-dev, linux-usb
Hi Sarah,
This series addresses the endian issues with the xHCI driver, and has brought
lovely USB 3 to PPC. :-) I've tested various types of traffic on ppc4xx and
POWER7 and (some sound driver bugs notwithstanding) all seems fine. Also
addresses an ordering problem we found and the recursive nature of the event
handling, plus the addition of some debug.
This should apply to 2.6.38/Linus' tree.
Thanks!
Matt
^ permalink raw reply
* [PATCH 1/5] xhci: Make xHCI driver endian-safe
From: Matt Evans @ 2011-03-25 7:43 UTC (permalink / raw)
To: sarah.a.sharp; +Cc: linuxppc-dev, linux-usb
This patch changes the struct members defining access to xHCI device-visible
memory to use __le32/__le64 where appropriate, and then adds swaps where
required. Checked with sparse that all accesses are correct.
MMIO accesses use readl/writel so already are performed LE, but prototypes
now reflect this with __le*.
There were a couple of (debug) instances of DMA pointers being truncated to
32bits which have been fixed too.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
drivers/usb/host/xhci-dbg.c | 51 ++++----
drivers/usb/host/xhci-hub.c | 18 ++--
drivers/usb/host/xhci-mem.c | 122 ++++++++++----------
drivers/usb/host/xhci-ring.c | 269 ++++++++++++++++++++++--------------------
drivers/usb/host/xhci.c | 118 ++++++++++--------
drivers/usb/host/xhci.h | 134 +++++++++++-----------
6 files changed, 371 insertions(+), 341 deletions(-)
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 0231814..2e04861 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -147,7 +147,7 @@ static void xhci_print_op_regs(struct xhci_hcd *xhci)
static void xhci_print_ports(struct xhci_hcd *xhci)
{
- u32 __iomem *addr;
+ __le32 __iomem *addr;
int i, j;
int ports;
char *names[NUM_PORT_REGS] = {
@@ -253,27 +253,27 @@ void xhci_print_trb_offsets(struct xhci_hcd *xhci, union xhci_trb *trb)
void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
{
u64 address;
- u32 type = xhci_readl(xhci, &trb->link.control) & TRB_TYPE_BITMASK;
+ u32 type = le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK;
switch (type) {
case TRB_TYPE(TRB_LINK):
xhci_dbg(xhci, "Link TRB:\n");
xhci_print_trb_offsets(xhci, trb);
- address = trb->link.segment_ptr;
+ address = le64_to_cpu(trb->link.segment_ptr);
xhci_dbg(xhci, "Next ring segment DMA address = 0x%llx\n", address);
xhci_dbg(xhci, "Interrupter target = 0x%x\n",
- GET_INTR_TARGET(trb->link.intr_target));
+ GET_INTR_TARGET(le32_to_cpu(trb->link.intr_target)));
xhci_dbg(xhci, "Cycle bit = %u\n",
- (unsigned int) (trb->link.control & TRB_CYCLE));
+ (unsigned int) (le32_to_cpu(trb->link.control) & TRB_CYCLE));
xhci_dbg(xhci, "Toggle cycle bit = %u\n",
- (unsigned int) (trb->link.control & LINK_TOGGLE));
+ (unsigned int) (le32_to_cpu(trb->link.control) & LINK_TOGGLE));
xhci_dbg(xhci, "No Snoop bit = %u\n",
- (unsigned int) (trb->link.control & TRB_NO_SNOOP));
+ (unsigned int) (le32_to_cpu(trb->link.control) & TRB_NO_SNOOP));
break;
case TRB_TYPE(TRB_TRANSFER):
- address = trb->trans_event.buffer;
+ address = le64_to_cpu(trb->trans_event.buffer);
/*
* FIXME: look at flags to figure out if it's an address or if
* the data is directly in the buffer field.
@@ -281,11 +281,12 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
break;
case TRB_TYPE(TRB_COMPLETION):
- address = trb->event_cmd.cmd_trb;
+ address = le64_to_cpu(trb->event_cmd.cmd_trb);
xhci_dbg(xhci, "Command TRB pointer = %llu\n", address);
xhci_dbg(xhci, "Completion status = %u\n",
- (unsigned int) GET_COMP_CODE(trb->event_cmd.status));
- xhci_dbg(xhci, "Flags = 0x%x\n", (unsigned int) trb->event_cmd.flags);
+ (unsigned int) GET_COMP_CODE(le32_to_cpu(trb->event_cmd.status)));
+ xhci_dbg(xhci, "Flags = 0x%x\n",
+ (unsigned int) le32_to_cpu(trb->event_cmd.flags));
break;
default:
xhci_dbg(xhci, "Unknown TRB with TRB type ID %u\n",
@@ -311,16 +312,16 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
void xhci_debug_segment(struct xhci_hcd *xhci, struct xhci_segment *seg)
{
int i;
- u32 addr = (u32) seg->dma;
+ u64 addr = seg->dma;
union xhci_trb *trb = seg->trbs;
for (i = 0; i < TRBS_PER_SEGMENT; ++i) {
trb = &seg->trbs[i];
- xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n", addr,
- lower_32_bits(trb->link.segment_ptr),
- upper_32_bits(trb->link.segment_ptr),
- (unsigned int) trb->link.intr_target,
- (unsigned int) trb->link.control);
+ xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n", addr,
+ (u32)lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
+ (u32)upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
+ (unsigned int) le32_to_cpu(trb->link.intr_target),
+ (unsigned int) le32_to_cpu(trb->link.control));
addr += sizeof(*trb);
}
}
@@ -391,18 +392,18 @@ void xhci_dbg_ep_rings(struct xhci_hcd *xhci,
void xhci_dbg_erst(struct xhci_hcd *xhci, struct xhci_erst *erst)
{
- u32 addr = (u32) erst->erst_dma_addr;
+ u64 addr = erst->erst_dma_addr;
int i;
struct xhci_erst_entry *entry;
for (i = 0; i < erst->num_entries; ++i) {
entry = &erst->entries[i];
- xhci_dbg(xhci, "@%08x %08x %08x %08x %08x\n",
- (unsigned int) addr,
- lower_32_bits(entry->seg_addr),
- upper_32_bits(entry->seg_addr),
- (unsigned int) entry->seg_size,
- (unsigned int) entry->rsvd);
+ xhci_dbg(xhci, "@%016llx %08x %08x %08x %08x\n",
+ addr,
+ lower_32_bits(le64_to_cpu(entry->seg_addr)),
+ upper_32_bits(le64_to_cpu(entry->seg_addr)),
+ (unsigned int) le32_to_cpu(entry->seg_size),
+ (unsigned int) le32_to_cpu(entry->rsvd));
addr += sizeof(*entry);
}
}
@@ -436,7 +437,7 @@ char *xhci_get_slot_state(struct xhci_hcd *xhci,
{
struct xhci_slot_ctx *slot_ctx = xhci_get_slot_ctx(xhci, ctx);
- switch (GET_SLOT_STATE(slot_ctx->dev_state)) {
+ switch (GET_SLOT_STATE(le32_to_cpu(slot_ctx->dev_state))) {
case 0:
return "enabled/disabled";
case 1:
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index a78f2eb..ae1d24c 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -50,7 +50,7 @@ static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
temp |= 0x0008;
/* Bits 6:5 - no TTs in root ports */
/* Bit 7 - no port indicators */
- desc->wHubCharacteristics = (__force __u16) cpu_to_le16(temp);
+ desc->wHubCharacteristics = cpu_to_le16(temp);
}
/* Fill in the USB 2.0 roothub descriptor */
@@ -314,7 +314,7 @@ void xhci_ring_device(struct xhci_hcd *xhci, int slot_id)
}
static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
- u16 wIndex, u32 __iomem *addr, u32 port_status)
+ u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
/* Don't allow the USB core to disable SuperSpeed ports. */
if (hcd->speed == HCD_USB3) {
@@ -331,7 +331,7 @@ static void xhci_disable_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
}
static void xhci_clear_port_change_bit(struct xhci_hcd *xhci, u16 wValue,
- u16 wIndex, u32 __iomem *addr, u32 port_status)
+ u16 wIndex, __le32 __iomem *addr, u32 port_status)
{
char *port_change_bit;
u32 status;
@@ -376,7 +376,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
unsigned long flags;
u32 temp, temp1, status;
int retval = 0;
- u32 __iomem **port_array;
+ __le32 __iomem **port_array;
int slot_id;
struct xhci_bus_state *bus_state;
@@ -664,7 +664,7 @@ int xhci_hub_status_data(struct usb_hcd *hcd, char *buf)
int i, retval;
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int ports;
- u32 __iomem **port_array;
+ __le32 __iomem **port_array;
struct xhci_bus_state *bus_state;
if (hcd->speed == HCD_USB3) {
@@ -709,7 +709,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int max_ports, port_index;
- u32 __iomem **port_array;
+ __le32 __iomem **port_array;
struct xhci_bus_state *bus_state;
unsigned long flags;
@@ -779,7 +779,7 @@ int xhci_bus_suspend(struct usb_hcd *hcd)
if (DEV_HIGHSPEED(t1)) {
/* enable remote wake up for USB 2.0 */
- u32 __iomem *addr;
+ __le32 __iomem *addr;
u32 tmp;
/* Add one to the port status register address to get
@@ -801,7 +801,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
{
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
int max_ports, port_index;
- u32 __iomem **port_array;
+ __le32 __iomem **port_array;
struct xhci_bus_state *bus_state;
u32 temp;
unsigned long flags;
@@ -875,7 +875,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
if (DEV_HIGHSPEED(temp)) {
/* disable remote wake up for USB 2.0 */
- u32 __iomem *addr;
+ __le32 __iomem *addr;
u32 tmp;
/* Add one to the port status register address to get
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index a003e79..e3a219d 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -89,16 +89,17 @@ static void xhci_link_segments(struct xhci_hcd *xhci, struct xhci_segment *prev,
return;
prev->next = next;
if (link_trbs) {
- prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr = next->dma;
+ prev->trbs[TRBS_PER_SEGMENT-1].link.
+ segment_ptr = cpu_to_le64(next->dma);
/* Set the last TRB in the segment to have a TRB type ID of Link TRB */
- val = prev->trbs[TRBS_PER_SEGMENT-1].link.control;
+ val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
val &= ~TRB_TYPE_BITMASK;
val |= TRB_TYPE(TRB_LINK);
/* Always set the chain bit with 0.95 hardware */
if (xhci_link_trb_quirk(xhci))
val |= TRB_CHAIN;
- prev->trbs[TRBS_PER_SEGMENT-1].link.control = val;
+ prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
}
xhci_dbg(xhci, "Linking segment 0x%llx to segment 0x%llx (DMA)\n",
(unsigned long long)prev->dma,
@@ -186,7 +187,8 @@ static struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
if (link_trbs) {
/* See section 4.9.2.1 and 6.4.4.1 */
- prev->trbs[TRBS_PER_SEGMENT-1].link.control |= (LINK_TOGGLE);
+ prev->trbs[TRBS_PER_SEGMENT-1].link.
+ control |= cpu_to_le32(LINK_TOGGLE);
xhci_dbg(xhci, "Wrote link toggle flag to"
" segment %p (virtual), 0x%llx (DMA)\n",
prev, (unsigned long long)prev->dma);
@@ -548,7 +550,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
addr = cur_ring->first_seg->dma |
SCT_FOR_CTX(SCT_PRI_TR) |
cur_ring->cycle_state;
- stream_info->stream_ctx_array[cur_stream].stream_ring = addr;
+ stream_info->stream_ctx_array[cur_stream].
+ stream_ring = cpu_to_le64(addr);
xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n",
cur_stream, (unsigned long long) addr);
@@ -614,10 +617,10 @@ void xhci_setup_streams_ep_input_ctx(struct xhci_hcd *xhci,
max_primary_streams = fls(stream_info->num_stream_ctxs) - 2;
xhci_dbg(xhci, "Setting number of stream ctx array entries to %u\n",
1 << (max_primary_streams + 1));
- ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK;
- ep_ctx->ep_info |= EP_MAXPSTREAMS(max_primary_streams);
- ep_ctx->ep_info |= EP_HAS_LSA;
- ep_ctx->deq = stream_info->ctx_array_dma;
+ ep_ctx->ep_info &= cpu_to_le32(~EP_MAXPSTREAMS_MASK);
+ ep_ctx->ep_info |= cpu_to_le32(EP_MAXPSTREAMS(max_primary_streams)
+ | EP_HAS_LSA);
+ ep_ctx->deq = cpu_to_le64(stream_info->ctx_array_dma);
}
/*
@@ -630,10 +633,9 @@ void xhci_setup_no_streams_ep_input_ctx(struct xhci_hcd *xhci,
struct xhci_virt_ep *ep)
{
dma_addr_t addr;
- ep_ctx->ep_info &= ~EP_MAXPSTREAMS_MASK;
- ep_ctx->ep_info &= ~EP_HAS_LSA;
+ ep_ctx->ep_info &= cpu_to_le32(~(EP_MAXPSTREAMS_MASK | EP_HAS_LSA));
addr = xhci_trb_virt_to_dma(ep->ring->deq_seg, ep->ring->dequeue);
- ep_ctx->deq = addr | ep->ring->cycle_state;
+ ep_ctx->deq = cpu_to_le64(addr | ep->ring->cycle_state);
}
/* Frees all stream contexts associated with the endpoint,
@@ -781,11 +783,11 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
dev->udev = udev;
/* Point to output device context in dcbaa. */
- xhci->dcbaa->dev_context_ptrs[slot_id] = dev->out_ctx->dma;
+ xhci->dcbaa->dev_context_ptrs[slot_id] = cpu_to_le64(dev->out_ctx->dma);
xhci_dbg(xhci, "Set slot id %d dcbaa entry %p to 0x%llx\n",
- slot_id,
- &xhci->dcbaa->dev_context_ptrs[slot_id],
- (unsigned long long) xhci->dcbaa->dev_context_ptrs[slot_id]);
+ slot_id,
+ &xhci->dcbaa->dev_context_ptrs[slot_id],
+ (unsigned long long) le64_to_cpu(xhci->dcbaa->dev_context_ptrs[slot_id]));
return 1;
fail:
@@ -810,8 +812,9 @@ void xhci_copy_ep0_dequeue_into_input_ctx(struct xhci_hcd *xhci,
* configured device has reset, so all control transfers should have
* been completed or cancelled before the reset.
*/
- ep0_ctx->deq = xhci_trb_virt_to_dma(ep_ring->enq_seg, ep_ring->enqueue);
- ep0_ctx->deq |= ep_ring->cycle_state;
+ ep0_ctx->deq = cpu_to_le64(xhci_trb_virt_to_dma(ep_ring->enq_seg,
+ ep_ring->enqueue)
+ | ep_ring->cycle_state);
}
/*
@@ -885,24 +888,22 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
slot_ctx = xhci_get_slot_ctx(xhci, dev->in_ctx);
/* 2) New slot context and endpoint 0 context are valid*/
- ctrl_ctx->add_flags = SLOT_FLAG | EP0_FLAG;
+ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG | EP0_FLAG);
/* 3) Only the control endpoint is valid - one endpoint context */
- slot_ctx->dev_info |= LAST_CTX(1);
-
- slot_ctx->dev_info |= (u32) udev->route;
+ slot_ctx->dev_info |= cpu_to_le32(LAST_CTX(1) | (u32) udev->route);
switch (udev->speed) {
case USB_SPEED_SUPER:
- slot_ctx->dev_info |= (u32) SLOT_SPEED_SS;
+ slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_SS);
break;
case USB_SPEED_HIGH:
- slot_ctx->dev_info |= (u32) SLOT_SPEED_HS;
+ slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_HS);
break;
case USB_SPEED_FULL:
- slot_ctx->dev_info |= (u32) SLOT_SPEED_FS;
+ slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_FS);
break;
case USB_SPEED_LOW:
- slot_ctx->dev_info |= (u32) SLOT_SPEED_LS;
+ slot_ctx->dev_info |= cpu_to_le32((u32) SLOT_SPEED_LS);
break;
case USB_SPEED_WIRELESS:
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
@@ -916,7 +917,7 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
port_num = xhci_find_real_port_number(xhci, udev);
if (!port_num)
return -EINVAL;
- slot_ctx->dev_info2 |= (u32) ROOT_HUB_PORT(port_num);
+ slot_ctx->dev_info2 |= cpu_to_le32((u32) ROOT_HUB_PORT(port_num));
/* Set the port number in the virtual_device to the faked port number */
for (top_dev = udev; top_dev->parent && top_dev->parent->parent;
top_dev = top_dev->parent)
@@ -927,31 +928,31 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
/* Is this a LS/FS device under an external HS hub? */
if (udev->tt && udev->tt->hub->parent) {
- slot_ctx->tt_info = udev->tt->hub->slot_id;
- slot_ctx->tt_info |= udev->ttport << 8;
+ slot_ctx->tt_info = cpu_to_le32(udev->tt->hub->slot_id |
+ (udev->ttport << 8));
if (udev->tt->multi)
- slot_ctx->dev_info |= DEV_MTT;
+ slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
}
xhci_dbg(xhci, "udev->tt = %p\n", udev->tt);
xhci_dbg(xhci, "udev->ttport = 0x%x\n", udev->ttport);
/* Step 4 - ring already allocated */
/* Step 5 */
- ep0_ctx->ep_info2 = EP_TYPE(CTRL_EP);
+ ep0_ctx->ep_info2 = cpu_to_le32(EP_TYPE(CTRL_EP));
/*
* XXX: Not sure about wireless USB devices.
*/
switch (udev->speed) {
case USB_SPEED_SUPER:
- ep0_ctx->ep_info2 |= MAX_PACKET(512);
+ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(512));
break;
case USB_SPEED_HIGH:
/* USB core guesses at a 64-byte max packet first for FS devices */
case USB_SPEED_FULL:
- ep0_ctx->ep_info2 |= MAX_PACKET(64);
+ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(64));
break;
case USB_SPEED_LOW:
- ep0_ctx->ep_info2 |= MAX_PACKET(8);
+ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(8));
break;
case USB_SPEED_WIRELESS:
xhci_dbg(xhci, "FIXME xHCI doesn't support wireless speeds\n");
@@ -962,12 +963,10 @@ int xhci_setup_addressable_virt_dev(struct xhci_hcd *xhci, struct usb_device *ud
BUG();
}
/* EP 0 can handle "burst" sizes of 1, so Max Burst Size field is 0 */
- ep0_ctx->ep_info2 |= MAX_BURST(0);
- ep0_ctx->ep_info2 |= ERROR_COUNT(3);
+ ep0_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(0) | ERROR_COUNT(3));
- ep0_ctx->deq =
- dev->eps[0].ring->first_seg->dma;
- ep0_ctx->deq |= dev->eps[0].ring->cycle_state;
+ ep0_ctx->deq = cpu_to_le64(dev->eps[0].ring->first_seg->dma |
+ dev->eps[0].ring->cycle_state);
/* Steps 7 and 8 were done in xhci_alloc_virt_device() */
@@ -1099,8 +1098,8 @@ static inline u32 xhci_get_max_esit_payload(struct xhci_hcd *xhci,
if (udev->speed == USB_SPEED_SUPER)
return ep->ss_ep_comp.wBytesPerInterval;
- max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
- max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
+ max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize));
+ max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize) & 0x1800) >> 11;
/* A 0 in max burst means 1 transfer per ESIT */
return max_packet * (max_burst + 1);
}
@@ -1149,10 +1148,10 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
}
virt_dev->eps[ep_index].skip = false;
ep_ring = virt_dev->eps[ep_index].new_ring;
- ep_ctx->deq = ep_ring->first_seg->dma | ep_ring->cycle_state;
+ ep_ctx->deq = cpu_to_le64(ep_ring->first_seg->dma | ep_ring->cycle_state);
- ep_ctx->ep_info = xhci_get_endpoint_interval(udev, ep);
- ep_ctx->ep_info |= EP_MULT(xhci_get_endpoint_mult(udev, ep));
+ ep_ctx->ep_info = cpu_to_le32(xhci_get_endpoint_interval(udev, ep)
+ | EP_MULT(xhci_get_endpoint_mult(udev, ep)));
/* FIXME dig Mult and streams info out of ep companion desc */
@@ -1160,22 +1159,22 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
* error count = 0 means infinite retries.
*/
if (!usb_endpoint_xfer_isoc(&ep->desc))
- ep_ctx->ep_info2 = ERROR_COUNT(3);
+ ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(3));
else
- ep_ctx->ep_info2 = ERROR_COUNT(1);
+ ep_ctx->ep_info2 = cpu_to_le32(ERROR_COUNT(1));
- ep_ctx->ep_info2 |= xhci_get_endpoint_type(udev, ep);
+ ep_ctx->ep_info2 |= cpu_to_le32(xhci_get_endpoint_type(udev, ep));
/* Set the max packet size and max burst */
switch (udev->speed) {
case USB_SPEED_SUPER:
- max_packet = ep->desc.wMaxPacketSize;
- ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
+ max_packet = le16_to_cpu(ep->desc.wMaxPacketSize);
+ ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
/* dig out max burst from ep companion desc */
max_packet = ep->ss_ep_comp.bMaxBurst;
if (!max_packet)
xhci_warn(xhci, "WARN no SS endpoint bMaxBurst\n");
- ep_ctx->ep_info2 |= MAX_BURST(max_packet);
+ ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_packet));
break;
case USB_SPEED_HIGH:
/* bits 11:12 specify the number of additional transaction
@@ -1183,20 +1182,21 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
*/
if (usb_endpoint_xfer_isoc(&ep->desc) ||
usb_endpoint_xfer_int(&ep->desc)) {
- max_burst = (ep->desc.wMaxPacketSize & 0x1800) >> 11;
- ep_ctx->ep_info2 |= MAX_BURST(max_burst);
+ max_burst = (le16_to_cpu(ep->desc.wMaxPacketSize)
+ & 0x1800) >> 11;
+ ep_ctx->ep_info2 |= cpu_to_le32(MAX_BURST(max_burst));
}
/* Fall through */
case USB_SPEED_FULL:
case USB_SPEED_LOW:
- max_packet = GET_MAX_PACKET(ep->desc.wMaxPacketSize);
- ep_ctx->ep_info2 |= MAX_PACKET(max_packet);
+ max_packet = GET_MAX_PACKET(le16_to_cpu(ep->desc.wMaxPacketSize));
+ ep_ctx->ep_info2 |= cpu_to_le32(MAX_PACKET(max_packet));
break;
default:
BUG();
}
max_esit_payload = xhci_get_max_esit_payload(xhci, udev, ep);
- ep_ctx->tx_info = MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload);
+ ep_ctx->tx_info = cpu_to_le32(MAX_ESIT_PAYLOAD_FOR_EP(max_esit_payload));
/*
* XXX no idea how to calculate the average TRB buffer length for bulk
@@ -1213,7 +1213,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
* use Event Data TRBs, and we don't chain in a link TRB on short
* transfers, we're basically dividing by 1.
*/
- ep_ctx->tx_info |= AVG_TRB_LENGTH_FOR_EP(max_esit_payload);
+ ep_ctx->tx_info |= cpu_to_le32(AVG_TRB_LENGTH_FOR_EP(max_esit_payload));
/* FIXME Debug endpoint context */
return 0;
@@ -1313,7 +1313,7 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
if (!xhci->scratchpad->sp_dma_buffers)
goto fail_sp4;
- xhci->dcbaa->dev_context_ptrs[0] = xhci->scratchpad->sp_dma;
+ xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
for (i = 0; i < num_sp; i++) {
dma_addr_t dma;
void *buf = pci_alloc_consistent(to_pci_dev(dev),
@@ -1690,7 +1690,7 @@ static void xhci_set_hc_event_deq(struct xhci_hcd *xhci)
}
static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
- u32 __iomem *addr, u8 major_revision)
+ __le32 __iomem *addr, u8 major_revision)
{
u32 temp, port_offset, port_count;
int i;
@@ -1755,7 +1755,7 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
*/
static int xhci_setup_port_arrays(struct xhci_hcd *xhci, gfp_t flags)
{
- u32 __iomem *addr;
+ __le32 __iomem *addr;
u32 offset;
unsigned int num_ports;
int i, port_index;
@@ -2008,8 +2008,8 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
/* set ring base address and size for each segment table entry */
for (val = 0, seg = xhci->event_ring->first_seg; val < ERST_NUM_SEGS; val++) {
struct xhci_erst_entry *entry = &xhci->erst.entries[val];
- entry->seg_addr = seg->dma;
- entry->seg_size = TRBS_PER_SEGMENT;
+ entry->seg_addr = cpu_to_le64(seg->dma);
+ entry->seg_size = cpu_to_le32(TRBS_PER_SEGMENT);
entry->rsvd = 0;
seg = seg->next;
}
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index cfc1ad9..3898f22 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -100,7 +100,7 @@ static inline bool last_trb_on_last_seg(struct xhci_hcd *xhci, struct xhci_ring
return (trb == &seg->trbs[TRBS_PER_SEGMENT]) &&
(seg->next == xhci->event_ring->first_seg);
else
- return trb->link.control & LINK_TOGGLE;
+ return le32_to_cpu(trb->link.control) & LINK_TOGGLE;
}
/* Is this TRB a link TRB or was the last TRB the last TRB in this event ring
@@ -113,13 +113,15 @@ static inline int last_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
if (ring == xhci->event_ring)
return trb == &seg->trbs[TRBS_PER_SEGMENT];
else
- return (trb->link.control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK);
+ return (le32_to_cpu(trb->link.control) & TRB_TYPE_BITMASK)
+ == TRB_TYPE(TRB_LINK);
}
static inline int enqueue_is_link_trb(struct xhci_ring *ring)
{
struct xhci_link_trb *link = &ring->enqueue->link;
- return ((link->control & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK));
+ return ((le32_to_cpu(link->control) & TRB_TYPE_BITMASK) ==
+ TRB_TYPE(TRB_LINK));
}
/* Updates trb to point to the next TRB in the ring, and updates seg if the next
@@ -197,7 +199,7 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
union xhci_trb *next;
unsigned long long addr;
- chain = ring->enqueue->generic.field[3] & TRB_CHAIN;
+ chain = le32_to_cpu(ring->enqueue->generic.field[3]) & TRB_CHAIN;
next = ++(ring->enqueue);
ring->enq_updates++;
@@ -223,12 +225,14 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
* (which may mean the chain bit is cleared).
*/
if (!xhci_link_trb_quirk(xhci)) {
- next->link.control &= ~TRB_CHAIN;
- next->link.control |= chain;
+ next->link.control &=
+ cpu_to_le32(~TRB_CHAIN);
+ next->link.control |=
+ cpu_to_le32(chain);
}
/* Give this link TRB to the hardware */
wmb();
- next->link.control ^= TRB_CYCLE;
+ next->link.control ^= cpu_to_le32(TRB_CYCLE);
}
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -319,7 +323,7 @@ void xhci_ring_ep_doorbell(struct xhci_hcd *xhci,
unsigned int ep_index,
unsigned int stream_id)
{
- __u32 __iomem *db_addr = &xhci->dba->doorbell[slot_id];
+ __le32 __iomem *db_addr = &xhci->dba->doorbell[slot_id];
struct xhci_virt_ep *ep = &xhci->devs[slot_id]->eps[ep_index];
unsigned int ep_state = ep->ep_state;
@@ -380,7 +384,7 @@ static struct xhci_segment *find_trb_seg(
while (cur_seg->trbs > trb ||
&cur_seg->trbs[TRBS_PER_SEGMENT - 1] < trb) {
generic_trb = &cur_seg->trbs[TRBS_PER_SEGMENT - 1].generic;
- if (generic_trb->field[3] & LINK_TOGGLE)
+ if (le32_to_cpu(generic_trb->field[3]) & LINK_TOGGLE)
*cycle_state ^= 0x1;
cur_seg = cur_seg->next;
if (cur_seg == start_seg)
@@ -447,6 +451,10 @@ static struct xhci_ring *xhci_urb_to_transfer_ring(struct xhci_hcd *xhci,
* any link TRBs with the toggle cycle bit set.
* - Finally we move the dequeue state one TRB further, toggling the cycle bit
* if we've moved it past a link TRB with the toggle cycle bit set.
+ *
+ * Some of the uses of xhci_generic_trb are grotty, but if they're done
+ * with correct __le32 accesses they should work fine. Only users of this are
+ * in here.
*/
void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
unsigned int slot_id, unsigned int ep_index,
@@ -480,7 +488,7 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
/* Dig out the cycle state saved by the xHC during the stop ep cmd */
xhci_dbg(xhci, "Finding endpoint context\n");
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
- state->new_cycle_state = 0x1 & ep_ctx->deq;
+ state->new_cycle_state = 0x1 & le64_to_cpu(ep_ctx->deq);
state->new_deq_ptr = cur_td->last_trb;
xhci_dbg(xhci, "Finding segment containing last TRB in TD.\n");
@@ -493,8 +501,8 @@ void xhci_find_new_dequeue_state(struct xhci_hcd *xhci,
}
trb = &state->new_deq_ptr->generic;
- if ((trb->field[3] & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK) &&
- (trb->field[3] & LINK_TOGGLE))
+ if ((le32_to_cpu(trb->field[3]) & TRB_TYPE_BITMASK) ==
+ TRB_TYPE(TRB_LINK) && (le32_to_cpu(trb->field[3]) & LINK_TOGGLE))
state->new_cycle_state ^= 0x1;
next_trb(xhci, ep_ring, &state->new_deq_seg, &state->new_deq_ptr);
@@ -529,12 +537,14 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
for (cur_seg = cur_td->start_seg, cur_trb = cur_td->first_trb;
true;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
- if ((cur_trb->generic.field[3] & TRB_TYPE_BITMASK) ==
- TRB_TYPE(TRB_LINK)) {
+ u32 f;
+ if ((le32_to_cpu(cur_trb->generic.field[3]) & TRB_TYPE_BITMASK)
+ == TRB_TYPE(TRB_LINK)) {
/* Unchain any chained Link TRBs, but
* leave the pointers intact.
*/
- cur_trb->generic.field[3] &= ~TRB_CHAIN;
+ f = le32_to_cpu(cur_trb->generic.field[3]) & ~TRB_CHAIN;
+ cur_trb->generic.field[3] = cpu_to_le32(f);
xhci_dbg(xhci, "Cancel (unchain) link TRB\n");
xhci_dbg(xhci, "Address = %p (0x%llx dma); "
"in seg %p (0x%llx dma)\n",
@@ -547,8 +557,9 @@ static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
cur_trb->generic.field[1] = 0;
cur_trb->generic.field[2] = 0;
/* Preserve only the cycle bit of this TRB */
- cur_trb->generic.field[3] &= TRB_CYCLE;
- cur_trb->generic.field[3] |= TRB_TYPE(TRB_TR_NOOP);
+ f = (le32_to_cpu(cur_trb->generic.field[3]) & TRB_CYCLE)
+ | TRB_TYPE(TRB_TR_NOOP);
+ cur_trb->generic.field[3] = cpu_to_le32(f);
xhci_dbg(xhci, "Cancel TRB %p (0x%llx dma) "
"in seg %p (0x%llx dma)\n",
cur_trb,
@@ -655,9 +666,9 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
struct xhci_dequeue_state deq_state;
if (unlikely(TRB_TO_SUSPEND_PORT(
- xhci->cmd_ring->dequeue->generic.field[3]))) {
+ le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])))) {
slot_id = TRB_TO_SLOT_ID(
- xhci->cmd_ring->dequeue->generic.field[3]);
+ le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]));
virt_dev = xhci->devs[slot_id];
if (virt_dev)
handle_cmd_in_cmd_wait_list(xhci, virt_dev,
@@ -670,8 +681,8 @@ static void handle_stopped_endpoint(struct xhci_hcd *xhci,
}
memset(&deq_state, 0, sizeof(deq_state));
- slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
- ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3]));
+ ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
ep = &xhci->devs[slot_id]->eps[ep_index];
if (list_empty(&ep->cancelled_td_list)) {
@@ -903,9 +914,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
- slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
- ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
- stream_id = TRB_TO_STREAM_ID(trb->generic.field[2]);
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3]));
+ ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
+ stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
dev = xhci->devs[slot_id];
ep_ring = xhci_stream_id_to_ring(dev, ep_index, stream_id);
@@ -921,11 +932,11 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
slot_ctx = xhci_get_slot_ctx(xhci, dev->out_ctx);
- if (GET_COMP_CODE(event->status) != COMP_SUCCESS) {
+ if (GET_COMP_CODE(le32_to_cpu(event->status)) != COMP_SUCCESS) {
unsigned int ep_state;
unsigned int slot_state;
- switch (GET_COMP_CODE(event->status)) {
+ switch (GET_COMP_CODE(le32_to_cpu(event->status))) {
case COMP_TRB_ERR:
xhci_warn(xhci, "WARN Set TR Deq Ptr cmd invalid because "
"of stream ID configuration\n");
@@ -933,9 +944,9 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
case COMP_CTX_STATE:
xhci_warn(xhci, "WARN Set TR Deq Ptr cmd failed due "
"to incorrect slot or ep state.\n");
- ep_state = ep_ctx->ep_info;
+ ep_state = le32_to_cpu(ep_ctx->ep_info);
ep_state &= EP_STATE_MASK;
- slot_state = slot_ctx->dev_state;
+ slot_state = le32_to_cpu(slot_ctx->dev_state);
slot_state = GET_SLOT_STATE(slot_state);
xhci_dbg(xhci, "Slot state = %u, EP state = %u\n",
slot_state, ep_state);
@@ -947,7 +958,7 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
default:
xhci_warn(xhci, "WARN Set TR Deq Ptr cmd with unknown "
"completion code of %u.\n",
- GET_COMP_CODE(event->status));
+ GET_COMP_CODE(le32_to_cpu(event->status)));
break;
}
/* OK what do we do now? The endpoint state is hosed, and we
@@ -958,10 +969,10 @@ static void handle_set_deq_completion(struct xhci_hcd *xhci,
*/
} else {
xhci_dbg(xhci, "Successful Set TR Deq Ptr cmd, deq = @%08llx\n",
- ep_ctx->deq);
+ le64_to_cpu(ep_ctx->deq));
if (xhci_trb_virt_to_dma(dev->eps[ep_index].queued_deq_seg,
- dev->eps[ep_index].queued_deq_ptr) ==
- (ep_ctx->deq & ~(EP_CTX_CYCLE_MASK))) {
+ dev->eps[ep_index].queued_deq_ptr) ==
+ (le64_to_cpu(ep_ctx->deq) & ~(EP_CTX_CYCLE_MASK))) {
/* Update the ring's dequeue segment and dequeue pointer
* to reflect the new position.
*/
@@ -990,13 +1001,13 @@ static void handle_reset_ep_completion(struct xhci_hcd *xhci,
int slot_id;
unsigned int ep_index;
- slot_id = TRB_TO_SLOT_ID(trb->generic.field[3]);
- ep_index = TRB_TO_EP_INDEX(trb->generic.field[3]);
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(trb->generic.field[3]));
+ ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
/* This command will only fail if the endpoint wasn't halted,
* but we don't care.
*/
xhci_dbg(xhci, "Ignoring reset ep completion code of %u\n",
- (unsigned int) GET_COMP_CODE(event->status));
+ (unsigned int) GET_COMP_CODE(le32_to_cpu(event->status)));
/* HW with the reset endpoint quirk needs to have a configure endpoint
* command complete before the endpoint can be used. Queue that here
@@ -1033,8 +1044,7 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
if (xhci->cmd_ring->dequeue != command->command_trb)
return 0;
- command->status =
- GET_COMP_CODE(event->status);
+ command->status = GET_COMP_CODE(le32_to_cpu(event->status));
list_del(&command->cmd_list);
if (command->completion)
complete(command->completion);
@@ -1046,7 +1056,7 @@ static int handle_cmd_in_cmd_wait_list(struct xhci_hcd *xhci,
static void handle_cmd_completion(struct xhci_hcd *xhci,
struct xhci_event_cmd *event)
{
- int slot_id = TRB_TO_SLOT_ID(event->flags);
+ int slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
u64 cmd_dma;
dma_addr_t cmd_dequeue_dma;
struct xhci_input_control_ctx *ctrl_ctx;
@@ -1055,7 +1065,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
struct xhci_ring *ep_ring;
unsigned int ep_state;
- cmd_dma = event->cmd_trb;
+ cmd_dma = le64_to_cpu(event->cmd_trb);
cmd_dequeue_dma = xhci_trb_virt_to_dma(xhci->cmd_ring->deq_seg,
xhci->cmd_ring->dequeue);
/* Is the command ring deq ptr out of sync with the deq seg ptr? */
@@ -1068,9 +1078,10 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
xhci->error_bitmask |= 1 << 5;
return;
}
- switch (xhci->cmd_ring->dequeue->generic.field[3] & TRB_TYPE_BITMASK) {
+ switch (le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3])
+ & TRB_TYPE_BITMASK) {
case TRB_TYPE(TRB_ENABLE_SLOT):
- if (GET_COMP_CODE(event->status) == COMP_SUCCESS)
+ if (GET_COMP_CODE(le32_to_cpu(event->status)) == COMP_SUCCESS)
xhci->slot_id = slot_id;
else
xhci->slot_id = 0;
@@ -1095,7 +1106,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
ctrl_ctx = xhci_get_input_control_ctx(xhci,
virt_dev->in_ctx);
/* Input ctx add_flags are the endpoint index plus one */
- ep_index = xhci_last_valid_endpoint(ctrl_ctx->add_flags) - 1;
+ ep_index = xhci_last_valid_endpoint(le32_to_cpu(ctrl_ctx->add_flags)) - 1;
/* A usb_set_interface() call directly after clearing a halted
* condition may race on this quirky hardware. Not worth
* worrying about, since this is prototype hardware. Not sure
@@ -1104,8 +1115,8 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
*/
if (xhci->quirks & XHCI_RESET_EP_QUIRK &&
ep_index != (unsigned int) -1 &&
- ctrl_ctx->add_flags - SLOT_FLAG ==
- ctrl_ctx->drop_flags) {
+ le32_to_cpu(ctrl_ctx->add_flags) - SLOT_FLAG ==
+ le32_to_cpu(ctrl_ctx->drop_flags)) {
ep_ring = xhci->devs[slot_id]->eps[ep_index].ring;
ep_state = xhci->devs[slot_id]->eps[ep_index].ep_state;
if (!(ep_state & EP_HALTED))
@@ -1122,18 +1133,18 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
bandwidth_change:
xhci_dbg(xhci, "Completed config ep cmd\n");
xhci->devs[slot_id]->cmd_status =
- GET_COMP_CODE(event->status);
+ GET_COMP_CODE(le32_to_cpu(event->status));
complete(&xhci->devs[slot_id]->cmd_completion);
break;
case TRB_TYPE(TRB_EVAL_CONTEXT):
virt_dev = xhci->devs[slot_id];
if (handle_cmd_in_cmd_wait_list(xhci, virt_dev, event))
break;
- xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+ xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status));
complete(&xhci->devs[slot_id]->cmd_completion);
break;
case TRB_TYPE(TRB_ADDR_DEV):
- xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(event->status);
+ xhci->devs[slot_id]->cmd_status = GET_COMP_CODE(le32_to_cpu(event->status));
complete(&xhci->addr_dev);
break;
case TRB_TYPE(TRB_STOP_RING):
@@ -1150,7 +1161,7 @@ bandwidth_change:
case TRB_TYPE(TRB_RESET_DEV):
xhci_dbg(xhci, "Completed reset device command.\n");
slot_id = TRB_TO_SLOT_ID(
- xhci->cmd_ring->dequeue->generic.field[3]);
+ le32_to_cpu(xhci->cmd_ring->dequeue->generic.field[3]));
virt_dev = xhci->devs[slot_id];
if (virt_dev)
handle_cmd_in_cmd_wait_list(xhci, virt_dev, event);
@@ -1164,8 +1175,8 @@ bandwidth_change:
break;
}
xhci_dbg(xhci, "NEC firmware version %2x.%02x\n",
- NEC_FW_MAJOR(event->status),
- NEC_FW_MINOR(event->status));
+ NEC_FW_MAJOR(le32_to_cpu(event->status)),
+ NEC_FW_MINOR(le32_to_cpu(event->status)));
break;
default:
/* Skip over unknown commands on the event ring */
@@ -1180,7 +1191,7 @@ static void handle_vendor_event(struct xhci_hcd *xhci,
{
u32 trb_type;
- trb_type = TRB_FIELD_TO_TYPE(event->generic.field[3]);
+ trb_type = TRB_FIELD_TO_TYPE(le32_to_cpu(event->generic.field[3]));
xhci_dbg(xhci, "Vendor specific event TRB type = %u\n", trb_type);
if (trb_type == TRB_NEC_CMD_COMP && (xhci->quirks & XHCI_NEC_HOST))
handle_cmd_completion(xhci, &event->event_cmd);
@@ -1234,14 +1245,14 @@ static void handle_port_status(struct xhci_hcd *xhci,
unsigned int faked_port_index;
u8 major_revision;
struct xhci_bus_state *bus_state;
- u32 __iomem **port_array;
+ __le32 __iomem **port_array;
/* Port status change events always have a successful completion code */
- if (GET_COMP_CODE(event->generic.field[2]) != COMP_SUCCESS) {
+ if (GET_COMP_CODE(le32_to_cpu(event->generic.field[2])) != COMP_SUCCESS) {
xhci_warn(xhci, "WARN: xHC returned failed port status event\n");
xhci->error_bitmask |= 1 << 8;
}
- port_id = GET_PORT_ID(event->generic.field[0]);
+ port_id = GET_PORT_ID(le32_to_cpu(event->generic.field[0]));
xhci_dbg(xhci, "Port Status Change Event for port %d\n", port_id);
max_ports = HCS_MAX_PORTS(xhci->hcs_params1);
@@ -1438,7 +1449,7 @@ static int xhci_requires_manual_halt_cleanup(struct xhci_hcd *xhci,
* endpoint anyway. Check if a babble halted the
* endpoint.
*/
- if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_HALTED)
+ if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) == EP_STATE_HALTED)
return 1;
return 0;
@@ -1476,12 +1487,12 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_td *td,
struct urb_priv *urb_priv;
u32 trb_comp_code;
- slot_id = TRB_TO_SLOT_ID(event->flags);
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
- ep_index = TRB_TO_EP_ID(event->flags) - 1;
- ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+ ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
- trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
if (skip)
goto td_cleanup;
@@ -1575,12 +1586,12 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
struct xhci_ep_ctx *ep_ctx;
u32 trb_comp_code;
- slot_id = TRB_TO_SLOT_ID(event->flags);
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
- ep_index = TRB_TO_EP_ID(event->flags) - 1;
- ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+ ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
- trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
xhci_debug_trb(xhci, xhci->event_ring->dequeue);
switch (trb_comp_code) {
@@ -1619,7 +1630,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
event_trb != td->last_trb)
td->urb->actual_length =
td->urb->transfer_buffer_length
- - TRB_LEN(event->transfer_len);
+ - TRB_LEN(le32_to_cpu(event->transfer_len));
else
td->urb->actual_length = 0;
@@ -1653,7 +1664,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* We didn't stop on a link TRB in the middle */
td->urb->actual_length =
td->urb->transfer_buffer_length -
- TRB_LEN(event->transfer_len);
+ TRB_LEN(le32_to_cpu(event->transfer_len));
xhci_dbg(xhci, "Waiting for status "
"stage event\n");
return 0;
@@ -1680,8 +1691,8 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
struct xhci_segment *cur_seg;
u32 trb_comp_code;
- ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
- trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
urb_priv = td->urb->hcpriv;
idx = urb_priv->td_cnt;
@@ -1744,15 +1755,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
for (cur_trb = ep_ring->dequeue,
cur_seg = ep_ring->deq_seg; cur_trb != event_trb;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
- if ((cur_trb->generic.field[3] &
+ if ((le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
- (cur_trb->generic.field[3] &
+ (le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
- len +=
- TRB_LEN(cur_trb->generic.field[2]);
+ len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
}
- len += TRB_LEN(cur_trb->generic.field[2]) -
- TRB_LEN(event->transfer_len);
+ len += TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+ TRB_LEN(le32_to_cpu(event->transfer_len));
if (trb_comp_code != COMP_STOP_INVAL) {
td->urb->iso_frame_desc[idx].actual_length = len;
@@ -1778,8 +1788,8 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
struct xhci_segment *cur_seg;
u32 trb_comp_code;
- ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
- trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
switch (trb_comp_code) {
case COMP_SUCCESS:
@@ -1815,18 +1825,18 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
"%d bytes untransferred\n",
td->urb->ep->desc.bEndpointAddress,
td->urb->transfer_buffer_length,
- TRB_LEN(event->transfer_len));
+ TRB_LEN(le32_to_cpu(event->transfer_len)));
/* Fast path - was this the last TRB in the TD for this URB? */
if (event_trb == td->last_trb) {
- if (TRB_LEN(event->transfer_len) != 0) {
+ if (TRB_LEN(le32_to_cpu(event->transfer_len)) != 0) {
td->urb->actual_length =
td->urb->transfer_buffer_length -
- TRB_LEN(event->transfer_len);
+ TRB_LEN(le32_to_cpu(event->transfer_len));
if (td->urb->transfer_buffer_length <
td->urb->actual_length) {
xhci_warn(xhci, "HC gave bad length "
"of %d bytes left\n",
- TRB_LEN(event->transfer_len));
+ TRB_LEN(le32_to_cpu(event->transfer_len)));
td->urb->actual_length = 0;
if (td->urb->transfer_flags & URB_SHORT_NOT_OK)
*status = -EREMOTEIO;
@@ -1857,20 +1867,20 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_td *td,
for (cur_trb = ep_ring->dequeue, cur_seg = ep_ring->deq_seg;
cur_trb != event_trb;
next_trb(xhci, ep_ring, &cur_seg, &cur_trb)) {
- if ((cur_trb->generic.field[3] &
+ if ((le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_TR_NOOP) &&
- (cur_trb->generic.field[3] &
+ (le32_to_cpu(cur_trb->generic.field[3]) &
TRB_TYPE_BITMASK) != TRB_TYPE(TRB_LINK))
td->urb->actual_length +=
- TRB_LEN(cur_trb->generic.field[2]);
+ TRB_LEN(le32_to_cpu(cur_trb->generic.field[2]));
}
/* If the ring didn't stop on a Link or No-op TRB, add
* in the actual bytes transferred from the Normal TRB
*/
if (trb_comp_code != COMP_STOP_INVAL)
td->urb->actual_length +=
- TRB_LEN(cur_trb->generic.field[2]) -
- TRB_LEN(event->transfer_len);
+ TRB_LEN(le32_to_cpu(cur_trb->generic.field[2])) -
+ TRB_LEN(le32_to_cpu(event->transfer_len));
}
return finish_td(xhci, td, event_trb, event, ep, status, false);
@@ -1900,7 +1910,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
u32 trb_comp_code;
int ret = 0;
- slot_id = TRB_TO_SLOT_ID(event->flags);
+ slot_id = TRB_TO_SLOT_ID(le32_to_cpu(event->flags));
xdev = xhci->devs[slot_id];
if (!xdev) {
xhci_err(xhci, "ERROR Transfer event pointed to bad slot\n");
@@ -1908,20 +1918,21 @@ static int handle_tx_event(struct xhci_hcd *xhci,
}
/* Endpoint ID is 1 based, our index is zero based */
- ep_index = TRB_TO_EP_ID(event->flags) - 1;
+ ep_index = TRB_TO_EP_ID(le32_to_cpu(event->flags)) - 1;
xhci_dbg(xhci, "%s - ep index = %d\n", __func__, ep_index);
ep = &xdev->eps[ep_index];
- ep_ring = xhci_dma_to_transfer_ring(ep, event->buffer);
+ ep_ring = xhci_dma_to_transfer_ring(ep, le64_to_cpu(event->buffer));
ep_ctx = xhci_get_ep_ctx(xhci, xdev->out_ctx, ep_index);
if (!ep_ring ||
- (ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED) {
+ (le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
+ EP_STATE_DISABLED) {
xhci_err(xhci, "ERROR Transfer event for disabled endpoint "
"or incorrect stream ring\n");
return -ENODEV;
}
- event_dma = event->buffer;
- trb_comp_code = GET_COMP_CODE(event->transfer_len);
+ event_dma = le64_to_cpu(event->buffer);
+ trb_comp_code = GET_COMP_CODE(le32_to_cpu(event->transfer_len));
/* Look for common error cases */
switch (trb_comp_code) {
/* Skip codes that require special handling depending on
@@ -1974,14 +1985,16 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (!list_empty(&ep_ring->td_list))
xhci_dbg(xhci, "Underrun Event for slot %d ep %d "
"still with TDs queued?\n",
- TRB_TO_SLOT_ID(event->flags), ep_index);
+ TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
+ ep_index);
goto cleanup;
case COMP_OVERRUN:
xhci_dbg(xhci, "overrun event on endpoint\n");
if (!list_empty(&ep_ring->td_list))
xhci_dbg(xhci, "Overrun Event for slot %d ep %d "
"still with TDs queued?\n",
- TRB_TO_SLOT_ID(event->flags), ep_index);
+ TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
+ ep_index);
goto cleanup;
case COMP_MISSED_INT:
/*
@@ -2010,9 +2023,11 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (list_empty(&ep_ring->td_list)) {
xhci_warn(xhci, "WARN Event TRB for slot %d ep %d "
"with no TDs queued?\n",
- TRB_TO_SLOT_ID(event->flags), ep_index);
+ TRB_TO_SLOT_ID(le32_to_cpu(event->flags)),
+ ep_index);
xhci_dbg(xhci, "Event TRB with TRB type ID %u\n",
- (unsigned int) (event->flags & TRB_TYPE_BITMASK)>>10);
+ (unsigned int) (le32_to_cpu(event->flags)
+ & TRB_TYPE_BITMASK)>>10);
xhci_print_trb_offsets(xhci, (union xhci_trb *) event);
if (ep->skip) {
ep->skip = false;
@@ -2048,7 +2063,8 @@ static int handle_tx_event(struct xhci_hcd *xhci,
* corresponding TD has been cancelled. Just ignore
* the TD.
*/
- if ((event_trb->generic.field[3] & TRB_TYPE_BITMASK)
+ if ((le32_to_cpu(event_trb->generic.field[3])
+ & TRB_TYPE_BITMASK)
== TRB_TYPE(TRB_TR_NOOP)) {
xhci_dbg(xhci, "event_trb is a no-op TRB. "
"Skip it\n");
@@ -2129,15 +2145,15 @@ static void xhci_handle_event(struct xhci_hcd *xhci)
event = xhci->event_ring->dequeue;
/* Does the HC or OS own the TRB? */
- if ((event->event_cmd.flags & TRB_CYCLE) !=
- xhci->event_ring->cycle_state) {
+ if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) !=
+ xhci->event_ring->cycle_state) {
xhci->error_bitmask |= 1 << 2;
return;
}
xhci_dbg(xhci, "%s - OS owns TRB\n", __func__);
/* FIXME: Handle more event types. */
- switch ((event->event_cmd.flags & TRB_TYPE_BITMASK)) {
+ switch ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK)) {
case TRB_TYPE(TRB_COMPLETION):
xhci_dbg(xhci, "%s - calling handle_cmd_completion\n", __func__);
handle_cmd_completion(xhci, &event->event_cmd);
@@ -2159,7 +2175,8 @@ static void xhci_handle_event(struct xhci_hcd *xhci)
update_ptrs = 0;
break;
default:
- if ((event->event_cmd.flags & TRB_TYPE_BITMASK) >= TRB_TYPE(48))
+ if ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK) >=
+ TRB_TYPE(48))
handle_vendor_event(xhci, event);
else
xhci->error_bitmask |= 1 << 3;
@@ -2209,12 +2226,12 @@ irqreturn_t xhci_irq(struct usb_hcd *hcd)
xhci_dbg(xhci, "op reg status = %08x\n", status);
xhci_dbg(xhci, "Event ring dequeue ptr:\n");
xhci_dbg(xhci, "@%llx %08x %08x %08x %08x\n",
- (unsigned long long)
- xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
- lower_32_bits(trb->link.segment_ptr),
- upper_32_bits(trb->link.segment_ptr),
- (unsigned int) trb->link.intr_target,
- (unsigned int) trb->link.control);
+ (unsigned long long)
+ xhci_trb_virt_to_dma(xhci->event_ring->deq_seg, trb),
+ lower_32_bits(le64_to_cpu(trb->link.segment_ptr)),
+ upper_32_bits(le64_to_cpu(trb->link.segment_ptr)),
+ (unsigned int) le32_to_cpu(trb->link.intr_target),
+ (unsigned int) le32_to_cpu(trb->link.control));
if (status & STS_FATAL) {
xhci_warn(xhci, "WARNING: Host System Error\n");
@@ -2315,10 +2332,10 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
struct xhci_generic_trb *trb;
trb = &ring->enqueue->generic;
- trb->field[0] = field1;
- trb->field[1] = field2;
- trb->field[2] = field3;
- trb->field[3] = field4;
+ trb->field[0] = cpu_to_le32(field1);
+ trb->field[1] = cpu_to_le32(field2);
+ trb->field[2] = cpu_to_le32(field3);
+ trb->field[3] = cpu_to_le32(field4);
inc_enq(xhci, ring, consumer, more_trbs_coming);
}
@@ -2371,17 +2388,16 @@ static int prepare_ring(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
next = ring->enqueue;
while (last_trb(xhci, ring, ring->enq_seg, next)) {
-
/* If we're not dealing with 0.95 hardware,
* clear the chain bit.
*/
if (!xhci_link_trb_quirk(xhci))
- next->link.control &= ~TRB_CHAIN;
+ next->link.control &= cpu_to_le32(~TRB_CHAIN);
else
- next->link.control |= TRB_CHAIN;
+ next->link.control |= cpu_to_le32(TRB_CHAIN);
wmb();
- next->link.control ^= (u32) TRB_CYCLE;
+ next->link.control ^= cpu_to_le32((u32) TRB_CYCLE);
/* Toggle the cycle bit after the last ring segment. */
if (last_trb_on_last_seg(xhci, ring, ring->enq_seg, next)) {
@@ -2424,8 +2440,8 @@ static int prepare_transfer(struct xhci_hcd *xhci,
}
ret = prepare_ring(xhci, ep_ring,
- ep_ctx->ep_info & EP_STATE_MASK,
- num_trbs, mem_flags);
+ le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
+ num_trbs, mem_flags);
if (ret)
return ret;
@@ -2527,9 +2543,9 @@ static void giveback_first_trb(struct xhci_hcd *xhci, int slot_id,
*/
wmb();
if (start_cycle)
- start_trb->field[3] |= start_cycle;
+ start_trb->field[3] |= cpu_to_le32(start_cycle);
else
- start_trb->field[3] &= ~0x1;
+ start_trb->field[3] &= cpu_to_le32(~TRB_CYCLE);
xhci_ring_ep_doorbell(xhci, slot_id, ep_index, stream_id);
}
@@ -2547,7 +2563,7 @@ int xhci_queue_intr_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
int xhci_interval;
int ep_interval;
- xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
+ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info));
ep_interval = urb->interval;
/* Convert to microframes */
if (urb->dev->speed == USB_SPEED_LOW ||
@@ -2936,12 +2952,11 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (start_cycle == 0)
field |= 0x1;
queue_trb(xhci, ep_ring, false, true,
- /* FIXME endianness is probably going to bite my ass here. */
- setup->bRequestType | setup->bRequest << 8 | setup->wValue << 16,
- setup->wIndex | setup->wLength << 16,
- TRB_LEN(8) | TRB_INTR_TARGET(0),
- /* Immediate data in pointer */
- field);
+ setup->bRequestType | setup->bRequest << 8 | le16_to_cpu(setup->wValue) << 16,
+ le16_to_cpu(setup->wIndex) | le16_to_cpu(setup->wLength) << 16,
+ TRB_LEN(8) | TRB_INTR_TARGET(0),
+ /* Immediate data in pointer */
+ field);
/* If there's data, queue data TRBs */
field = 0;
@@ -3162,8 +3177,8 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
/* Check the ring to guarantee there is enough room for the whole urb.
* Do not insert any td of the urb to the ring if the check failed.
*/
- ret = prepare_ring(xhci, ep_ring, ep_ctx->ep_info & EP_STATE_MASK,
- num_trbs, mem_flags);
+ ret = prepare_ring(xhci, ep_ring, le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK,
+ num_trbs, mem_flags);
if (ret)
return ret;
@@ -3175,7 +3190,7 @@ int xhci_queue_isoc_tx_prepare(struct xhci_hcd *xhci, gfp_t mem_flags,
urb->dev->speed == USB_SPEED_FULL)
urb->start_frame >>= 3;
- xhci_interval = EP_INTERVAL_TO_UFRAMES(ep_ctx->ep_info);
+ xhci_interval = EP_INTERVAL_TO_UFRAMES(le32_to_cpu(ep_ctx->ep_info));
ep_interval = urb->interval;
/* Convert to microframes */
if (urb->dev->speed == USB_SPEED_LOW ||
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 9a3645f..88e6298 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -968,9 +968,10 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
out_ctx = xhci->devs[slot_id]->out_ctx;
ep_ctx = xhci_get_ep_ctx(xhci, out_ctx, ep_index);
- hw_max_packet_size = MAX_PACKET_DECODED(ep_ctx->ep_info2);
- max_packet_size = urb->dev->ep0.desc.wMaxPacketSize;
+ hw_max_packet_size = MAX_PACKET_DECODED(le32_to_cpu(ep_ctx->ep_info2));
+ max_packet_size = le16_to_cpu(urb->dev->ep0.desc.wMaxPacketSize);
if (hw_max_packet_size != max_packet_size) {
+ u32 i;
xhci_dbg(xhci, "Max Packet Size for ep 0 changed.\n");
xhci_dbg(xhci, "Max packet size in usb_device = %d\n",
max_packet_size);
@@ -983,15 +984,15 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
xhci->devs[slot_id]->out_ctx, ep_index);
in_ctx = xhci->devs[slot_id]->in_ctx;
ep_ctx = xhci_get_ep_ctx(xhci, in_ctx, ep_index);
- ep_ctx->ep_info2 &= ~MAX_PACKET_MASK;
- ep_ctx->ep_info2 |= MAX_PACKET(max_packet_size);
+ i = (le32_to_cpu(ep_ctx->ep_info2) & ~MAX_PACKET_MASK);
+ ep_ctx->ep_info2 = cpu_to_le32(i | MAX_PACKET(max_packet_size));
/* Set up the input context flags for the command */
/* FIXME: This won't work if a non-default control endpoint
* changes max packet sizes.
*/
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
- ctrl_ctx->add_flags = EP0_FLAG;
+ ctrl_ctx->add_flags = cpu_to_le32(EP0_FLAG);
ctrl_ctx->drop_flags = 0;
xhci_dbg(xhci, "Slot %d input context\n", slot_id);
@@ -1005,7 +1006,7 @@ static int xhci_check_maxpacket(struct xhci_hcd *xhci, unsigned int slot_id,
/* Clean up the input context for later use by bandwidth
* functions.
*/
- ctrl_ctx->add_flags = SLOT_FLAG;
+ ctrl_ctx->add_flags = cpu_to_le32(SLOT_FLAG);
}
return ret;
}
@@ -1303,6 +1304,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
struct xhci_ep_ctx *ep_ctx;
u32 drop_flag;
u32 new_add_flags, new_drop_flags, new_slot_info;
+ u32 f;
int ret;
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
@@ -1326,27 +1328,33 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
/* If the HC already knows the endpoint is disabled,
* or the HCD has noted it is disabled, ignore this request
*/
- if ((ep_ctx->ep_info & EP_STATE_MASK) == EP_STATE_DISABLED ||
- ctrl_ctx->drop_flags & xhci_get_endpoint_flag(&ep->desc)) {
+ if ((le32_to_cpu(ep_ctx->ep_info) & EP_STATE_MASK) ==
+ EP_STATE_DISABLED ||
+ le32_to_cpu(ctrl_ctx->drop_flags) &
+ xhci_get_endpoint_flag(&ep->desc)) {
xhci_warn(xhci, "xHCI %s called with disabled ep %p\n",
__func__, ep);
return 0;
}
- ctrl_ctx->drop_flags |= drop_flag;
- new_drop_flags = ctrl_ctx->drop_flags;
+ f = le32_to_cpu(ctrl_ctx->drop_flags) | drop_flag;
+ ctrl_ctx->drop_flags = cpu_to_le32(f);
+ new_drop_flags = f;
- ctrl_ctx->add_flags &= ~drop_flag;
- new_add_flags = ctrl_ctx->add_flags;
+ f = le32_to_cpu(ctrl_ctx->add_flags) & ~drop_flag;
+ ctrl_ctx->add_flags = cpu_to_le32(f);
+ new_add_flags = f;
- last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags);
+ last_ctx = xhci_last_valid_endpoint(f);
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
/* Update the last valid endpoint context, if we deleted the last one */
- if ((slot_ctx->dev_info & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
- slot_ctx->dev_info &= ~LAST_CTX_MASK;
- slot_ctx->dev_info |= LAST_CTX(last_ctx);
+ f = le32_to_cpu(slot_ctx->dev_info);
+ if ((f & LAST_CTX_MASK) > LAST_CTX(last_ctx)) {
+ f &= ~LAST_CTX_MASK;
+ f |= LAST_CTX(last_ctx);
+ slot_ctx->dev_info = cpu_to_le32(f);
}
- new_slot_info = slot_ctx->dev_info;
+ new_slot_info = le32_to_cpu(slot_ctx->dev_info);
xhci_endpoint_zero(xhci, xhci->devs[udev->slot_id], ep);
@@ -1385,6 +1393,7 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
unsigned int last_ctx;
u32 new_add_flags, new_drop_flags, new_slot_info;
int ret = 0;
+ u32 f;
ret = xhci_check_args(hcd, udev, ep, 1, true, __func__);
if (ret <= 0) {
@@ -1414,7 +1423,8 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
/* If the HCD has already noted the endpoint is enabled,
* ignore this request.
*/
- if (ctrl_ctx->add_flags & xhci_get_endpoint_flag(&ep->desc)) {
+ if (le32_to_cpu(ctrl_ctx->add_flags) &
+ xhci_get_endpoint_flag(&ep->desc)) {
xhci_warn(xhci, "xHCI %s called with enabled ep %p\n",
__func__, ep);
return 0;
@@ -1432,8 +1442,9 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
return -ENOMEM;
}
- ctrl_ctx->add_flags |= added_ctxs;
- new_add_flags = ctrl_ctx->add_flags;
+ f = le32_to_cpu(ctrl_ctx->add_flags) | added_ctxs;
+ ctrl_ctx->add_flags = cpu_to_le32(f);
+ new_add_flags = f;
/* If xhci_endpoint_disable() was called for this endpoint, but the
* xHC hasn't been notified yet through the check_bandwidth() call,
@@ -1441,15 +1452,17 @@ int xhci_add_endpoint(struct usb_hcd *hcd, struct usb_device *udev,
* descriptors. We must drop and re-add this endpoint, so we leave the
* drop flags alone.
*/
- new_drop_flags = ctrl_ctx->drop_flags;
+ new_drop_flags = le32_to_cpu(ctrl_ctx->drop_flags);
slot_ctx = xhci_get_slot_ctx(xhci, in_ctx);
+ f = le32_to_cpu(slot_ctx->dev_info);
/* Update the last valid endpoint context, if we just added one past */
- if ((slot_ctx->dev_info & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
- slot_ctx->dev_info &= ~LAST_CTX_MASK;
- slot_ctx->dev_info |= LAST_CTX(last_ctx);
+ if ((f & LAST_CTX_MASK) < LAST_CTX(last_ctx)) {
+ f &= ~LAST_CTX_MASK;
+ f |= LAST_CTX(last_ctx);
+ slot_ctx->dev_info = cpu_to_le32(f);
}
- new_slot_info = slot_ctx->dev_info;
+ new_slot_info = f;
/* Store the usb_device pointer for later use */
ep->hcpriv = udev;
@@ -1469,6 +1482,7 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
int i;
+ u32 di;
/* When a device's add flag and drop flag are zero, any subsequent
* configure endpoint command will leave that endpoint's state
@@ -1479,9 +1493,9 @@ static void xhci_zero_in_ctx(struct xhci_hcd *xhci, struct xhci_virt_device *vir
ctrl_ctx->drop_flags = 0;
ctrl_ctx->add_flags = 0;
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
- slot_ctx->dev_info &= ~LAST_CTX_MASK;
+ di = le32_to_cpu(slot_ctx->dev_info) & ~LAST_CTX_MASK;
/* Endpoint 0 is always valid */
- slot_ctx->dev_info |= LAST_CTX(1);
+ slot_ctx->dev_info = cpu_to_le32(di |= LAST_CTX(1));
for (i = 1; i < 31; ++i) {
ep_ctx = xhci_get_ep_ctx(xhci, virt_dev->in_ctx, i);
ep_ctx->ep_info = 0;
@@ -1576,7 +1590,7 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
unsigned long flags;
struct xhci_container_ctx *in_ctx;
struct completion *cmd_completion;
- int *cmd_status;
+ u32 *cmd_status;
struct xhci_virt_device *virt_dev;
spin_lock_irqsave(&xhci->lock, flags);
@@ -1590,8 +1604,8 @@ static int xhci_configure_endpoint(struct xhci_hcd *xhci,
/* Enqueue pointer can be left pointing to the link TRB,
* we must handle that
*/
- if ((command->command_trb->link.control & TRB_TYPE_BITMASK)
- == TRB_TYPE(TRB_LINK))
+ if ((le32_to_cpu(command->command_trb->link.control)
+ & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
command->command_trb =
xhci->cmd_ring->enq_seg->next->trbs;
@@ -1667,14 +1681,13 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
/* See section 4.6.6 - A0 = 1; A1 = D0 = D1 = 0 */
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
- ctrl_ctx->add_flags |= SLOT_FLAG;
- ctrl_ctx->add_flags &= ~EP0_FLAG;
- ctrl_ctx->drop_flags &= ~SLOT_FLAG;
- ctrl_ctx->drop_flags &= ~EP0_FLAG;
+ ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
+ ctrl_ctx->add_flags &= cpu_to_le32(~EP0_FLAG);
+ ctrl_ctx->drop_flags &= cpu_to_le32(~(SLOT_FLAG | EP0_FLAG));
xhci_dbg(xhci, "New Input Control Context:\n");
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
xhci_dbg_ctx(xhci, virt_dev->in_ctx,
- LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
+ LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
ret = xhci_configure_endpoint(xhci, udev, NULL,
false, false);
@@ -1685,7 +1698,7 @@ int xhci_check_bandwidth(struct usb_hcd *hcd, struct usb_device *udev)
xhci_dbg(xhci, "Output context after successful config ep cmd:\n");
xhci_dbg_ctx(xhci, virt_dev->out_ctx,
- LAST_CTX_TO_EP_NUM(slot_ctx->dev_info));
+ LAST_CTX_TO_EP_NUM(le32_to_cpu(slot_ctx->dev_info)));
xhci_zero_in_ctx(xhci, virt_dev);
/* Install new rings and free or cache any old rings */
@@ -1735,10 +1748,10 @@ static void xhci_setup_input_ctx_for_config_ep(struct xhci_hcd *xhci,
{
struct xhci_input_control_ctx *ctrl_ctx;
ctrl_ctx = xhci_get_input_control_ctx(xhci, in_ctx);
- ctrl_ctx->add_flags = add_flags;
- ctrl_ctx->drop_flags = drop_flags;
+ ctrl_ctx->add_flags = cpu_to_le32(add_flags);
+ ctrl_ctx->drop_flags = cpu_to_le32(drop_flags);
xhci_slot_copy(xhci, in_ctx, out_ctx);
- ctrl_ctx->add_flags |= SLOT_FLAG;
+ ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
xhci_dbg(xhci, "Input Context:\n");
xhci_dbg_ctx(xhci, in_ctx, xhci_last_valid_endpoint(add_flags));
@@ -1767,7 +1780,7 @@ static void xhci_setup_input_ctx_for_quirk(struct xhci_hcd *xhci,
deq_state->new_deq_ptr);
return;
}
- ep_ctx->deq = addr | deq_state->new_cycle_state;
+ ep_ctx->deq = cpu_to_le64(addr | deq_state->new_cycle_state);
added_ctxs = xhci_get_endpoint_flag_from_index(ep_index);
xhci_setup_input_ctx_for_config_ep(xhci, xhci->devs[slot_id]->in_ctx,
@@ -2322,8 +2335,8 @@ int xhci_discover_or_reset_device(struct usb_hcd *hcd, struct usb_device *udev)
/* Enqueue pointer can be left pointing to the link TRB,
* we must handle that
*/
- if ((reset_device_cmd->command_trb->link.control & TRB_TYPE_BITMASK)
- == TRB_TYPE(TRB_LINK))
+ if ((le32_to_cpu(reset_device_cmd->command_trb->link.control)
+ & TRB_TYPE_BITMASK) == TRB_TYPE(TRB_LINK))
reset_device_cmd->command_trb =
xhci->cmd_ring->enq_seg->next->trbs;
@@ -2596,10 +2609,10 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
temp_64 = xhci_read_64(xhci, &xhci->op_regs->dcbaa_ptr);
xhci_dbg(xhci, "Op regs DCBAA ptr = %#016llx\n", temp_64);
xhci_dbg(xhci, "Slot ID %d dcbaa entry @%p = %#016llx\n",
- udev->slot_id,
- &xhci->dcbaa->dev_context_ptrs[udev->slot_id],
- (unsigned long long)
- xhci->dcbaa->dev_context_ptrs[udev->slot_id]);
+ udev->slot_id,
+ &xhci->dcbaa->dev_context_ptrs[udev->slot_id],
+ (unsigned long long)
+ le64_to_cpu(xhci->dcbaa->dev_context_ptrs[udev->slot_id]));
xhci_dbg(xhci, "Output Context DMA address = %#08llx\n",
(unsigned long long)virt_dev->out_ctx->dma);
xhci_dbg(xhci, "Slot ID %d Input Context:\n", udev->slot_id);
@@ -2613,7 +2626,8 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->out_ctx);
/* Use kernel assigned address for devices; store xHC assigned
* address locally. */
- virt_dev->address = (slot_ctx->dev_state & DEV_ADDR_MASK) + 1;
+ virt_dev->address = (le32_to_cpu(slot_ctx->dev_state) & DEV_ADDR_MASK)
+ + 1;
/* Zero the input context control for later use */
ctrl_ctx = xhci_get_input_control_ctx(xhci, virt_dev->in_ctx);
ctrl_ctx->add_flags = 0;
@@ -2657,16 +2671,16 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
spin_lock_irqsave(&xhci->lock, flags);
xhci_slot_copy(xhci, config_cmd->in_ctx, vdev->out_ctx);
ctrl_ctx = xhci_get_input_control_ctx(xhci, config_cmd->in_ctx);
- ctrl_ctx->add_flags |= SLOT_FLAG;
+ ctrl_ctx->add_flags |= cpu_to_le32(SLOT_FLAG);
slot_ctx = xhci_get_slot_ctx(xhci, config_cmd->in_ctx);
- slot_ctx->dev_info |= DEV_HUB;
+ slot_ctx->dev_info |= cpu_to_le32(DEV_HUB);
if (tt->multi)
- slot_ctx->dev_info |= DEV_MTT;
+ slot_ctx->dev_info |= cpu_to_le32(DEV_MTT);
if (xhci->hci_version > 0x95) {
xhci_dbg(xhci, "xHCI version %x needs hub "
"TT think time and number of ports\n",
(unsigned int) xhci->hci_version);
- slot_ctx->dev_info2 |= XHCI_MAX_PORTS(hdev->maxchild);
+ slot_ctx->dev_info2 |= cpu_to_le32(XHCI_MAX_PORTS(hdev->maxchild));
/* Set TT think time - convert from ns to FS bit times.
* 0 = 8 FS bit times, 1 = 16 FS bit times,
* 2 = 24 FS bit times, 3 = 32 FS bit times.
@@ -2674,7 +2688,7 @@ int xhci_update_hub_device(struct usb_hcd *hcd, struct usb_device *hdev,
think_time = tt->think_time;
if (think_time != 0)
think_time = (think_time / 666) - 1;
- slot_ctx->tt_info |= TT_THINK_TIME(think_time);
+ slot_ctx->tt_info |= cpu_to_le32(TT_THINK_TIME(think_time));
} else {
xhci_dbg(xhci, "xHCI version %x doesn't need hub "
"TT think time or number of ports\n",
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 711de25..7970f6b 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -56,13 +56,13 @@
* @run_regs_off: RTSOFF - Runtime register space offset
*/
struct xhci_cap_regs {
- u32 hc_capbase;
- u32 hcs_params1;
- u32 hcs_params2;
- u32 hcs_params3;
- u32 hcc_params;
- u32 db_off;
- u32 run_regs_off;
+ __le32 hc_capbase;
+ __le32 hcs_params1;
+ __le32 hcs_params2;
+ __le32 hcs_params3;
+ __le32 hcc_params;
+ __le32 db_off;
+ __le32 run_regs_off;
/* Reserved up to (CAPLENGTH - 0x1C) */
};
@@ -154,26 +154,26 @@ struct xhci_cap_regs {
* devices.
*/
struct xhci_op_regs {
- u32 command;
- u32 status;
- u32 page_size;
- u32 reserved1;
- u32 reserved2;
- u32 dev_notification;
- u64 cmd_ring;
+ __le32 command;
+ __le32 status;
+ __le32 page_size;
+ __le32 reserved1;
+ __le32 reserved2;
+ __le32 dev_notification;
+ __le64 cmd_ring;
/* rsvd: offset 0x20-2F */
- u32 reserved3[4];
- u64 dcbaa_ptr;
- u32 config_reg;
+ __le32 reserved3[4];
+ __le64 dcbaa_ptr;
+ __le32 config_reg;
/* rsvd: offset 0x3C-3FF */
- u32 reserved4[241];
+ __le32 reserved4[241];
/* port 1 registers, which serve as a base address for other ports */
- u32 port_status_base;
- u32 port_power_base;
- u32 port_link_base;
- u32 reserved5;
+ __le32 port_status_base;
+ __le32 port_power_base;
+ __le32 port_link_base;
+ __le32 reserved5;
/* registers for ports 2-255 */
- u32 reserved6[NUM_PORT_REGS*254];
+ __le32 reserved6[NUM_PORT_REGS*254];
};
/* USBCMD - USB command - command bitmasks */
@@ -378,12 +378,12 @@ struct xhci_op_regs {
* updates the dequeue pointer.
*/
struct xhci_intr_reg {
- u32 irq_pending;
- u32 irq_control;
- u32 erst_size;
- u32 rsvd;
- u64 erst_base;
- u64 erst_dequeue;
+ __le32 irq_pending;
+ __le32 irq_control;
+ __le32 erst_size;
+ __le32 rsvd;
+ __le64 erst_base;
+ __le64 erst_dequeue;
};
/* irq_pending bitmasks */
@@ -428,8 +428,8 @@ struct xhci_intr_reg {
* or larger accesses"
*/
struct xhci_run_regs {
- u32 microframe_index;
- u32 rsvd[7];
+ __le32 microframe_index;
+ __le32 rsvd[7];
struct xhci_intr_reg ir_set[128];
};
@@ -443,7 +443,7 @@ struct xhci_run_regs {
* Section 5.6
*/
struct xhci_doorbell_array {
- u32 doorbell[256];
+ __le32 doorbell[256];
};
#define DB_VALUE(ep, stream) ((((ep) + 1) & 0xff) | ((stream) << 16))
@@ -500,12 +500,12 @@ struct xhci_container_ctx {
* reserved at the end of the slot context for HC internal use.
*/
struct xhci_slot_ctx {
- u32 dev_info;
- u32 dev_info2;
- u32 tt_info;
- u32 dev_state;
+ __le32 dev_info;
+ __le32 dev_info2;
+ __le32 tt_info;
+ __le32 dev_state;
/* offset 0x10 to 0x1f reserved for HC internal use */
- u32 reserved[4];
+ __le32 reserved[4];
};
/* dev_info bitmasks */
@@ -576,12 +576,12 @@ struct xhci_slot_ctx {
* reserved at the end of the endpoint context for HC internal use.
*/
struct xhci_ep_ctx {
- u32 ep_info;
- u32 ep_info2;
- u64 deq;
- u32 tx_info;
+ __le32 ep_info;
+ __le32 ep_info2;
+ __le64 deq;
+ __le32 tx_info;
/* offset 0x14 - 0x1f reserved for HC internal use */
- u32 reserved[3];
+ __le32 reserved[3];
};
/* ep_info bitmasks */
@@ -656,9 +656,9 @@ struct xhci_ep_ctx {
* @add_context: set the bit of the endpoint context you want to enable
*/
struct xhci_input_control_ctx {
- u32 drop_flags;
- u32 add_flags;
- u32 rsvd2[6];
+ __le32 drop_flags;
+ __le32 add_flags;
+ __le32 rsvd2[6];
};
/* Represents everything that is needed to issue a command on the command ring.
@@ -684,9 +684,9 @@ struct xhci_command {
struct xhci_stream_ctx {
/* 64-bit stream ring address, cycle state, and stream type */
- u64 stream_ring;
+ __le64 stream_ring;
/* offset 0x14 - 0x1f reserved for HC internal use */
- u32 reserved[2];
+ __le32 reserved[2];
};
/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */
@@ -799,7 +799,7 @@ struct xhci_virt_device {
*/
struct xhci_device_context_array {
/* 64-bit device addresses; we only write 32-bit addresses */
- u64 dev_context_ptrs[MAX_HC_SLOTS];
+ __le64 dev_context_ptrs[MAX_HC_SLOTS];
/* private xHCD pointers */
dma_addr_t dma;
};
@@ -812,10 +812,10 @@ struct xhci_device_context_array {
struct xhci_transfer_event {
/* 64-bit buffer address, or immediate data */
- u64 buffer;
- u32 transfer_len;
+ __le64 buffer;
+ __le32 transfer_len;
/* This field is interpreted differently based on the type of TRB */
- u32 flags;
+ __le32 flags;
};
/** Transfer Event bit fields **/
@@ -894,9 +894,9 @@ struct xhci_transfer_event {
struct xhci_link_trb {
/* 64-bit segment pointer*/
- u64 segment_ptr;
- u32 intr_target;
- u32 control;
+ __le64 segment_ptr;
+ __le32 intr_target;
+ __le32 control;
};
/* control bitfields */
@@ -905,9 +905,9 @@ struct xhci_link_trb {
/* Command completion event TRB */
struct xhci_event_cmd {
/* Pointer to command TRB, or the value passed by the event data trb */
- u64 cmd_trb;
- u32 status;
- u32 flags;
+ __le64 cmd_trb;
+ __le32 status;
+ __le32 flags;
};
/* flags bitmasks */
@@ -966,7 +966,7 @@ struct xhci_event_cmd {
#define TRB_SIA (1<<31)
struct xhci_generic_trb {
- u32 field[4];
+ __le32 field[4];
};
union xhci_trb {
@@ -1114,10 +1114,10 @@ struct xhci_ring {
struct xhci_erst_entry {
/* 64-bit event ring segment address */
- u64 seg_addr;
- u32 seg_size;
+ __le64 seg_addr;
+ __le32 seg_size;
/* Set to zero */
- u32 rsvd;
+ __le32 rsvd;
};
struct xhci_erst {
@@ -1281,10 +1281,10 @@ struct xhci_hcd {
/* Is each xHCI roothub port a USB 3.0, USB 2.0, or USB 1.1 port? */
u8 *port_array;
/* Array of pointers to USB 3.0 PORTSC registers */
- u32 __iomem **usb3_ports;
+ __le32 __iomem **usb3_ports;
unsigned int num_usb3_ports;
/* Array of pointers to USB 2.0 PORTSC registers */
- u32 __iomem **usb2_ports;
+ __le32 __iomem **usb2_ports;
unsigned int num_usb2_ports;
};
@@ -1317,12 +1317,12 @@ static inline struct usb_hcd *xhci_to_hcd(struct xhci_hcd *xhci)
/* TODO: copied from ehci.h - can be refactored? */
/* xHCI spec says all registers are little endian */
static inline unsigned int xhci_readl(const struct xhci_hcd *xhci,
- __u32 __iomem *regs)
+ __le32 __iomem *regs)
{
return readl(regs);
}
static inline void xhci_writel(struct xhci_hcd *xhci,
- const unsigned int val, __u32 __iomem *regs)
+ const unsigned int val, __le32 __iomem *regs)
{
xhci_dbg(xhci,
"`MEM_WRITE_DWORD(3'b000, 32'h%p, 32'h%0x, 4'hf);\n",
@@ -1340,7 +1340,7 @@ static inline void xhci_writel(struct xhci_hcd *xhci,
* the high dword, and write order is irrelevant.
*/
static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
- __u64 __iomem *regs)
+ __le64 __iomem *regs)
{
__u32 __iomem *ptr = (__u32 __iomem *) regs;
u64 val_lo = readl(ptr);
@@ -1348,7 +1348,7 @@ static inline u64 xhci_read_64(const struct xhci_hcd *xhci,
return val_lo + (val_hi << 32);
}
static inline void xhci_write_64(struct xhci_hcd *xhci,
- const u64 val, __u64 __iomem *regs)
+ const u64 val, __le64 __iomem *regs)
{
__u32 __iomem *ptr = (__u32 __iomem *) regs;
u32 val_lo = lower_32_bits(val);
--
1.7.0.4
^ permalink raw reply related
* [PATCH 2/5] xhci: Extend debug messages
From: Matt Evans @ 2011-03-25 7:43 UTC (permalink / raw)
To: sarah.a.sharp; +Cc: linuxppc-dev, linux-usb
Add more debug to print queued transfers, show control intentions and
modify an existing message to hexify address output.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
drivers/usb/host/xhci-dbg.c | 2 +-
drivers/usb/host/xhci-hub.c | 3 +++
drivers/usb/host/xhci-ring.c | 5 +++++
3 files changed, 9 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/host/xhci-dbg.c b/drivers/usb/host/xhci-dbg.c
index 2e04861..905f3bf 100644
--- a/drivers/usb/host/xhci-dbg.c
+++ b/drivers/usb/host/xhci-dbg.c
@@ -278,7 +278,7 @@ void xhci_debug_trb(struct xhci_hcd *xhci, union xhci_trb *trb)
* FIXME: look at flags to figure out if it's an address or if
* the data is directly in the buffer field.
*/
- xhci_dbg(xhci, "DMA address or buffer contents= %llu\n", address);
+ xhci_dbg(xhci, "DMA address or buffer contents= 0x%llx\n", address);
break;
case TRB_TYPE(TRB_COMPLETION):
address = le64_to_cpu(trb->event_cmd.cmd_trb);
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index ae1d24c..768fd6e 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -389,6 +389,9 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
}
bus_state = &xhci->bus_state[hcd_index(hcd)];
+ xhci_dbg(xhci, "%s(%04x, %04x, %04x, %p, %04x);\n", __func__,
+ typeReq, wValue, wIndex, buf, wLength);
+
spin_lock_irqsave(&xhci->lock, flags);
switch (typeReq) {
case GetHubStatus:
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 3898f22..45f3b77 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2336,6 +2336,11 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
trb->field[1] = cpu_to_le32(field2);
trb->field[2] = cpu_to_le32(field3);
trb->field[3] = cpu_to_le32(field4);
+
+ xhci_dbg(xhci, "queue_trb @%llx %08x %08x %08x %08x\n",
+ xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue),
+ le32_to_cpu(trb->field[0]), le32_to_cpu(trb->field[1]),
+ le32_to_cpu(trb->field[2]), le32_to_cpu(trb->field[3]));
inc_enq(xhci, ring, consumer, more_trbs_coming);
}
--
1.7.0.4
^ permalink raw reply related
* [PATCH 3/5] xhci: Add rmb() between reading event validity & event data access.
From: Matt Evans @ 2011-03-25 7:44 UTC (permalink / raw)
To: sarah.a.sharp; +Cc: linuxppc-dev, linux-usb
On weakly-ordered systems, the reading of an event's content must occur
after reading the event's validity.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
drivers/usb/host/xhci-ring.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 45f3b77..b46efd9 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2151,7 +2151,7 @@ static void xhci_handle_event(struct xhci_hcd *xhci)
return;
}
xhci_dbg(xhci, "%s - OS owns TRB\n", __func__);
-
+ rmb();
/* FIXME: Handle more event types. */
switch ((le32_to_cpu(event->event_cmd.flags) & TRB_TYPE_BITMASK)) {
case TRB_TYPE(TRB_COMPLETION):
--
1.7.0.4
^ permalink raw reply related
* [PATCH 4/5] xhci: Add an assertion to check for virt_dev=0 bug.
From: Matt Evans @ 2011-03-25 7:44 UTC (permalink / raw)
To: sarah.a.sharp; +Cc: linuxppc-dev, linux-usb
During a "plug-unplug" stress test on an NEC xHCI card, a null pointer
dereference was observed. xhci_address_device() dereferenced a null
virt_dev (possibly an erroneous udev->slot_id?); this patch adds a WARN_ON &
message to aid debug if it can be recreated.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
drivers/usb/host/xhci.c | 11 +++++++++++
1 files changed, 11 insertions(+), 0 deletions(-)
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 88e6298..7d43456 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -2542,6 +2542,17 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
virt_dev = xhci->devs[udev->slot_id];
+ if (WARN_ON(!virt_dev)) {
+ /*
+ * In plug/unplug torture test with an NEC controller,
+ * a zero-dereference was observed once due to virt_dev = 0.
+ * Print useful debug rather than crash if it is observed again!
+ */
+ xhci_warn(xhci, "Virt dev invalid for slot_id 0x%x!\n",
+ udev->slot_id);
+ return -EINVAL;
+ }
+
slot_ctx = xhci_get_slot_ctx(xhci, virt_dev->in_ctx);
/*
* If this is the first Set Address since device plug-in or
--
1.7.0.4
^ permalink raw reply related
* [PATCH 5/5] xhci: Remove recursive call to xhci_handle_event
From: Matt Evans @ 2011-03-25 7:44 UTC (permalink / raw)
To: sarah.a.sharp; +Cc: linuxppc-dev, linux-usb
Make the caller loop while there are events to handle, instead.
Signed-off-by: Matt Evans <matt@ozlabs.org>
---
drivers/usb/host/xhci-ring.c | 16 +++++++++-------
1 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index b46efd9..97bedd6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -2131,7 +2131,7 @@ cleanup:
* This function handles all OS-owned events on the event ring. It may drop
* xhci->lock between event processing (e.g. to pass up port status changes).
*/
-static void xhci_handle_event(struct xhci_hcd *xhci)
+static int xhci_handle_event(struct xhci_hcd *xhci)
{
union xhci_trb *event;
int update_ptrs = 1;
@@ -2140,7 +2140,7 @@ static void xhci_handle_event(struct xhci_hcd *xhci)
xhci_dbg(xhci, "In %s\n", __func__);
if (!xhci->event_ring || !xhci->event_ring->dequeue) {
xhci->error_bitmask |= 1 << 1;
- return;
+ return 0;
}
event = xhci->event_ring->dequeue;
@@ -2148,7 +2148,7 @@ static void xhci_handle_event(struct xhci_hcd *xhci)
if ((le32_to_cpu(event->event_cmd.flags) & TRB_CYCLE) !=
xhci->event_ring->cycle_state) {
xhci->error_bitmask |= 1 << 2;
- return;
+ return 0;
}
xhci_dbg(xhci, "%s - OS owns TRB\n", __func__);
rmb();
@@ -2187,15 +2187,17 @@ static void xhci_handle_event(struct xhci_hcd *xhci)
if (xhci->xhc_state & XHCI_STATE_DYING) {
xhci_dbg(xhci, "xHCI host dying, returning from "
"event handler.\n");
- return;
+ return 0;
}
if (update_ptrs)
/* Update SW event ring dequeue pointer */
inc_deq(xhci, xhci->event_ring, true);
- /* Are there more items on the event ring? */
- xhci_handle_event(xhci);
+ /* Are there more items on the event ring? Caller will call us again to
+ * check.
+ */
+ return 1;
}
/*
@@ -2277,7 +2279,7 @@ hw_died:
/* FIXME this should be a delayed service routine
* that clears the EHB.
*/
- xhci_handle_event(xhci);
+ while (xhci_handle_event(xhci)) {};
temp_64 = xhci_read_64(xhci, &xhci->ir_set->erst_dequeue);
/* If necessary, update the HW's version of the event ring deq ptr. */
--
1.7.0.4
^ permalink raw reply related
* Re: [BUG] pgprot_noncached() is -NOT- safe for mapping vmalloc buffers into userspace
From: Takashi Iwai @ 2011-03-25 8:01 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-arch, linuxppc-dev, linux-kernel@vger.kernel.org,
Matthew Evans
In-Reply-To: <1301005008.2402.453.camel@pasglop>
At Fri, 25 Mar 2011 09:16:48 +1100,
Benjamin Herrenschmidt wrote:
>
> Hi Takashi !
>
> While working on endian-fixing xHCI with Matt (CC), we discovered the
> source of our problems with usb-audio on a board we were working on.
>
> c32d977b8157bf67cdf47729ce7dd054a26eb534
> "ALSA: pcm - Call pgprot_noncached() for vmalloc'ed buffers"
>
> I'm afraid that this is totally bogus :-)
>
> I don't know on what arch it is safe to have the same memory be mapped
> cachable in the kernel (and accessed via this cached mapping) and
> non-cachable in userspace, but I can confidently say that wherever it
> works it does so by accident.
>
> In the case of usb-audio, what we observed is that the user application
> was writing samples using an uncached mapping, so directly to memory,
> which does -not- invalidate conflicting cache lines on the way, an the
> kernel would then memcpy those data to the USB buffers using a cached
> mapping (vmalloc) and essentially get stale stuff from the cache instead
> of the real samples.
>
> Worse, on some processors, it's actually -illegal- to create (and even
> more to -access-) a conflicting mapping of a page of memory, ie, have it
> mapped cached somewhere and uncached somewhere else. It will lockup some
> processors and afaik, some x86 as well.
>
> In fact, cache coherent architectures often don't support mapping memory
> uncached -at-all- so something like snd_pcm_lib_mmap_noncached()
> shouldn't exist, or at least be under arch control. There's no case
> where it's "always safe". There will almost always be a cache alias in
> the linear mapping unless special arch specific sauce has been applied.
I see. I'll take your removal patch.
It should be applied to stable kernel, too, right?
> Now, there's another problem on top of that, which is that
> snd_pcm_default_mmap() will not work properly the "other way around" on
> powerpc, where the mapping -needs- to be uncached bcs you are running on
> a non cache coherent embedded CPU and trying to mmap DMA memory, but
> that's something that needs fixing inside powerpc by properly defining
> dma_mmap_coherent() & ARCH_HAS_DMA_MMAP_COHERENT (I thought we had added
> it a while back but it's not upstream, patch must have got lost).
Mea culpa. I moved to a different team and have had little time for
the upstream development since then...
> We
> must also make sure we don't go down that path for vmalloc memory
> though.
Yes.
Your patch looks good. Thanks for taking care of this!
Takashi
^ permalink raw reply
* Re: [PATCH] powerpc: Implement dma_mmap_coherent()
From: Takashi Iwai @ 2011-03-25 8:06 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1301035806.2402.470.camel@pasglop>
At Fri, 25 Mar 2011 17:50:06 +1100,
Benjamin Herrenschmidt wrote:
>
> This is used by Alsa to mmap buffers allocated with dma_alloc_coherent()
> into userspace. We need a special variant to handle machines with
> non-coherent DMAs as those buffers have "special" virt addresses and
> require non-cachable mappings
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> ---
>
> Dunno if anybody with CONFIG_NOT_COHERENT_CACHE has some audio device
> that uses dma buffers (ie not usb-audio) and wants to try that out...
> should fix a long standing problem.
>
> arch/powerpc/include/asm/dma-mapping.h | 7 +++++++
> arch/powerpc/kernel/dma.c | 18 ++++++++++++++++++
> arch/powerpc/mm/dma-noncoherent.c | 20 ++++++++++++++++++++
> 3 files changed, 45 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
> index 6d2416a..41e0eb7 100644
> --- a/arch/powerpc/include/asm/dma-mapping.h
> +++ b/arch/powerpc/include/asm/dma-mapping.h
> @@ -42,6 +42,7 @@ extern void __dma_free_coherent(size_t size, void *vaddr);
> extern void __dma_sync(void *vaddr, size_t size, int direction);
> extern void __dma_sync_page(struct page *page, unsigned long offset,
> size_t size, int direction);
> +extern unsigned long __dma_get_coherent_pfn(void *cpu_addr);
>
> #else /* ! CONFIG_NOT_COHERENT_CACHE */
> /*
> @@ -52,6 +53,7 @@ extern void __dma_sync_page(struct page *page, unsigned long offset,
> #define __dma_free_coherent(size, addr) ((void)0)
> #define __dma_sync(addr, size, rw) ((void)0)
> #define __dma_sync_page(pg, off, sz, rw) ((void)0)
> +#define __dma_get_coherent_pfn(cpu_addr) (0)
Just nitpicking: shouldn't we define some real thing like
page_to_pfn(virt_to_page(cpu_addr))
or put something to trigger an error? Setting a bogus zero can be
easily overlooked, I'm afraid.
thanks,
Takashi
>
> #endif /* ! CONFIG_NOT_COHERENT_CACHE */
>
> @@ -198,6 +200,11 @@ static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
> #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
> #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
>
> +extern int dma_mmap_coherent(struct device *, struct vm_area_struct *,
> + void *, dma_addr_t, size_t);
> +#define ARCH_HAS_DMA_MMAP_COHERENT
> +
> +
> static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
> enum dma_data_direction direction)
> {
> diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
> index cf02cad..0f52235 100644
> --- a/arch/powerpc/kernel/dma.c
> +++ b/arch/powerpc/kernel/dma.c
> @@ -179,3 +179,21 @@ static int __init dma_init(void)
> return 0;
> }
> fs_initcall(dma_init);
> +
> +int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
> + void *cpu_addr, dma_addr_t handle, size_t size)
> +{
> + unsigned long pfn;
> +
> +#ifdef CONFIG_NOT_COHERENT_CACHE
> + vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
> + pfn = __dma_get_coherent_pfn(cpu_addr);
> +#else
> + pfn = page_to_pfn(virt_to_page(cpu_addr));
> +#endif
> + return remap_pfn_range(vma, vma->vm_start,
> + pfn + vma->vm_pgoff,
> + vma->vm_end - vma->vm_start,
> + vma->vm_page_prot);
> +}
> +
> diff --git a/arch/powerpc/mm/dma-noncoherent.c b/arch/powerpc/mm/dma-noncoherent.c
> index 757c0be..174b10a 100644
> --- a/arch/powerpc/mm/dma-noncoherent.c
> +++ b/arch/powerpc/mm/dma-noncoherent.c
> @@ -399,3 +399,23 @@ void __dma_sync_page(struct page *page, unsigned long offset,
> #endif
> }
> EXPORT_SYMBOL(__dma_sync_page);
> +
> +/*
> + * Return the PFN for a given cpu virtual address returned by
> + * __dma_alloc_coherent. This is used by dma_mmap_coherent()
> + */
> +unsigned long __dma_get_coherent_pfn(void *cpu_addr)
> +{
> + /* This should always be populated, so we don't test every
> + * level. If that fails, we'll have a nice crash which
> + * will be as good as a BUG_ON()
> + */
> + pgd_t *pgd = pgd_offset_k(cpu_addr);
> + pud_t *pud = pud_offset(pgd, cpu_addr);
> + pmd_t *pmd = pmd_offset(pud, cpu_addr);
> + pte_t *ptep = pte_offset_kernel(pmd, cpu_addr);
> +
> + if (pte_none(*ptep) || !pte_present(*ptep))
> + return 0;
> + return pte_pfn(*ptep);
> +}
>
>
>
^ permalink raw reply
* Re: hvc_console: Don't access hvc_task if not initialised
From: Amit Shah @ 2011-03-25 8:47 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Rusty Russell, linux-kernel, greg
In-Reply-To: <hvc-kick-notask@mdm.bga.com>
On (Thu) 24 Mar 2011 [08:58:04], Milton Miller wrote:
> On Thu, 24 Mar 2011 07:29:58 -0000, Amit Shah wrote:
> > hvc_open() can be called without having any backing device. This
> > results in a call to hvc_kick() which calls wake_up_process on a NULL
> > pointer.
>
> How is hvc_open called without a hvc_driver registered to the tty layer?
This gets reproduced in a couple of scenarios, I'm trying to get more
information.
> > Ensure hvc is initialised by checking for a non-NULL hvc_task
> > before waking up the hvc thread.
>
> No if the task is missing the subsystem is really stuck. Put a check
> in open and refuse to open.
>
> >
> > This was found by an autotest run for virtio_console without having a
> > console backend.
> >
>
> stack trace please
Yes, should have included that:
BUG: unable to handle kernel NULL pointer dereference at 0000000000000008
IP: [<ffffffff8104fef2>] task_rq_lock+0x42/0xa0
PGD 1d66a067 PUD 1d598067 PMD 0
Oops: 0000 [#1] SMP
last sysfs file: /sys/devices/pci0000:00/0000:00:04.0/virtio1/virtio-ports/vport0p0/name
CPU 0
Modules linked in: virtio_console virtio_net i2c_piix4 i2c_core ext4
mbcache jbd2 sr_mod cdrom virtio_blk pata_acpi ata_generic ata_piix
virtio_pci virtio_ring virtio dm_mod [last unloaded: scsi_wait_scan]
Modules linked in: virtio_console virtio_net i2c_piix4 i2c_core ext4
mbcache jbd2 sr_mod cdrom virtio_blk pata_acpi ata_generic ata_piix
virtio_pci virtio_ring virtio dm_mod [last unloaded: scsi_wait_scan]
Pid: 672, comm: console_check Not tainted 2.6.32-125.el6.x86_64 #1 KVM
RIP: 0010:[<ffffffff8104fef2>] [<ffffffff8104fef2>] task_rq_lock+0x42/0xa0
RSP: 0018:ffff880017cbbb98 EFLAGS: 00010082
RAX: 0000000000000282 RBX: 0000000000015f40 RCX: 0000000000000002
RDX: 0000000000000282 RSI: ffff880017cbbbf0 RDI: 0000000000000000
RBP: ffff880017cbbbb8 R08: ffff88001bf39208 R09: ffff88001d67a000
R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000
R13: ffff880017cbbbf0 R14: 0000000000000000 R15: 000000000000000f
FS: 00007f3592683700(0000) GS:ffff880002000000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 000000008005003b
CR2: 0000000000000008 CR3: 000000001d595000 CR4: 00000000000006f0
DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
DR3: 0000000000000000 DR6: 00000000ffff0ff0 DR7: 0000000000000400
Process console_check (pid: 672, threadinfo ffff880017cba000, task ffff88001f5fe100)
Stack:
0000000000000000 ffff88001bf39000 0000000000000000 0000000000000000
<0> ffff880017cbbc28 ffffffff8105c74c ffff88001d5966a0 0000000000008800
<0> ffff880017cbbbe8 ffffffff813081c1 ffff880017cbbc28 0000000000000282
Call Trace:
[<ffffffff8105c74c>] try_to_wake_up+0x3c/0x400
[<ffffffff813081c1>] ? tty_ldisc_enable+0x31/0x40
[<ffffffff8105cb65>] wake_up_process+0x15/0x20
[<ffffffff8131a10f>] hvc_kick+0x1f/0x30
[<ffffffff8131a58a>] hvc_open+0xca/0x120
[<ffffffff81302ba1>] tty_open+0x211/0x510
[<ffffffff811754b5>] chrdev_open+0x125/0x230
[<ffffffff81175390>] ? chrdev_open+0x0/0x230
[<ffffffff8116e70a>] __dentry_open+0x10a/0x360
[<ffffffff8120d022>] ? selinux_inode_permission+0x72/0xb0
[<ffffffff812050ff>] ? security_inode_permission+0x1f/0x30
[<ffffffff8116ea74>] nameidata_to_filp+0x54/0x70
[<ffffffff811816b0>] do_filp_open+0x700/0xd90
[<ffffffff810cfd42>] ? audit_alloc_name+0x62/0x100
[<ffffffff8118fd20>] ? mntput_no_expire+0x30/0x110
[<ffffffff8118dd12>] ? alloc_fd+0x92/0x160
[<ffffffff8116e4b9>] do_sys_open+0x69/0x140
[<ffffffff8116e5d0>] sys_open+0x20/0x30
[<ffffffff8100b172>] system_call_fastpath+0x16/0x1b
Code: 89 74 24 18 0f 1f 44 00 00 48 c7 c3 40 5f 01 00 49 89 fc 49 89
f5 9c 58 0f 1f 44 00 00 48 89 c2 fa 66 0f 1f 44 00 00 49 89 55 00 <49>
8b 44 24 08 49 89 de 8b 40 18 4c 03 34 c5 40 46 b9 81 4c 89
RIP [<ffffffff8104fef2>] task_rq_lock+0x42/0xa0
RSP <ffff880017cbbb98>
CR2: 0000000000000008
---[ end trace a6f40a29150796da ]---
Amit
^ permalink raw reply
* Early kernel debugging
From: Guillaume Dargaud @ 2011-03-25 8:50 UTC (permalink / raw)
To: linuxppc-dev
Hello all,
what can you do when the kernel you try to run stops before printing anything on the console ?
I tried enabling the 'early printk' option, but still I get nothing.
I posted something about it in the 'Booting with ramdisk in kernel' message and I haven't improved the situation since
then, although I found the CONFIG_BLK_DEV_RAM option.
--
Guillaume Dargaud
http://www.gdargaud.net/
"Freedom is just chaos, with better lighting."
^ permalink raw reply
* Re: [PATCH] powerpc: Implement dma_mmap_coherent()
From: Benjamin Herrenschmidt @ 2011-03-25 9:11 UTC (permalink / raw)
To: Takashi Iwai; +Cc: linuxppc-dev
In-Reply-To: <s5h62r7vd2w.wl%tiwai@suse.de>
On Fri, 2011-03-25 at 09:06 +0100, Takashi Iwai wrote:
> > @@ -52,6 +53,7 @@ extern void __dma_sync_page(struct page *page,
> unsigned long offset,
> > #define __dma_free_coherent(size, addr) ((void)0)
> > #define __dma_sync(addr, size, rw) ((void)0)
> > #define __dma_sync_page(pg, off, sz, rw) ((void)0)
> > +#define __dma_get_coherent_pfn(cpu_addr) (0)
>
> Just nitpicking: shouldn't we define some real thing like
> page_to_pfn(virt_to_page(cpu_addr))
> or put something to trigger an error? Setting a bogus zero can be
> easily overlooked, I'm afraid.
Yes, all those variants are bogus if you noticed :-) The trick is that
they aren't actually called when CONFIG_NOT_COHERENT_CACHE is not set
anyways, with the exception of __dma_sync(), so I want to just remove
them all. But I'll do that in a separate patch.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc: Implement dma_mmap_coherent()
From: Takashi Iwai @ 2011-03-25 9:13 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1301044317.2402.475.camel@pasglop>
At Fri, 25 Mar 2011 20:11:57 +1100,
Benjamin Herrenschmidt wrote:
>
> On Fri, 2011-03-25 at 09:06 +0100, Takashi Iwai wrote:
> > > @@ -52,6 +53,7 @@ extern void __dma_sync_page(struct page *page,
> > unsigned long offset,
> > > #define __dma_free_coherent(size, addr) ((void)0)
> > > #define __dma_sync(addr, size, rw) ((void)0)
> > > #define __dma_sync_page(pg, off, sz, rw) ((void)0)
> > > +#define __dma_get_coherent_pfn(cpu_addr) (0)
> >
> > Just nitpicking: shouldn't we define some real thing like
> > page_to_pfn(virt_to_page(cpu_addr))
> > or put something to trigger an error? Setting a bogus zero can be
> > easily overlooked, I'm afraid.
>
> Yes, all those variants are bogus if you noticed :-) The trick is that
> they aren't actually called when CONFIG_NOT_COHERENT_CACHE is not set
> anyways, with the exception of __dma_sync(), so I want to just remove
> them all. But I'll do that in a separate patch.
OK, that makes sense.
thanks,
Takashi
^ permalink raw reply
* Re: [BUG] pgprot_noncached() is -NOT- safe for mapping vmalloc buffers into userspace
From: Benjamin Herrenschmidt @ 2011-03-25 9:15 UTC (permalink / raw)
To: Takashi Iwai
Cc: linux-arch, linuxppc-dev, linux-kernel@vger.kernel.org,
Matthew Evans
In-Reply-To: <s5h8vw3vdb1.wl%tiwai@suse.de>
On Fri, 2011-03-25 at 09:01 +0100, Takashi Iwai wrote:
> > In fact, cache coherent architectures often don't support mapping memory
> > uncached -at-all- so something like snd_pcm_lib_mmap_noncached()
> > shouldn't exist, or at least be under arch control. There's no case
> > where it's "always safe". There will almost always be a cache alias in
> > the linear mapping unless special arch specific sauce has been applied.
>
> I see. I'll take your removal patch.
> It should be applied to stable kernel, too, right?
I suppose so :-)
> > Now, there's another problem on top of that, which is that
> > snd_pcm_default_mmap() will not work properly the "other way around" on
> > powerpc, where the mapping -needs- to be uncached bcs you are running on
> > a non cache coherent embedded CPU and trying to mmap DMA memory, but
> > that's something that needs fixing inside powerpc by properly defining
> > dma_mmap_coherent() & ARCH_HAS_DMA_MMAP_COHERENT (I thought we had added
> > it a while back but it's not upstream, patch must have got lost).
>
> Mea culpa. I moved to a different team and have had little time for
> the upstream development since then...
That's ok, I did a new one, which you have noticed already anyways :-)
> > We
> > must also make sure we don't go down that path for vmalloc memory
> > though.
>
> Yes.
I haven't actually checked, but I assume that the test
substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV
In snd_pcm_default_mmap() takes care of that, please correct me if
I'm wrong in which case we'll need something else there.
> Your patch looks good. Thanks for taking care of this!
Are you taking care of sending it upstream ?
Cheers,
Ben.
^ permalink raw reply
* Re: High load average (~2.0) on an idle PowerPC 64 machine
From: Benjamin Herrenschmidt @ 2011-03-25 9:20 UTC (permalink / raw)
To: Romain Goyet; +Cc: linuxppc-dev
In-Reply-To: <AANLkTikbd0S6MGK4p7=_0q8c6nbk=k1TmLcM+Mc52=FW@mail.gmail.com>
On Thu, 2011-03-24 at 21:23 +0100, Romain Goyet wrote:
> I there,
>
> I've this Quad G5 machine that's sitting pretty much idle with the
> latest Debian stable installed, and yet it's got an abnormaly high
> load average.
> I've detailed the situation over here, maybe you guys will find it
> interesting or have something to say :
> http://serverfault.com/questions/251299/high-load-average-over-2-0-on-an-idle-machine
>
> The machine doesn't seem to be actually slowed down, it looks more
> like an incorrect measurement.
>
> Thank you very much for any help !
>From memory, this can be due to the thermal control driver's kernel
thread, which essentially does uninterruptible sleeps all the time,
either when waiting for request completion from SMU or i2c.
Since it's pretty much constantly talking to these, it causes an
increase load (they can take time to respond). So in effect it's not
actually hogging the CPU.
I don't know if there's a clean way to fix that.
Now it's possible that there's a different cause, that's just talking
from some vague memories, so some investigations would be useful
regardless.
Cheers,
Ben.
^ permalink raw reply
* High load average (~2.0) on an idle PowerPC 64 machine
From: David Laight @ 2011-03-25 9:23 UTC (permalink / raw)
To: linuxppc-dev
> I've this Quad G5 machine that's sitting pretty much idle with the
> latest Debian stable installed, and yet it's got an abnormaly high
> load average.
The 'load average' value is rather useless since it seems to
contain any process that is sleeping uninterruptibly, and
IIRC any process that has run at all (for however short a
period) in the current schedule epoch (or whatever period
is relevant).
I can easily generate a linux system that is 99.9% idle
but has a 'load average' of 20 or more.
It would still be 99.9% idle even if the idle time
were based of the actual time outside the scheduler
idle loop (as NetBSD doe) rather than where timer
ticks interrupted.
We also have the related fubar (on x64/amd64) of the
kernel generating stack traces for processes that are
sleeping uninterruptibly for long periods.
David
^ permalink raw reply
* Re: How to define an I2C-to-SPI bridge device ?
From: Andre Schwarz @ 2011-03-25 9:28 UTC (permalink / raw)
To: Grant Likely; +Cc: LinuxPPC List
In-Reply-To: <c843f864-2a5a-4146-bd95-13c2fb91f430@email.android.com>
Grant, Anton,
>>> we're about to get new MPC8377 based hardware with various peripherals.
>>>> There are two I2C-to-SPI bridge devices (NXP SC18IS602) and I'm not sure
>>>> how to define a proper dts...
>>>>
>>>> Of course it's an easy thing creating 2 child nodes on the CPU's I2C
>>>> device - but how can I represent the created SPI bus ?
>>> Um.. the same as the other SPI buses? I.e.
>>>
>>> i2c-controller { /* SOC I2C controller */
>>> spi-controller { /* The I2C-to-SPI bridge */
>>> spi-device@0 {
>>> };
>>> spi-device@1 {
>>> };
>>> };
>>> };
>>>
>> ok , thanks - looks straight forward.
>> Is this any more than plain definition, i.e. will this trigger any I2C
>> or SPI device registration/linking ?
>>>> Is the (possibly) required driver (of_sc18is60x_spi ?) supposed to be an
>>>> I2C slave or an SPI host driver ?
>>> It should be an I2C driver that registers an SPI master (i.e.
>>> calls spi_alloc_master() and spi_register_master()).
>> hmm - ok. Will have to do it manually then ...
> Yes, but this is the case for non-of drivers too. The i2c to spi device driver must always create (and trigger population of) the spi bus instance.
>
I've kicked that I2C-to-SPI stuff completely because it's been too slow.
We've connected the SPI busses to the FPGA controlling almost everything
now.
Unfortunately there are some questions left :
Following Anton's suggestion I've had a look at /drivers/mfd (sm501.c)
and implemented a pci driver for the FPGA using
subdevices for additional functionality it exports - besides others we
now have 2 SPI masters.
For both SPI masters I have created and registered a platform_device.
pdev->dev is then fed into spi_alloc_master() and the resulting master
goes into spi_register_master().
master->bus_num is set to 0 and 1, i.e. no dynamic numbering.
master->chipselect = 8;
Since I can probe the SPI device using FPGA intrinsic information I
decided to register the client
devices on runtime using a "struct spi_board_info" which is fed into
spi_new_device().
The current design has 2 clients on SPI-0 and 5 clients on SPI-1.
static struct spi_board_info mergerbox_spi_boardinfo[] = {
{ .bus_num = 0,
.chip_select = 0,
.max_speed_hz = 4<<20, },
{ .bus_num = 0,
.chip_select = 1,
.max_speed_hz = 4<<20, },
{ .bus_num = 1,
.chip_select = 0,
.max_speed_hz = 4<<20, },
.....
After loading my module I get :
#> ls /sys/devices/platform/AlteraSPI.0/
/sys/devices/platform/AlteraSPI.0/modalias
/sys/devices/platform/AlteraSPI.0/spi0.0/
/sys/devices/platform/AlteraSPI.0/spi0.1/
/sys/devices/platform/AlteraSPI.0/spi_master/
/sys/devices/platform/AlteraSPI.0/subsystem/
/sys/devices/platform/AlteraSPI.0/uevent
#> ls /sys/devices/platform/AlteraSPI.1/
/sys/devices/platform/AlteraSPI.1/modalias
/sys/devices/platform/AlteraSPI.1/spi1.0/
/sys/devices/platform/AlteraSPI.1/spi1.1/
/sys/devices/platform/AlteraSPI.1/spi1.2/
/sys/devices/platform/AlteraSPI.1/spi1.3/
/sys/devices/platform/AlteraSPI.1/spi1.4/
/sys/devices/platform/AlteraSPI.1/spi_master/
/sys/devices/platform/AlteraSPI.1/subsystem/
/sys/devices/platform/AlteraSPI.1/uevent
What I'm missing are the /dev/spi* entries.
There's also a spi_mpc8xxx driver using the CPU's SPI controller.
It is configured by dts (2 devices) and uses dynamic bus numbering:
#> ls /sys/bus/spi/devices/
spi0.0 spi1.0 spi1.2 spi1.4 spi32766.1
spi0.1 spi1.1 spi1.3 spi32766.0
This devices are processed by spidev and proper entries are created
ready for use :
#> ls /dev/spi*
/dev/spidev32766.0 /dev/spidev32766.1
Am I missing somehting obvious ?
Since there's no driver registration we don't have a probe function - is
this a problem regarding device binding ?
Do I need to use the .modalias in "struct spi_board_info" ?
Any help is welcome.
Regards,
André
MATRIX VISION GmbH, Talstrasse 16, DE-71570 Oppenweiler
Registergericht: Amtsgericht Stuttgart, HRB 271090
Geschaeftsfuehrer: Gerhard Thullner, Werner Armingeon, Uwe Furtner
^ permalink raw reply
* Re: [BUG] pgprot_noncached() is -NOT- safe for mapping vmalloc buffers into userspace
From: Takashi Iwai @ 2011-03-25 10:12 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linux-arch, linuxppc-dev, linux-kernel@vger.kernel.org,
Matthew Evans
In-Reply-To: <1301044533.2402.478.camel@pasglop>
At Fri, 25 Mar 2011 20:15:33 +1100,
Benjamin Herrenschmidt wrote:
>
> > > We
> > > must also make sure we don't go down that path for vmalloc memory
> > > though.
> >
> > Yes.
>
> I haven't actually checked, but I assume that the test
>
> substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV
>
> In snd_pcm_default_mmap() takes care of that, please correct me if
> I'm wrong in which case we'll need something else there.
Well, in the case of usb-audio, it's not handled via
dma_mmap_coherent(), as the page isn't allocated via
dma_alloc_coherent() but vmalloc().
The bad commit was to overcome some problems on SH platform, IIRC,
when it's used with dmix -- i.e. concurrent accesses on the mmapped
buffer from multiple processes. But, this looks obviously like a
wrong approach.
Actually, the buffer allocated there in usb-audio is an intermediate
buffer, that isn't directly transferred to hardware. We may need a
bit more consideration what is the best way to solve that issue (if
it's still really present).
> > Your patch looks good. Thanks for taking care of this!
>
> Are you taking care of sending it upstream ?
I'll apply the patch to remove vmalloc pgprot thingy surely to sound
tree and include in the next pull request.
Others should be sent through arch maintainers (PPC and ARM), right?
thanks,
Takashi
^ permalink raw reply
* Re: ALSA: vmalloc buffers should use normal mmap
From: Takashi Iwai @ 2011-03-25 10:14 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-kernel@vger.kernel.org
In-Reply-To: <1301035914.2402.472.camel@pasglop>
At Fri, 25 Mar 2011 17:51:54 +1100,
Benjamin Herrenschmidt wrote:
>
> It's a big no-no to use pgprot_noncached() when mmap'ing such buffers
> into userspace since they are mapped cachable in kernel space.
>
> This can cause all sort of interesting things ranging from to garbled
> sound to lockups on various architectures. I've observed that usb-audio
> is broken on powerpc 4xx for example because of that.
>
> Also remove the now unused snd_pcm_lib_mmap_noncached(). It's
> an arch business to know when to use uncached mappings, there's
> already hacks for MIPS inside snd_pcm_default_mmap() and other
> archs are supposed to use dma_mmap_coherent().
>
> (See my separate patch that adds dma_mmap_coherent() to powerpc)
>
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> CC: Takashi Iwai <tiwai@suse.de>
Applied now to sound git tree. Thanks.
Takashi
> ---
> include/sound/pcm.h | 4 +---
> sound/core/pcm_native.c | 9 ---------
> 2 files changed, 1 insertions(+), 12 deletions(-)
>
> diff --git a/include/sound/pcm.h b/include/sound/pcm.h
> index 430a9cc..e1bad11 100644
> --- a/include/sound/pcm.h
> +++ b/include/sound/pcm.h
> @@ -1031,9 +1031,7 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream, struct vm_area_s
> #define snd_pcm_lib_mmap_iomem NULL
> #endif
>
> -int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
> - struct vm_area_struct *area);
> -#define snd_pcm_lib_mmap_vmalloc snd_pcm_lib_mmap_noncached
> +#define snd_pcm_lib_mmap_vmalloc NULL
>
> static inline void snd_pcm_limit_isa_dma_size(int dma, size_t *max)
> {
> diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
> index 2d99c37..7639407 100644
> --- a/sound/core/pcm_native.c
> +++ b/sound/core/pcm_native.c
> @@ -3194,15 +3194,6 @@ int snd_pcm_lib_mmap_iomem(struct snd_pcm_substream *substream,
> EXPORT_SYMBOL(snd_pcm_lib_mmap_iomem);
> #endif /* SNDRV_PCM_INFO_MMAP */
>
> -/* mmap callback with pgprot_noncached */
> -int snd_pcm_lib_mmap_noncached(struct snd_pcm_substream *substream,
> - struct vm_area_struct *area)
> -{
> - area->vm_page_prot = pgprot_noncached(area->vm_page_prot);
> - return snd_pcm_default_mmap(substream, area);
> -}
> -EXPORT_SYMBOL(snd_pcm_lib_mmap_noncached);
> -
> /*
> * mmap DMA buffer
> */
>
>
^ permalink raw reply
* Re: [BUG] pgprot_noncached() is -NOT- safe for mapping vmalloc buffers into userspace
From: Benjamin Herrenschmidt @ 2011-03-25 10:23 UTC (permalink / raw)
To: Takashi Iwai
Cc: linux-arch, linuxppc-dev, linux-kernel@vger.kernel.org,
Matthew Evans
In-Reply-To: <s5htyer8q5m.wl%tiwai@suse.de>
On Fri, 2011-03-25 at 11:12 +0100, Takashi Iwai wrote:
> At Fri, 25 Mar 2011 20:15:33 +1100,
> Benjamin Herrenschmidt wrote:
> >
> > > > We
> > > > must also make sure we don't go down that path for vmalloc memory
> > > > though.
> > >
> > > Yes.
> >
> > I haven't actually checked, but I assume that the test
> >
> > substream->dma_buffer.dev.type == SNDRV_DMA_TYPE_DEV
> >
> > In snd_pcm_default_mmap() takes care of that, please correct me if
> > I'm wrong in which case we'll need something else there.
>
> Well, in the case of usb-audio, it's not handled via
> dma_mmap_coherent(), as the page isn't allocated via
> dma_alloc_coherent() but vmalloc().
Right, I just wanted to make sure I was right to assume that a page
allocated by vmalloc() was going to fail the above test in
snd_pcm_default_mmap() and thus -not- get into dma_mmap_coherent()...
just double checking as I'm not totally familiar with the intricacies of
the pcm code :-)
> The bad commit was to overcome some problems on SH platform, IIRC,
> when it's used with dmix -- i.e. concurrent accesses on the mmapped
> buffer from multiple processes. But, this looks obviously like a
> wrong approach.
Is this a vivt architecture ? Maybe enforcing some restrictions on the
virtual addresses so they hit the same cache congruence classes ?
> Actually, the buffer allocated there in usb-audio is an intermediate
> buffer, that isn't directly transferred to hardware. We may need a
> bit more consideration what is the best way to solve that issue (if
> it's still really present).
Right. I wouldn't expect vmalloc stuff to hit HW in most cases anyways,
though I do wonder why you don't pass the buffer directly to the HCD and
avoid that intermediate step but that's a completely different
question :-)
> > > Your patch looks good. Thanks for taking care of this!
> >
> > Are you taking care of sending it upstream ?
>
> I'll apply the patch to remove vmalloc pgprot thingy surely to sound
> tree and include in the next pull request.
>
> Others should be sent through arch maintainers (PPC and ARM), right?
Well, I am ppc maintainer so that's sorted :-) I've CCed Russell for the
other, it's up to him, I have no specific dependency there, it's just an
easy cleanup I stumbled upon.
Cheers,
Ben.
>
> thanks,
>
> Takashi
> --
> To unsubscribe from this list: send the line "unsubscribe linux-arch" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox