* FHCI: USB: The use of qe general purpose timer and usb device descriptor read/64, error -110
From: Richard Retanubun @ 2009-07-23 20:56 UTC (permalink / raw)
To: Linuxppc-dev-mList
Hi,
I am working on Linux-2.6.29.5 on an MPC8360E, trying to make the FHCI USB working.
the output of clocks in u-boot is as follows:
> Output of u-boot clocks command <
Clock configuration:
Core: 533.333 MHz
Coherent System Bus: 266.667 MHz
QE: 400 MHz
BRG: 200 MHz
Local Bus Controller:266.667 MHz
Local Bus: 66.667 MHz
DDR: 266.667 MHz
DDR Secondary: 266.667 MHz
SEC: 88.889 MHz
I2C1: 266.667 MHz
I2C2: 266.667 MHz
rcm1:~# cat /proc/cpuinfo
processor : 0
cpu : e300c1
clock : 533.333328MHz
revision : 3.1 (pvr 8083 0031)
bogomips : 133.12
timebase : 66666666
platform : MPC836x
model : RC8360
Memory : 512 MB
In the dts, because our cpu_clk and csb_clk is the same as mpc8360_rdk eval platfrom (533.333 MHz and 266.666 MHZ)
I modeled the gtm frame limit timer the same as mpc836x_rdk.dts, namely as follows:
timer@440 {
compatible = "fsl,mpc8360-qe-gtm",
"fsl,qe-gtm", "fsl,gtm";
reg = <0x440 0x40>;
interrupts = <12 13 14 15>;
interrupt-parent = <&qeic>;
clock-frequency = <166666666>; /* RDK at 533.333 MHz */
/* clock-frequency = <132000000>; [DISABLED] MDS at 528 MHz */
};
In the fhci-hdc.c code, the timer is used as the "Frame limit timer"
I am wondering how is the clock-frequency = <166666666> derived and what its function is for the fhci-usb driver?
Also, using the timer settings as shown, so far I can only got one USB flash mass-storage device to come up successfully.
The rest of the device will enumerate, but fails like this:
usb 1-1: new full speed USB device using fsl,usb-fhci and address 2
usb 1-1: New USB device found, idVendor=0204, idProduct=6025
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: Flash Disk
usb 1-1: Manufacturer: CBM
usb 1-1: SerialNumber: 2519130247661913
usb 1-1: configuration #1 chosen from 1 choice
scsi1 : SCSI emulation for USB Mass Storage devices
usb-storage: device found at 2
usb-storage: waiting for device to settle before scanning
usb 1-1: reset full speed USB device using fsl,usb-fhci and address 2
usb 1-1: device descriptor read/64, error -110
usb 1-1: device descriptor read/64, error -110
usb 1-1: USB disconnect, address 2
usb-storage: device scan complete
usb 1-1: new full speed USB device using fsl,usb-fhci and address 3
usb 1-1: device descriptor read/64, error -110
usb 1-1: device descriptor read/64, error -110
hub 1-0:1.0: unable to enumerate USB device on port 1
usb 1-1: new full speed USB device using fsl,usb-fhci and address 5
usb 1-1: device descriptor read/64, error -110
usb 1-1: device descriptor read/64, error -110
From web-search, the resolution for the usb 1-1: device descriptor read/64, error -110 is usually to modprobe -r ehci-hdc,
however I never enabled ehci driver because the fhci is the only one that works with MPC8360.
If it is indeed a timeout from getting the device information from the flash chip on the USB mass-storage, how can I extend this
timeout to allow for more time?
This is the relevant dmesg output on usb:
=========================================
fsl,usb-fhci e01006c0.usb: assuming board doesn't have speed gpio
fsl,usb-fhci e01006c0.usb: assuming board doesn't have power gpio
fsl,usb-fhci e01006c0.usb: at 0xe10386c0, irq 25
fsl,usb-fhci e01006c0.usb: FHCI HOST Controller
fsl,usb-fhci e01006c0.usb: new USB bus registered, assigned bus number 1
fsl,usb-fhci e01006c0.usb: irq 25, io mem 0x00000000
usb usb1: New USB device found, idVendor=1d6b, idProduct=0001
usb usb1: New USB device strings: Mfr=3, Product=2, SerialNumber=1
usb usb1: Product: FHCI HOST Controller
usb usb1: Manufacturer: Linux 2.6.29.5-dirty fsl,usb-fhci
usb usb1: SerialNumber: e01006c0.usb
usb usb1: configuration #1 chosen from 1 choice
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 1 port detected
Initializing USB Mass Storage driver...
usbcore: registered new interface driver usb-storage
USB Mass Storage support registered.
...
usb 1-1: new full speed USB device using fsl,usb-fhci and address 2
usb 1-1: New USB device found, idVendor=0204, idProduct=6025
usb 1-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
usb 1-1: Product: Flash Disk
usb 1-1: Manufacturer: CBM
usb 1-1: SerialNumber: 2519130247661913
usb 1-1: configuration #1 chosen from 1 choice
scsi1 : SCSI emulation for USB Mass Storage devices
usb-storage: device found at 2
usb-storage: waiting for device to settle before scanning
usb 1-1: reset full speed USB device using fsl,usb-fhci and address 2
usb 1-1: device descriptor read/64, error -110
usb 1-1: device descriptor read/64, error -110
usb 1-1: USB disconnect, address 2
usb-storage: device scan complete
usb 1-1: new full speed USB device using fsl,usb-fhci and address 3
usb 1-1: device descriptor read/64, error -110
usb 1-1: device descriptor read/64, error -110
hub 1-0:1.0: unable to enumerate USB device on port 1
usb 1-1: new full speed USB device using fsl,usb-fhci and address 5
usb 1-1: device descriptor read/64, error -110
usb 1-1: device descriptor read/64, error -110
Thanks for everyone's time
- Richard Retanubun
^ permalink raw reply
* Re: [PATCH] powerpc: minor Makefile simplification through use of cc-ifversion
From: Sam Ravnborg @ 2009-07-23 21:31 UTC (permalink / raw)
To: Frans Pop; +Cc: linuxppc-dev, linux-kbuild, linux-kernel
In-Reply-To: <200907232057.19942.elendil@planet.nl>
On Thu, Jul 23, 2009 at 08:57:18PM +0200, Frans Pop wrote:
> Signed-off-by: Frans Pop <elendil@planet.nl>
Acked-by: Sam Ravnborg <sam@ravnborg.org>
^ permalink raw reply
* Re: [PATCH 0/20] powerpc: base 64-bit Book3E processor support
From: Benjamin Herrenschmidt @ 2009-07-23 22:10 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev list
In-Reply-To: <94483336-7714-4713-AB1C-2AAAA9BBB638@kernel.crashing.org>
On Thu, 2009-07-23 at 09:42 -0500, Kumar Gala wrote:
> >
> > The intend is to merge these in 2.6.32. They rely on pretty much
> > all the other patches I've been posting lately including the
> > generic changes to add the virtual address argument to pte_free_tlb.
> >
>
> Are these in a git tree/branch. Makes it a bit easier to test out on
> FSL booke-32 to make sure we didn't break anything.
Plan is to stick them in my -test branch for a few days before they hit
-next, I just didn't have time to finish that yesterday, hopefully will
do today along with addressing a few comments already done about them.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH 11/20] powerpc: Move definitions of secondary CPU spinloop to header file
From: Benjamin Herrenschmidt @ 2009-07-23 22:11 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <9D0737C4-EA82-41B8-B109-ED4FDB901C00@kernel.crashing.org>
On Thu, 2009-07-23 at 09:51 -0500, Kumar Gala wrote:
> On Jul 23, 2009, at 12:59 AM, Benjamin Herrenschmidt wrote:
>
> > Those definitions are currently declared extern in the .c file where
> > they are used, move them to a header file instead.
> >
> > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > --
> >
> > arch/powerpc/include/asm/smp.h | 5 +++++
> > arch/powerpc/kernel/setup_64.c | 3 ---
> > 2 files changed, 5 insertions(+), 3 deletions(-)
>
> Can we not get rid of the externs in:
>
> arch/powerpc/platforms/cell/smp.c:extern void
> generic_secondary_smp_init(unsigned long);
> arch/powerpc/platforms/pseries/smp.c:extern void
> generic_secondary_smp_init(unsigned long);
>
> arch/powerpc/kernel/prom_init.c:extern unsigned long
> __secondary_hold_spinloop;
Probably :-) I'll have a look.
Cheers,
Ben.
> - k
>
> >
> >
> > --- linux-work.orig/arch/powerpc/include/asm/smp.h 2009-07-22
> > 16:38:32.000000000 +1000
> > +++ linux-work/arch/powerpc/include/asm/smp.h 2009-07-22
> > 16:46:59.000000000 +1000
> > @@ -148,6 +148,11 @@ extern struct smp_ops_t *smp_ops;
> > extern void arch_send_call_function_single_ipi(int cpu);
> > extern void arch_send_call_function_ipi(cpumask_t mask);
> >
> > +#ifdef CONFIG_PPC64
> > +extern void generic_secondary_smp_init(void);
> > +extern unsigned long __secondary_hold_spinloop;
> > +#endif /* CONFIG_PPC64 */
> > +
> > #endif /* __ASSEMBLY__ */
> >
> > #endif /* __KERNEL__ */
> > Index: linux-work/arch/powerpc/kernel/setup_64.c
> > ===================================================================
> > --- linux-work.orig/arch/powerpc/kernel/setup_64.c 2009-07-22
> > 16:38:12.000000000 +1000
> > +++ linux-work/arch/powerpc/kernel/setup_64.c 2009-07-22
> > 16:46:59.000000000 +1000
> > @@ -230,9 +230,6 @@ void early_setup_secondary(void)
> > #endif /* CONFIG_SMP */
> >
> > #if defined(CONFIG_SMP) || defined(CONFIG_KEXEC)
> > -extern unsigned long __secondary_hold_spinloop;
> > -extern void generic_secondary_smp_init(void);
> > -
> > void smp_release_cpus(void)
> > {
> > unsigned long *ptr;
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 4/20] powerpc/mm: Add opcode definitions for tlbivax and tlbsrx.
From: Benjamin Herrenschmidt @ 2009-07-23 22:12 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <883C2E2A-F904-4FDE-9363-BF813B90676D@kernel.crashing.org>
On Thu, 2009-07-23 at 10:55 -0500, Kumar Gala wrote:
> On Jul 23, 2009, at 12:59 AM, Benjamin Herrenschmidt wrote:
>
> > This adds the opcode definitions to ppc-opcode.h for the two
> > instructions
> > tlbivax and tlbsrx. as defined by Book3E 2.06
> >
> > Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> > ---
> >
> > arch/powerpc/include/asm/ppc-opcode.h | 6 ++++++
> > 1 file changed, 6 insertions(+)
>
> Do we really have binutils that don't have tlbivax properly at this
> point?
I don't know for sure, I like being consistent with the rest though
and so I use those macros for all those MMU opcodes. Also means that
I have no problem building with my current toolchain without passing
a specific -mcpu option or anything like that :-)
We can change that back later if you want.
Cheers,
Ben.
^ permalink raw reply
* BUG in dma-mapping.h:218 // MESH SCSI driver not working
From: Stef Simoens @ 2009-07-23 22:18 UTC (permalink / raw)
To: linuxppc-dev
Hello list,
I'm running Gentoo Linux with kernel 2.6.29 on a PPC9600 with a G3
processor upgrade.
My boot drive is on the internal "mesh" SCSI-controller. Self-compiled
kernel 2.6.29 is running fine for quite some time.
However, after compiling 2.6.30 (with more or less the same
configuration), I get this BUG (typed over from a picture, sorry for
possible typos):
kernel BUG at
/usr/src/linux-2.6.30-gentoo-r3/arch/powerpc/include/asm/dma-mapping.h:218!
Oops: Exception in kernel mode, sig: 5 [#1]
PowerMac
Modules linked in:
NIP: c01bb4cc LR: c01c01cc CTR: c01c01
REGS: ...
MSR: ...
TASK = c030f500[0] 'swapper' THREAD: ...
GPR00: ...
GPR08: ...
GPR16: ...
GPR24: ...
NIP [c01bb4cc] scsi_dma_map+0x4c/0x7c
LR [c01c01cc] start_phase+0x3a0/0x5c8
I found on the list a patch by Benjamin :
http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-June/073468.html
I applied this patch to the 2.6.30 source-tree.
After applying this patch, the BUG dissapears, but the mesh controller
still is not able to read any data from disk. The screen output is:
mesh: performing initial bus reset...
ADB mouse at 3, handler set to 2
input: ADB mouse as /devices/virtual/input/input2
adb: finished probe task...
scsi0: MESH
mesh: target 0 synchronous at 10MB/s
scsi 0:0:0:0: Direct-Access ...
mesh: target 1 synchronous at 10 MB/s
scsi 0:0:1:0: Direct-Access ...
mesh: target 3 synchronous at 10 MB/s
scsi 0:0:3:0: CD-ROM ...
mice: PS/2 mouse device common for all mice
TCP cubic registered
Initializing XFRM netlink socket
NET: Registered protocol family 17
[there's a long time-out here]
mesh_abort(ef8501e0)
mesh: state at ef868a4c, regs at f1010000, dma at
ct= 1 seq=5a bs=4023 fc= 0 exc= 0 err= 0 in=
dma stat=e0 cmdptr=2f8d4010
phase=6 msgphase=4 conn_tgt=0 data_ptr=0
dma_st=0 dma_ct=0 n_msgout=0
target 0: req=ef8501e0 goes_out=0 saved_ptr=0
mesh_abort(ef850280)
(continues some times, to finally panic because the root-device cannot
be found)
I tried the latest 2.6.31-rc3-git3 (without any other patch).
However, I have the same behaviour as the patched 2.6.30 (so: no BUG,
but the mesh_abort messages).
Anybody knows what's going wrong, and how to fix it? I've read the
history of this list of June and July ... but I didn't find any other
reports of the problem I'm encountering...
Thank you for your help.
Kind regards
Stef Simoens
^ permalink raw reply
* Re: [PATCH] powerpc: minor Makefile simplification through use of cc-ifversion
From: Benjamin Herrenschmidt @ 2009-07-23 23:52 UTC (permalink / raw)
To: Sam Ravnborg; +Cc: linuxppc-dev, Frans Pop, linux-kernel, linux-kbuild
In-Reply-To: <20090723213132.GA9514@merkur.ravnborg.org>
On Thu, 2009-07-23 at 23:31 +0200, Sam Ravnborg wrote:
> On Thu, Jul 23, 2009 at 08:57:18PM +0200, Frans Pop wrote:
> > Signed-off-by: Frans Pop <elendil@planet.nl>
> Acked-by: Sam Ravnborg <sam@ravnborg.org>
Thanks, will include in my next batch.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 2/5] powerpc: remove swiotlb_pci_dma_ops
From: FUJITA Tomonori @ 2009-07-24 3:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: FUJITA Tomonori, linux-kernel
In-Reply-To: <1248405855-15546-1-git-send-email-fujita.tomonori@lab.ntt.co.jp>
Now swiotlb_pci_dma_ops is identical to swiotlb_dma_ops; we can use
swiotlb_dma_ops with any devices. This removes swiotlb_pci_dma_ops.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
arch/powerpc/include/asm/swiotlb.h | 1 -
arch/powerpc/kernel/dma-swiotlb.c | 14 --------------
arch/powerpc/platforms/85xx/mpc8536_ds.c | 2 +-
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 2 +-
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 2 +-
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 2 +-
6 files changed, 4 insertions(+), 19 deletions(-)
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 31e0e43..21ce0a3 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -14,7 +14,6 @@
#include <linux/swiotlb.h>
extern struct dma_mapping_ops swiotlb_dma_ops;
-extern struct dma_mapping_ops swiotlb_pci_dma_ops;
static inline void dma_mark_clean(void *addr, size_t size) {}
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index c9f6a30..ca141e1 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -45,20 +45,6 @@ struct dma_mapping_ops swiotlb_dma_ops = {
.sync_sg_for_device = swiotlb_sync_sg_for_device
};
-struct dma_mapping_ops swiotlb_pci_dma_ops = {
- .alloc_coherent = dma_direct_alloc_coherent,
- .free_coherent = dma_direct_free_coherent,
- .map_sg = swiotlb_map_sg_attrs,
- .unmap_sg = swiotlb_unmap_sg_attrs,
- .dma_supported = swiotlb_dma_supported,
- .map_page = swiotlb_map_page,
- .unmap_page = swiotlb_unmap_page,
- .sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
- .sync_single_range_for_device = swiotlb_sync_single_range_for_device,
- .sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
- .sync_sg_for_device = swiotlb_sync_sg_for_device
-};
-
void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
{
struct pci_controller *hose;
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index bf052c0..004b7d3 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -96,7 +96,7 @@ static void __init mpc8536_ds_setup_arch(void)
#ifdef CONFIG_SWIOTLB
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ set_pci_dma_ops(&swiotlb_dma_ops);
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index c6f92cc..544011a 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -192,7 +192,7 @@ static void __init mpc85xx_ds_setup_arch(void)
#ifdef CONFIG_SWIOTLB
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ set_pci_dma_ops(&swiotlb_dma_ops);
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 8b8e5f9..c4961ed 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -241,7 +241,7 @@ static void __init mpc85xx_mds_setup_arch(void)
#ifdef CONFIG_SWIOTLB
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ set_pci_dma_ops(&swiotlb_dma_ops);
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 8032301..2aa69a6 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -105,7 +105,7 @@ mpc86xx_hpcn_setup_arch(void)
#ifdef CONFIG_SWIOTLB
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
- set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ set_pci_dma_ops(&swiotlb_dma_ops);
ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
--
1.6.0.6
^ permalink raw reply related
* [PATCH 3/5] add set_dma_mask hook to struct dma_map_ops
From: FUJITA Tomonori @ 2009-07-24 3:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: FUJITA Tomonori, linux-kernel
In-Reply-To: <1248405855-15546-1-git-send-email-fujita.tomonori@lab.ntt.co.jp>
POWERPC needs this hook. SPARC could use it too.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
include/linux/dma-mapping.h | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index c0f6c3c..91b7618 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -58,6 +58,7 @@ struct dma_map_ops {
enum dma_data_direction dir);
int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
int (*dma_supported)(struct device *dev, u64 mask);
+ int (*set_dma_mask)(struct device *dev, u64 mask);
int is_phys;
};
--
1.6.0.6
^ permalink raw reply related
* [PATCH 5/5] powerpc: use asm-generic/dma-mapping-common.h
From: FUJITA Tomonori @ 2009-07-24 3:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: FUJITA Tomonori, linux-kernel
In-Reply-To: <1248405855-15546-1-git-send-email-fujita.tomonori@lab.ntt.co.jp>
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/dma-mapping.h | 242 +-------------------------------
2 files changed, 7 insertions(+), 237 deletions(-)
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig
index d00131c..0603b6c 100644
--- a/arch/powerpc/Kconfig
+++ b/arch/powerpc/Kconfig
@@ -120,7 +120,7 @@ config PPC
select HAVE_KRETPROBES
select HAVE_ARCH_TRACEHOOK
select HAVE_LMB
- select HAVE_DMA_ATTRS if PPC64
+ select HAVE_DMA_ATTRS
select USE_GENERIC_SMP_HELPERS if SMP
select HAVE_OPROFILE
select HAVE_SYSCALL_WRAPPERS if PPC64
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 8ca2b51..91217e4 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -14,6 +14,7 @@
#include <linux/mm.h>
#include <linux/scatterlist.h>
#include <linux/dma-attrs.h>
+#include <linux/dma-debug.h>
#include <asm/io.h>
#include <asm/swiotlb.h>
@@ -89,6 +90,11 @@ static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
dev->archdata.dma_ops = ops;
}
+/* this will be removed soon */
+#define flush_write_buffers()
+
+#include <asm-generic/dma-mapping-common.h>
+
static inline int dma_supported(struct device *dev, u64 mask)
{
struct dma_map_ops *dma_ops = get_dma_ops(dev);
@@ -117,87 +123,6 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
return 0;
}
-/*
- * map_/unmap_single actually call through to map/unmap_page now that all the
- * dma_map_ops have been converted over. We just have to get the page and
- * offset to pass through to map_page
- */
-static inline dma_addr_t dma_map_single_attrs(struct device *dev,
- void *cpu_addr,
- size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- return dma_ops->map_page(dev, virt_to_page(cpu_addr),
- (unsigned long)cpu_addr % PAGE_SIZE, size,
- direction, attrs);
-}
-
-static inline void dma_unmap_single_attrs(struct device *dev,
- dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- dma_ops->unmap_page(dev, dma_addr, size, direction, attrs);
-}
-
-static inline dma_addr_t dma_map_page_attrs(struct device *dev,
- struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- return dma_ops->map_page(dev, page, offset, size, direction, attrs);
-}
-
-static inline void dma_unmap_page_attrs(struct device *dev,
- dma_addr_t dma_address,
- size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- dma_ops->unmap_page(dev, dma_address, size, direction, attrs);
-}
-
-static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- return dma_ops->map_sg(dev, sg, nents, direction, attrs);
-}
-
-static inline void dma_unmap_sg_attrs(struct device *dev,
- struct scatterlist *sg,
- int nhwentries,
- enum dma_data_direction direction,
- struct dma_attrs *attrs)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
- dma_ops->unmap_sg(dev, sg, nhwentries, direction, attrs);
-}
-
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
@@ -216,161 +141,6 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
}
-static inline dma_addr_t dma_map_single(struct device *dev, void *cpu_addr,
- size_t size,
- enum dma_data_direction direction)
-{
- return dma_map_single_attrs(dev, cpu_addr, size, direction, NULL);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction direction)
-{
- dma_unmap_single_attrs(dev, dma_addr, size, direction, NULL);
-}
-
-static inline dma_addr_t dma_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- return dma_map_page_attrs(dev, page, offset, size, direction, NULL);
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
- size_t size,
- enum dma_data_direction direction)
-{
- dma_unmap_page_attrs(dev, dma_address, size, direction, NULL);
-}
-
-static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
-{
- return dma_map_sg_attrs(dev, sg, nents, direction, NULL);
-}
-
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nhwentries,
- enum dma_data_direction direction)
-{
- dma_unmap_sg_attrs(dev, sg, nhwentries, direction, NULL);
-}
-
-#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
-static inline void dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- if (dma_ops->sync_single_range_for_cpu)
- dma_ops->sync_single_range_for_cpu(dev, dma_handle, 0,
- size, direction);
-}
-
-static inline void dma_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- if (dma_ops->sync_single_range_for_device)
- dma_ops->sync_single_range_for_device(dev, dma_handle,
- 0, size, direction);
-}
-
-static inline void dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sgl, int nents,
- enum dma_data_direction direction)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- if (dma_ops->sync_sg_for_cpu)
- dma_ops->sync_sg_for_cpu(dev, sgl, nents, direction);
-}
-
-static inline void dma_sync_sg_for_device(struct device *dev,
- struct scatterlist *sgl, int nents,
- enum dma_data_direction direction)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- if (dma_ops->sync_sg_for_device)
- dma_ops->sync_sg_for_device(dev, sgl, nents, direction);
-}
-
-static inline void dma_sync_single_range_for_cpu(struct device *dev,
- dma_addr_t dma_handle, unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- if (dma_ops->sync_single_range_for_cpu)
- dma_ops->sync_single_range_for_cpu(dev, dma_handle,
- offset, size, direction);
-}
-
-static inline void dma_sync_single_range_for_device(struct device *dev,
- dma_addr_t dma_handle, unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
- struct dma_map_ops *dma_ops = get_dma_ops(dev);
-
- BUG_ON(!dma_ops);
-
- if (dma_ops->sync_single_range_for_device)
- dma_ops->sync_single_range_for_device(dev, dma_handle, offset,
- size, direction);
-}
-#else /* CONFIG_PPC_NEED_DMA_SYNC_OPS */
-static inline void dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
-}
-
-static inline void dma_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
-}
-
-static inline void dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sgl, int nents,
- enum dma_data_direction direction)
-{
-}
-
-static inline void dma_sync_sg_for_device(struct device *dev,
- struct scatterlist *sgl, int nents,
- enum dma_data_direction direction)
-{
-}
-
-static inline void dma_sync_single_range_for_cpu(struct device *dev,
- dma_addr_t dma_handle, unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
-}
-
-static inline void dma_sync_single_range_for_device(struct device *dev,
- dma_addr_t dma_handle, unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
-}
-#endif
-
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
#ifdef CONFIG_PPC64
--
1.6.0.6
^ permalink raw reply related
* [PATCH 0/5] powerpc: use asm-generic/dma-mapping-common.h
From: FUJITA Tomonori @ 2009-07-24 3:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: fujita.tomonori, linux-kernel
This patchset converts POWERPC to use asm-generic/dma-mapping-common.h.
The major change is removing addr_needs_map in struct dma_mapping_ops
(1/5):
http://marc.info/?t=124719060200001&r=1&w=2
This is on the top of my swiotlb cleanup patchset:
http://marc.info/?l=linuxppc-embedded&m=124718920320951&w=2
The patchset also is available via a git tree:
git://git.kernel.org/pub/scm/linux/kernel/git/tomo/linux-2.6-misc.git powerpc
=
arch/powerpc/Kconfig | 2 +-
arch/powerpc/include/asm/device.h | 7 +-
arch/powerpc/include/asm/dma-mapping.h | 308 ++--------------------------
arch/powerpc/include/asm/pci.h | 4 +-
arch/powerpc/include/asm/swiotlb.h | 8 +-
arch/powerpc/kernel/dma-iommu.c | 2 +-
arch/powerpc/kernel/dma-swiotlb.c | 50 ++---
arch/powerpc/kernel/dma.c | 2 +-
arch/powerpc/kernel/ibmebus.c | 2 +-
arch/powerpc/kernel/pci-common.c | 6 +-
arch/powerpc/kernel/vio.c | 2 +-
arch/powerpc/platforms/85xx/mpc8536_ds.c | 3 +-
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 3 +-
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 3 +-
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 3 +-
arch/powerpc/platforms/cell/iommu.c | 2 +-
arch/powerpc/platforms/ps3/system-bus.c | 4 +-
include/linux/dma-mapping.h | 1 +
18 files changed, 63 insertions(+), 349 deletions(-)
^ permalink raw reply
* [PATCH 1/5] powerpc: remove addr_needs_map in struct dma_mapping_ops
From: FUJITA Tomonori @ 2009-07-24 3:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: FUJITA Tomonori, linux-kernel
In-Reply-To: <1248405855-15546-1-git-send-email-fujita.tomonori@lab.ntt.co.jp>
This patch adds max_direct_dma_addr to struct dev_archdata to remove
addr_needs_map in struct dma_mapping_ops. It also converts
dma_capable() to use max_direct_dma_addr.
max_direct_dma_addr is initialized in pci_dma_dev_setup_swiotlb(),
called via ppc_md.pci_dma_dev_setup hook.
For further information:
http://marc.info/?t=124719060200001&r=1&w=2
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
arch/powerpc/include/asm/device.h | 3 ++
arch/powerpc/include/asm/dma-mapping.h | 8 +++---
arch/powerpc/include/asm/swiotlb.h | 5 +--
arch/powerpc/kernel/dma-swiotlb.c | 36 +++++++++++----------------
arch/powerpc/platforms/85xx/mpc8536_ds.c | 1 +
arch/powerpc/platforms/85xx/mpc85xx_ds.c | 1 +
arch/powerpc/platforms/85xx/mpc85xx_mds.c | 1 +
arch/powerpc/platforms/86xx/mpc86xx_hpcn.c | 1 +
8 files changed, 28 insertions(+), 28 deletions(-)
diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
index 7d2277c..0086f8d 100644
--- a/arch/powerpc/include/asm/device.h
+++ b/arch/powerpc/include/asm/device.h
@@ -16,6 +16,9 @@ struct dev_archdata {
/* DMA operations on that device */
struct dma_mapping_ops *dma_ops;
void *dma_data;
+#ifdef CONFIG_SWIOTLB
+ dma_addr_t max_direct_dma_addr;
+#endif
};
static inline void dev_archdata_set_node(struct dev_archdata *ad,
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 0c34371..1765c37 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -87,8 +87,6 @@ struct dma_mapping_ops {
dma_addr_t dma_address, size_t size,
enum dma_data_direction direction,
struct dma_attrs *attrs);
- int (*addr_needs_map)(struct device *dev, dma_addr_t addr,
- size_t size);
#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
void (*sync_single_range_for_cpu)(struct device *hwdev,
dma_addr_t dma_handle, unsigned long offset,
@@ -426,10 +424,12 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
{
- struct dma_mapping_ops *ops = get_dma_ops(dev);
+#ifdef CONFIG_SWIOTLB
+ struct dev_archdata *sd = &dev->archdata;
- if (ops->addr_needs_map && ops->addr_needs_map(dev, addr, size))
+ if (sd->max_direct_dma_addr && addr + size > sd->max_direct_dma_addr)
return 0;
+#endif
if (!dev->dma_mask)
return 0;
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 30891d6..31e0e43 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -16,12 +16,11 @@
extern struct dma_mapping_ops swiotlb_dma_ops;
extern struct dma_mapping_ops swiotlb_pci_dma_ops;
-int swiotlb_arch_address_needs_mapping(struct device *, dma_addr_t,
- size_t size);
-
static inline void dma_mark_clean(void *addr, size_t size) {}
extern unsigned int ppc_swiotlb_enable;
int __init swiotlb_setup_bus_notifier(void);
+extern void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev);
+
#endif /* __ASM_SWIOTLB_H */
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index e8a57de..c9f6a30 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -25,26 +25,6 @@ int swiotlb __read_mostly;
unsigned int ppc_swiotlb_enable;
/*
- * Determine if an address is reachable by a pci device, or if we must bounce.
- */
-static int
-swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
-{
- dma_addr_t max;
- struct pci_controller *hose;
- struct pci_dev *pdev = to_pci_dev(hwdev);
-
- hose = pci_bus_to_host(pdev->bus);
- max = hose->dma_window_base_cur + hose->dma_window_size;
-
- /* check that we're within mapped pci window space */
- if ((addr + size > max) | (addr < hose->dma_window_base_cur))
- return 1;
-
- return 0;
-}
-
-/*
* At the moment, all platforms that use this code only require
* swiotlb to be used if we're operating on HIGHMEM. Since
* we don't ever call anything other than map_sg, unmap_sg,
@@ -73,22 +53,36 @@ struct dma_mapping_ops swiotlb_pci_dma_ops = {
.dma_supported = swiotlb_dma_supported,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
- .addr_needs_map = swiotlb_pci_addr_needs_map,
.sync_single_range_for_cpu = swiotlb_sync_single_range_for_cpu,
.sync_single_range_for_device = swiotlb_sync_single_range_for_device,
.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
.sync_sg_for_device = swiotlb_sync_sg_for_device
};
+void pci_dma_dev_setup_swiotlb(struct pci_dev *pdev)
+{
+ struct pci_controller *hose;
+ struct dev_archdata *sd;
+
+ hose = pci_bus_to_host(pdev->bus);
+ sd = &pdev->dev.archdata;
+ sd->max_direct_dma_addr =
+ hose->dma_window_base_cur + hose->dma_window_size;
+}
+
static int ppc_swiotlb_bus_notify(struct notifier_block *nb,
unsigned long action, void *data)
{
struct device *dev = data;
+ struct dev_archdata *sd;
/* We are only intereted in device addition */
if (action != BUS_NOTIFY_ADD_DEVICE)
return 0;
+ sd = &dev->archdata;
+ sd->max_direct_dma_addr = 0;
+
/* May need to bounce if the device can't address all of DRAM */
if (dma_get_mask(dev) < lmb_end_of_DRAM())
set_dma_ops(dev, &swiotlb_dma_ops);
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c
index 055ff41..bf052c0 100644
--- a/arch/powerpc/platforms/85xx/mpc8536_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c
@@ -97,6 +97,7 @@ static void __init mpc8536_ds_setup_arch(void)
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 849c0ac..c6f92cc 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -193,6 +193,7 @@ static void __init mpc85xx_ds_setup_arch(void)
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
index 60ed9c0..8b8e5f9 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c
@@ -242,6 +242,7 @@ static void __init mpc85xx_mds_setup_arch(void)
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
}
diff --git a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
index 6632702..8032301 100644
--- a/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
+++ b/arch/powerpc/platforms/86xx/mpc86xx_hpcn.c
@@ -106,6 +106,7 @@ mpc86xx_hpcn_setup_arch(void)
if (lmb_end_of_DRAM() > max) {
ppc_swiotlb_enable = 1;
set_pci_dma_ops(&swiotlb_pci_dma_ops);
+ ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_swiotlb;
}
#endif
}
--
1.6.0.6
^ permalink raw reply related
* [PATCH 4/5] powerpc: use dma_map_ops struct
From: FUJITA Tomonori @ 2009-07-24 3:24 UTC (permalink / raw)
To: linuxppc-dev; +Cc: FUJITA Tomonori, linux-kernel
In-Reply-To: <1248405855-15546-1-git-send-email-fujita.tomonori@lab.ntt.co.jp>
This converts uses dma_map_ops struct (in include/linux/dma-mapping.h)
instead of POWERPC homegrown dma_mapping_ops.
Signed-off-by: FUJITA Tomonori <fujita.tomonori@lab.ntt.co.jp>
---
arch/powerpc/include/asm/device.h | 4 +-
arch/powerpc/include/asm/dma-mapping.h | 84 ++++++++-----------------------
arch/powerpc/include/asm/pci.h | 4 +-
arch/powerpc/include/asm/swiotlb.h | 2 +-
arch/powerpc/kernel/dma-iommu.c | 2 +-
arch/powerpc/kernel/dma-swiotlb.c | 2 +-
arch/powerpc/kernel/dma.c | 2 +-
arch/powerpc/kernel/ibmebus.c | 2 +-
arch/powerpc/kernel/pci-common.c | 6 +-
arch/powerpc/kernel/vio.c | 2 +-
arch/powerpc/platforms/cell/iommu.c | 2 +-
arch/powerpc/platforms/ps3/system-bus.c | 4 +-
12 files changed, 37 insertions(+), 79 deletions(-)
diff --git a/arch/powerpc/include/asm/device.h b/arch/powerpc/include/asm/device.h
index 0086f8d..67fcd7f 100644
--- a/arch/powerpc/include/asm/device.h
+++ b/arch/powerpc/include/asm/device.h
@@ -6,7 +6,7 @@
#ifndef _ASM_POWERPC_DEVICE_H
#define _ASM_POWERPC_DEVICE_H
-struct dma_mapping_ops;
+struct dma_map_ops;
struct device_node;
struct dev_archdata {
@@ -14,7 +14,7 @@ struct dev_archdata {
struct device_node *of_node;
/* DMA operations on that device */
- struct dma_mapping_ops *dma_ops;
+ struct dma_map_ops *dma_ops;
void *dma_data;
#ifdef CONFIG_SWIOTLB
dma_addr_t max_direct_dma_addr;
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index 1765c37..8ca2b51 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -64,56 +64,14 @@ static inline unsigned long device_to_mask(struct device *dev)
}
/*
- * DMA operations are abstracted for G5 vs. i/pSeries, PCI vs. VIO
- */
-struct dma_mapping_ops {
- void * (*alloc_coherent)(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag);
- void (*free_coherent)(struct device *dev, size_t size,
- void *vaddr, dma_addr_t dma_handle);
- int (*map_sg)(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs);
- void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction,
- struct dma_attrs *attrs);
- int (*dma_supported)(struct device *dev, u64 mask);
- int (*set_dma_mask)(struct device *dev, u64 dma_mask);
- dma_addr_t (*map_page)(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs);
- void (*unmap_page)(struct device *dev,
- dma_addr_t dma_address, size_t size,
- enum dma_data_direction direction,
- struct dma_attrs *attrs);
-#ifdef CONFIG_PPC_NEED_DMA_SYNC_OPS
- void (*sync_single_range_for_cpu)(struct device *hwdev,
- dma_addr_t dma_handle, unsigned long offset,
- size_t size,
- enum dma_data_direction direction);
- void (*sync_single_range_for_device)(struct device *hwdev,
- dma_addr_t dma_handle, unsigned long offset,
- size_t size,
- enum dma_data_direction direction);
- void (*sync_sg_for_cpu)(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction direction);
- void (*sync_sg_for_device)(struct device *hwdev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction direction);
-#endif
-};
-
-/*
* Available generic sets of operations
*/
#ifdef CONFIG_PPC64
-extern struct dma_mapping_ops dma_iommu_ops;
+extern struct dma_map_ops dma_iommu_ops;
#endif
-extern struct dma_mapping_ops dma_direct_ops;
+extern struct dma_map_ops dma_direct_ops;
-static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
/* We don't handle the NULL dev case for ISA for now. We could
* do it via an out of line call but it is not needed for now. The
@@ -126,14 +84,14 @@ static inline struct dma_mapping_ops *get_dma_ops(struct device *dev)
return dev->archdata.dma_ops;
}
-static inline void set_dma_ops(struct device *dev, struct dma_mapping_ops *ops)
+static inline void set_dma_ops(struct device *dev, struct dma_map_ops *ops)
{
dev->archdata.dma_ops = ops;
}
static inline int dma_supported(struct device *dev, u64 mask)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
if (unlikely(dma_ops == NULL))
return 0;
@@ -147,7 +105,7 @@ static inline int dma_supported(struct device *dev, u64 mask)
static inline int dma_set_mask(struct device *dev, u64 dma_mask)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
if (unlikely(dma_ops == NULL))
return -EIO;
@@ -161,7 +119,7 @@ static inline int dma_set_mask(struct device *dev, u64 dma_mask)
/*
* map_/unmap_single actually call through to map/unmap_page now that all the
- * dma_mapping_ops have been converted over. We just have to get the page and
+ * dma_map_ops have been converted over. We just have to get the page and
* offset to pass through to map_page
*/
static inline dma_addr_t dma_map_single_attrs(struct device *dev,
@@ -170,7 +128,7 @@ static inline dma_addr_t dma_map_single_attrs(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -185,7 +143,7 @@ static inline void dma_unmap_single_attrs(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -198,7 +156,7 @@ static inline dma_addr_t dma_map_page_attrs(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -211,7 +169,7 @@ static inline void dma_unmap_page_attrs(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -222,7 +180,7 @@ static inline int dma_map_sg_attrs(struct device *dev, struct scatterlist *sg,
int nents, enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
return dma_ops->map_sg(dev, sg, nents, direction, attrs);
@@ -234,7 +192,7 @@ static inline void dma_unmap_sg_attrs(struct device *dev,
enum dma_data_direction direction,
struct dma_attrs *attrs)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
dma_ops->unmap_sg(dev, sg, nhwentries, direction, attrs);
@@ -243,7 +201,7 @@ static inline void dma_unmap_sg_attrs(struct device *dev,
static inline void *dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_handle, gfp_t flag)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
@@ -252,7 +210,7 @@ static inline void *dma_alloc_coherent(struct device *dev, size_t size,
static inline void dma_free_coherent(struct device *dev, size_t size,
void *cpu_addr, dma_addr_t dma_handle)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
@@ -304,7 +262,7 @@ static inline void dma_sync_single_for_cpu(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -317,7 +275,7 @@ static inline void dma_sync_single_for_device(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -330,7 +288,7 @@ static inline void dma_sync_sg_for_cpu(struct device *dev,
struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -342,7 +300,7 @@ static inline void dma_sync_sg_for_device(struct device *dev,
struct scatterlist *sgl, int nents,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -354,7 +312,7 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
dma_addr_t dma_handle, unsigned long offset, size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
@@ -367,7 +325,7 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
dma_addr_t dma_handle, unsigned long offset, size_t size,
enum dma_data_direction direction)
{
- struct dma_mapping_ops *dma_ops = get_dma_ops(dev);
+ struct dma_map_ops *dma_ops = get_dma_ops(dev);
BUG_ON(!dma_ops);
diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
index d9483c5..7ae46d7 100644
--- a/arch/powerpc/include/asm/pci.h
+++ b/arch/powerpc/include/asm/pci.h
@@ -61,8 +61,8 @@ static inline int pci_get_legacy_ide_irq(struct pci_dev *dev, int channel)
}
#ifdef CONFIG_PCI
-extern void set_pci_dma_ops(struct dma_mapping_ops *dma_ops);
-extern struct dma_mapping_ops *get_pci_dma_ops(void);
+extern void set_pci_dma_ops(struct dma_map_ops *dma_ops);
+extern struct dma_map_ops *get_pci_dma_ops(void);
#else /* CONFIG_PCI */
#define set_pci_dma_ops(d)
#define get_pci_dma_ops() NULL
diff --git a/arch/powerpc/include/asm/swiotlb.h b/arch/powerpc/include/asm/swiotlb.h
index 21ce0a3..8979d4c 100644
--- a/arch/powerpc/include/asm/swiotlb.h
+++ b/arch/powerpc/include/asm/swiotlb.h
@@ -13,7 +13,7 @@
#include <linux/swiotlb.h>
-extern struct dma_mapping_ops swiotlb_dma_ops;
+extern struct dma_map_ops swiotlb_dma_ops;
static inline void dma_mark_clean(void *addr, size_t size) {}
diff --git a/arch/powerpc/kernel/dma-iommu.c b/arch/powerpc/kernel/dma-iommu.c
index 2983ada..87ddb3f 100644
--- a/arch/powerpc/kernel/dma-iommu.c
+++ b/arch/powerpc/kernel/dma-iommu.c
@@ -89,7 +89,7 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
return 1;
}
-struct dma_mapping_ops dma_iommu_ops = {
+struct dma_map_ops dma_iommu_ops = {
.alloc_coherent = dma_iommu_alloc_coherent,
.free_coherent = dma_iommu_free_coherent,
.map_sg = dma_iommu_map_sg,
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index ca141e1..d1143a6 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -31,7 +31,7 @@ unsigned int ppc_swiotlb_enable;
* map_page, and unmap_page on highmem, use normal dma_ops
* for everything else.
*/
-struct dma_mapping_ops swiotlb_dma_ops = {
+struct dma_map_ops swiotlb_dma_ops = {
.alloc_coherent = dma_direct_alloc_coherent,
.free_coherent = dma_direct_free_coherent,
.map_sg = swiotlb_map_sg_attrs,
diff --git a/arch/powerpc/kernel/dma.c b/arch/powerpc/kernel/dma.c
index 20a60d6..3e8bb9a 100644
--- a/arch/powerpc/kernel/dma.c
+++ b/arch/powerpc/kernel/dma.c
@@ -140,7 +140,7 @@ static inline void dma_direct_sync_single_range(struct device *dev,
}
#endif
-struct dma_mapping_ops dma_direct_ops = {
+struct dma_map_ops dma_direct_ops = {
.alloc_coherent = dma_direct_alloc_coherent,
.free_coherent = dma_direct_free_coherent,
.map_sg = dma_direct_map_sg,
diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c
index 6e3f624..a4c8b38 100644
--- a/arch/powerpc/kernel/ibmebus.c
+++ b/arch/powerpc/kernel/ibmebus.c
@@ -127,7 +127,7 @@ static int ibmebus_dma_supported(struct device *dev, u64 mask)
return 1;
}
-static struct dma_mapping_ops ibmebus_dma_ops = {
+static struct dma_map_ops ibmebus_dma_ops = {
.alloc_coherent = ibmebus_alloc_coherent,
.free_coherent = ibmebus_free_coherent,
.map_sg = ibmebus_map_sg,
diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 5a56e97..7585f1f 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -50,14 +50,14 @@ resource_size_t isa_mem_base;
unsigned int ppc_pci_flags = 0;
-static struct dma_mapping_ops *pci_dma_ops = &dma_direct_ops;
+static struct dma_map_ops *pci_dma_ops = &dma_direct_ops;
-void set_pci_dma_ops(struct dma_mapping_ops *dma_ops)
+void set_pci_dma_ops(struct dma_map_ops *dma_ops)
{
pci_dma_ops = dma_ops;
}
-struct dma_mapping_ops *get_pci_dma_ops(void)
+struct dma_map_ops *get_pci_dma_ops(void)
{
return pci_dma_ops;
}
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 819e59f..bc7b41e 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -601,7 +601,7 @@ static void vio_dma_iommu_unmap_sg(struct device *dev,
vio_cmo_dealloc(viodev, alloc_size);
}
-struct dma_mapping_ops vio_dma_mapping_ops = {
+struct dma_map_ops vio_dma_mapping_ops = {
.alloc_coherent = vio_dma_iommu_alloc_coherent,
.free_coherent = vio_dma_iommu_free_coherent,
.map_sg = vio_dma_iommu_map_sg,
diff --git a/arch/powerpc/platforms/cell/iommu.c b/arch/powerpc/platforms/cell/iommu.c
index 5b34fc2..416db17 100644
--- a/arch/powerpc/platforms/cell/iommu.c
+++ b/arch/powerpc/platforms/cell/iommu.c
@@ -642,7 +642,7 @@ static int dma_fixed_dma_supported(struct device *dev, u64 mask)
static int dma_set_mask_and_switch(struct device *dev, u64 dma_mask);
-struct dma_mapping_ops dma_iommu_fixed_ops = {
+struct dma_map_ops dma_iommu_fixed_ops = {
.alloc_coherent = dma_fixed_alloc_coherent,
.free_coherent = dma_fixed_free_coherent,
.map_sg = dma_fixed_map_sg,
diff --git a/arch/powerpc/platforms/ps3/system-bus.c b/arch/powerpc/platforms/ps3/system-bus.c
index 3f763c5..02ddcc2 100644
--- a/arch/powerpc/platforms/ps3/system-bus.c
+++ b/arch/powerpc/platforms/ps3/system-bus.c
@@ -694,7 +694,7 @@ static int ps3_dma_supported(struct device *_dev, u64 mask)
return mask >= DMA_BIT_MASK(32);
}
-static struct dma_mapping_ops ps3_sb_dma_ops = {
+static struct dma_map_ops ps3_sb_dma_ops = {
.alloc_coherent = ps3_alloc_coherent,
.free_coherent = ps3_free_coherent,
.map_sg = ps3_sb_map_sg,
@@ -704,7 +704,7 @@ static struct dma_mapping_ops ps3_sb_dma_ops = {
.unmap_page = ps3_unmap_page,
};
-static struct dma_mapping_ops ps3_ioc0_dma_ops = {
+static struct dma_map_ops ps3_ioc0_dma_ops = {
.alloc_coherent = ps3_alloc_coherent,
.free_coherent = ps3_free_coherent,
.map_sg = ps3_ioc0_map_sg,
--
1.6.0.6
^ permalink raw reply related
* Re: [PATCH 4/20] powerpc/mm: Add opcode definitions for tlbivax and tlbsrx.
From: Kumar Gala @ 2009-07-24 4:52 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev
In-Reply-To: <1248387158.25467.3.camel@pasglop>
On Jul 23, 2009, at 5:12 PM, Benjamin Herrenschmidt wrote:
> On Thu, 2009-07-23 at 10:55 -0500, Kumar Gala wrote:
>> On Jul 23, 2009, at 12:59 AM, Benjamin Herrenschmidt wrote:
>>
>>> This adds the opcode definitions to ppc-opcode.h for the two
>>> instructions
>>> tlbivax and tlbsrx. as defined by Book3E 2.06
>>>
>>> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
>>> ---
>>>
>>> arch/powerpc/include/asm/ppc-opcode.h | 6 ++++++
>>> 1 file changed, 6 insertions(+)
>>
>> Do we really have binutils that don't have tlbivax properly at this
>> point?
>
> I don't know for sure, I like being consistent with the rest though
> and so I use those macros for all those MMU opcodes. Also means that
> I have no problem building with my current toolchain without passing
> a specific -mcpu option or anything like that :-)
>
> We can change that back later if you want.
ok, just wondering.. at some point we should decide which way we want
to go, since we use "tlbivax" today on e500/fsl-booke.
- k
^ permalink raw reply
* Re: BUG in dma-mapping.h:218 // MESH SCSI driver not working
From: Benjamin Herrenschmidt @ 2009-07-24 8:52 UTC (permalink / raw)
To: Stef Simoens; +Cc: linuxppc-dev
In-Reply-To: <4A68E1CE.4040307@scarlet.be>
On Fri, 2009-07-24 at 00:18 +0200, Stef Simoens wrote:
> I tried the latest 2.6.31-rc3-git3 (without any other patch).
> However, I have the same behaviour as the patched 2.6.30 (so: no BUG,
> but the mesh_abort messages).
>
> Anybody knows what's going wrong, and how to fix it? I've read the
> history of this list of June and July ... but I didn't find any other
> reports of the problem I'm encountering...
>
Would it be possible for you to roughly find out at what kernel version
it stopped working ? (Some kernels may need my patch to avoid crashing)
I have a machine with a MESH here that -appears- to work, at least it
did last time I tried it which was a couple of weeks ago, I'll try again
just to be sure.
Cheers,
Ben.
^ permalink raw reply
* [PATCH 0/20] powerpc: base 64-bit Book3E processor support (v2)
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
Here is a series of patches that implement some basic support
for 64-bit Book3E processors that comply to architecture 2.06.
There is no specific processor announced yet. The patches make
some shortcut which means they currently rely on an implementation
that supports MMU v2 with support for the "HES" feature (HW entry
select) and with support for the "TLB reservation" feature. They
also assume a single unified TLB array. I shouldn't be very hard
to implement support for other variants of the architecture on
top of this though.
The current set of patch has no proper support yet for hugetlb,
nor for "special" interrupt levels (debug, critical and machine
check). Some minimal support for debug/critical levels is provided
specifically for the "Debug" interrupt (single step etc...) only
when it occurs from within user space code.
The intend is to merge these in 2.6.32. They rely on pretty much
all the other patches I've been posting lately including the
generic changes to add the virtual address argument to pte_free_tlb.
v2. Various fixes, some addressing comments recieved and a whole
bunch fixing other issues including breakage of existing platforms
^ permalink raw reply
* [PATCH 1/20] powerpc/mm: Fix misplaced #endif in pgtable-ppc64-64k.h
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
A misplaced #endif causes more definitions than intended to be
protected by #ifndef __ASSEMBLY__. This breaks upcoming 64-bit
BookE support patch when using 64k pages.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/pgtable-ppc64-64k.h | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
--- linux-work.orig/arch/powerpc/include/asm/pgtable-ppc64-64k.h 2009-07-22 11:45:34.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/pgtable-ppc64-64k.h 2009-07-22 11:45:47.000000000 +1000
@@ -10,10 +10,10 @@
#define PGD_INDEX_SIZE 4
#ifndef __ASSEMBLY__
-
#define PTE_TABLE_SIZE (sizeof(real_pte_t) << PTE_INDEX_SIZE)
#define PMD_TABLE_SIZE (sizeof(pmd_t) << PMD_INDEX_SIZE)
#define PGD_TABLE_SIZE (sizeof(pgd_t) << PGD_INDEX_SIZE)
+#endif /* __ASSEMBLY__ */
#define PTRS_PER_PTE (1 << PTE_INDEX_SIZE)
#define PTRS_PER_PMD (1 << PMD_INDEX_SIZE)
@@ -32,8 +32,6 @@
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
-#endif /* __ASSEMBLY__ */
-
/* Bits to mask out from a PMD to get to the PTE page */
#define PMD_MASKED_BITS 0x1ff
/* Bits to mask out from a PGD/PUD to get to the PMD page */
^ permalink raw reply
* [PATCH 2/20] powerpc/of: Remove useless register save/restore when calling OF back
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
enter_prom() used to save and restore registers such as CTR, XER etc..
which are volatile, or SRR0,1... which we don't care about. This
removes a bunch of useless code and while at it turns an mtmsrd into
an MTMSRD macro which will be useful to Book3E.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/entry_64.S | 38 ++++++--------------------------------
1 file changed, 6 insertions(+), 32 deletions(-)
--- linux-work.orig/arch/powerpc/kernel/entry_64.S 2009-07-22 15:20:26.000000000 +1000
+++ linux-work/arch/powerpc/kernel/entry_64.S 2009-07-22 15:22:44.000000000 +1000
@@ -823,30 +823,17 @@ _GLOBAL(enter_prom)
* of all registers that it saves. We therefore save those registers
* PROM might touch to the stack. (r0, r3-r13 are caller saved)
*/
- SAVE_8GPRS(2, r1)
+ SAVE_GPR(2, r1)
SAVE_GPR(13, r1)
SAVE_8GPRS(14, r1)
SAVE_10GPRS(22, r1)
- mfcr r4
- std r4,_CCR(r1)
- mfctr r5
- std r5,_CTR(r1)
- mfspr r6,SPRN_XER
- std r6,_XER(r1)
- mfdar r7
- std r7,_DAR(r1)
- mfdsisr r8
- std r8,_DSISR(r1)
- mfsrr0 r9
- std r9,_SRR0(r1)
- mfsrr1 r10
- std r10,_SRR1(r1)
+ mfcr r10
mfmsr r11
+ std r10,_CCR(r1)
std r11,_MSR(r1)
/* Get the PROM entrypoint */
- ld r0,GPR4(r1)
- mtlr r0
+ mtlr r4
/* Switch MSR to 32 bits mode
*/
@@ -860,8 +847,7 @@ _GLOBAL(enter_prom)
mtmsrd r11
isync
- /* Restore arguments & enter PROM here... */
- ld r3,GPR3(r1)
+ /* Enter PROM here... */
blrl
/* Just make sure that r1 top 32 bits didn't get
@@ -871,7 +857,7 @@ _GLOBAL(enter_prom)
/* Restore the MSR (back to 64 bits) */
ld r0,_MSR(r1)
- mtmsrd r0
+ MTMSRD(r0)
isync
/* Restore other registers */
@@ -881,18 +867,6 @@ _GLOBAL(enter_prom)
REST_10GPRS(22, r1)
ld r4,_CCR(r1)
mtcr r4
- ld r5,_CTR(r1)
- mtctr r5
- ld r6,_XER(r1)
- mtspr SPRN_XER,r6
- ld r7,_DAR(r1)
- mtdar r7
- ld r8,_DSISR(r1)
- mtdsisr r8
- ld r9,_SRR0(r1)
- mtsrr0 r9
- ld r10,_SRR1(r1)
- mtsrr1 r10
addi r1,r1,PROM_FRAME_SIZE
ld r0,16(r1)
^ permalink raw reply
* [PATCH 3/20] powerpc/mm: Add HW threads support to no_hash TLB management
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
The current "no hash" MMU context management code is written with
the assumption that one CPU == one TLB. This is not the case on
implementations that support HW multithreading, where several
linux CPUs can share the same TLB.
This adds some basic support for this to our context management
and our TLB flushing code.
It also cleans up the optional debugging output a bit
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/cputhreads.h | 16 +++++
arch/powerpc/mm/mmu_context_nohash.c | 93 ++++++++++++++++++++++------------
arch/powerpc/mm/tlb_nohash.c | 10 ++-
3 files changed, 86 insertions(+), 33 deletions(-)
--- linux-work.orig/arch/powerpc/mm/mmu_context_nohash.c 2009-07-21 12:43:27.000000000 +1000
+++ linux-work/arch/powerpc/mm/mmu_context_nohash.c 2009-07-21 12:56:16.000000000 +1000
@@ -25,10 +25,20 @@
* also clear mm->cpu_vm_mask bits when processes are migrated
*/
-#undef DEBUG
-#define DEBUG_STEAL_ONLY
-#undef DEBUG_MAP_CONSISTENCY
-/*#define DEBUG_CLAMP_LAST_CONTEXT 15 */
+#define DEBUG_MAP_CONSISTENCY
+#define DEBUG_CLAMP_LAST_CONTEXT 31
+//#define DEBUG_HARDER
+
+/* We don't use DEBUG because it tends to be compiled in always nowadays
+ * and this would generate way too much output
+ */
+#ifdef DEBUG_HARDER
+#define pr_hard(args...) printk(KERN_DEBUG args)
+#define pr_hardcont(args...) printk(KERN_CONT args)
+#else
+#define pr_hard(args...) do { } while(0)
+#define pr_hardcont(args...) do { } while(0)
+#endif
#include <linux/kernel.h>
#include <linux/mm.h>
@@ -71,7 +81,7 @@ static DEFINE_SPINLOCK(context_lock);
static unsigned int steal_context_smp(unsigned int id)
{
struct mm_struct *mm;
- unsigned int cpu, max;
+ unsigned int cpu, max, i;
max = last_context - first_context;
@@ -89,15 +99,22 @@ static unsigned int steal_context_smp(un
id = first_context;
continue;
}
- pr_devel("[%d] steal context %d from mm @%p\n",
- smp_processor_id(), id, mm);
+ pr_hardcont(" | steal %d from 0x%p", id, mm);
/* Mark this mm has having no context anymore */
mm->context.id = MMU_NO_CONTEXT;
- /* Mark it stale on all CPUs that used this mm */
- for_each_cpu(cpu, mm_cpumask(mm))
- __set_bit(id, stale_map[cpu]);
+ /* Mark it stale on all CPUs that used this mm. For threaded
+ * implementations, we set it on all threads on each core
+ * represented in the mask. A future implementation will use
+ * a core map instead but this will do for now.
+ */
+ for_each_cpu(cpu, mm_cpumask(mm)) {
+ for (i = cpu_first_thread_in_core(cpu);
+ i <= cpu_last_thread_in_core(cpu); i++)
+ __set_bit(id, stale_map[i]);
+ cpu = i - 1;
+ }
return id;
}
@@ -126,7 +143,7 @@ static unsigned int steal_context_up(uns
/* Pick up the victim mm */
mm = context_mm[id];
- pr_devel("[%d] steal context %d from mm @%p\n", cpu, id, mm);
+ pr_hardcont(" | steal %d from 0x%p", id, mm);
/* Flush the TLB for that context */
local_flush_tlb_mm(mm);
@@ -179,19 +196,14 @@ void switch_mmu_context(struct mm_struct
/* No lockless fast path .. yet */
spin_lock(&context_lock);
-#ifndef DEBUG_STEAL_ONLY
- pr_devel("[%d] activating context for mm @%p, active=%d, id=%d\n",
- cpu, next, next->context.active, next->context.id);
-#endif
+ pr_hard("[%d] activating context for mm @%p, active=%d, id=%d",
+ cpu, next, next->context.active, next->context.id);
#ifdef CONFIG_SMP
/* Mark us active and the previous one not anymore */
next->context.active++;
if (prev) {
-#ifndef DEBUG_STEAL_ONLY
- pr_devel(" old context %p active was: %d\n",
- prev, prev->context.active);
-#endif
+ pr_hardcont(" (old=0x%p a=%d)", prev, prev->context.active);
WARN_ON(prev->context.active < 1);
prev->context.active--;
}
@@ -201,8 +213,14 @@ void switch_mmu_context(struct mm_struct
/* If we already have a valid assigned context, skip all that */
id = next->context.id;
- if (likely(id != MMU_NO_CONTEXT))
+ if (likely(id != MMU_NO_CONTEXT)) {
+#ifdef DEBUG_MAP_CONSISTENCY
+ if (context_mm[id] != next)
+ pr_err("MMU: mm 0x%p has id %d but context_mm[%d] says 0x%p\n",
+ next, id, id, context_mm[id]);
+#endif
goto ctxt_ok;
+ }
/* We really don't have a context, let's try to acquire one */
id = next_context;
@@ -234,11 +252,7 @@ void switch_mmu_context(struct mm_struct
next_context = id + 1;
context_mm[id] = next;
next->context.id = id;
-
-#ifndef DEBUG_STEAL_ONLY
- pr_devel("[%d] picked up new id %d, nrf is now %d\n",
- cpu, id, nr_free_contexts);
-#endif
+ pr_hardcont(" | new id=%d,nrf=%d", id, nr_free_contexts);
context_check_map();
ctxt_ok:
@@ -247,15 +261,20 @@ void switch_mmu_context(struct mm_struct
* local TLB for it and unmark it before we use it
*/
if (test_bit(id, stale_map[cpu])) {
- pr_devel("[%d] flushing stale context %d for mm @%p !\n",
- cpu, id, next);
+ pr_hardcont(" | stale flush %d [%d..%d]",
+ id, cpu_first_thread_in_core(cpu),
+ cpu_last_thread_in_core(cpu));
+
local_flush_tlb_mm(next);
/* XXX This clear should ultimately be part of local_flush_tlb_mm */
- __clear_bit(id, stale_map[cpu]);
+ for (cpu = cpu_first_thread_in_core(cpu);
+ cpu <= cpu_last_thread_in_core(cpu); cpu++)
+ __clear_bit(id, stale_map[cpu]);
}
/* Flick the MMU and release lock */
+ pr_hardcont(" -> %d\n", id);
set_context(id, next->pgd);
spin_unlock(&context_lock);
}
@@ -265,6 +284,8 @@ void switch_mmu_context(struct mm_struct
*/
int init_new_context(struct task_struct *t, struct mm_struct *mm)
{
+ pr_hard("initing context for mm @%p\n", mm);
+
mm->context.id = MMU_NO_CONTEXT;
mm->context.active = 0;
@@ -304,7 +325,9 @@ static int __cpuinit mmu_context_cpu_not
unsigned long action, void *hcpu)
{
unsigned int cpu = (unsigned int)(long)hcpu;
-
+#ifdef CONFIG_HOTPLUG_CPU
+ struct task_struct *p;
+#endif
/* We don't touch CPU 0 map, it's allocated at aboot and kept
* around forever
*/
@@ -323,8 +346,16 @@ static int __cpuinit mmu_context_cpu_not
pr_devel("MMU: Freeing stale context map for CPU %d\n", cpu);
kfree(stale_map[cpu]);
stale_map[cpu] = NULL;
- break;
-#endif
+
+ /* We also clear the cpu_vm_mask bits of CPUs going away */
+ read_lock(&tasklist_lock);
+ for_each_process(p) {
+ if (p->mm)
+ cpu_mask_clear_cpu(cpu, mm_cpumask(p->mm));
+ }
+ read_unlock(&tasklist_lock);
+ break;
+#endif /* CONFIG_HOTPLUG_CPU */
}
return NOTIFY_OK;
}
Index: linux-work/arch/powerpc/include/asm/cputhreads.h
===================================================================
--- linux-work.orig/arch/powerpc/include/asm/cputhreads.h 2009-07-21 12:43:27.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/cputhreads.h 2009-07-21 12:56:16.000000000 +1000
@@ -5,6 +5,15 @@
/*
* Mapping of threads to cores
+ *
+ * Note: This implementation is limited to a power of 2 number of
+ * threads per core and the same number for each core in the system
+ * (though it would work if some processors had less threads as long
+ * as the CPU numbers are still allocated, just not brought offline).
+ *
+ * However, the API allows for a different implementation in the future
+ * if needed, as long as you only use the functions and not the variables
+ * directly.
*/
#ifdef CONFIG_SMP
@@ -67,5 +76,12 @@ static inline int cpu_first_thread_in_co
return cpu & ~(threads_per_core - 1);
}
+static inline int cpu_last_thread_in_core(int cpu)
+{
+ return cpu | (threads_per_core - 1);
+}
+
+
+
#endif /* _ASM_POWERPC_CPUTHREADS_H */
Index: linux-work/arch/powerpc/mm/tlb_nohash.c
===================================================================
--- linux-work.orig/arch/powerpc/mm/tlb_nohash.c 2009-07-21 12:43:31.000000000 +1000
+++ linux-work/arch/powerpc/mm/tlb_nohash.c 2009-07-21 12:57:21.000000000 +1000
@@ -87,6 +87,12 @@ EXPORT_SYMBOL(local_flush_tlb_page);
static DEFINE_SPINLOCK(tlbivax_lock);
+static int mm_is_core_local(struct mm_struct *mm)
+{
+ return cpumask_subset(mm_cpumask(mm),
+ topology_thread_cpumask(smp_processor_id()));
+}
+
struct tlb_flush_param {
unsigned long addr;
unsigned int pid;
@@ -131,7 +137,7 @@ void flush_tlb_mm(struct mm_struct *mm)
pid = mm->context.id;
if (unlikely(pid == MMU_NO_CONTEXT))
goto no_context;
- if (!cpumask_equal(mm_cpumask(mm), cpumask_of(smp_processor_id()))) {
+ if (!mm_is_core_local(mm)) {
struct tlb_flush_param p = { .pid = pid };
/* Ignores smp_processor_id() even if set. */
smp_call_function_many(mm_cpumask(mm),
@@ -153,7 +159,7 @@ void flush_tlb_page(struct vm_area_struc
if (unlikely(pid == MMU_NO_CONTEXT))
goto bail;
cpu_mask = mm_cpumask(vma->vm_mm);
- if (!cpumask_equal(cpu_mask, cpumask_of(smp_processor_id()))) {
+ if (!mm_is_core_local(mm)) {
/* If broadcast tlbivax is supported, use it */
if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) {
int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL);
^ permalink raw reply
* [PATCH 4/20] powerpc/mm: Add opcode definitions for tlbivax and tlbsrx.
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
This adds the opcode definitions to ppc-opcode.h for the two instructions
tlbivax and tlbsrx. as defined by Book3E 2.06
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/ppc-opcode.h | 6 ++++++
1 file changed, 6 insertions(+)
--- linux-work.orig/arch/powerpc/include/asm/ppc-opcode.h 2009-07-22 15:25:45.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/ppc-opcode.h 2009-07-22 15:26:05.000000000 +1000
@@ -48,6 +48,8 @@
#define PPC_INST_TLBIE 0x7c000264
#define PPC_INST_TLBILX 0x7c000024
#define PPC_INST_WAIT 0x7c00007c
+#define PPC_INST_TLBIVAX 0x7c000624
+#define PPC_INST_TLBSRX_DOT 0x7c0006a5
/* macros to insert fields into opcodes */
#define __PPC_RA(a) (((a) & 0x1f) << 16)
@@ -76,6 +78,10 @@
__PPC_WC(w))
#define PPC_TLBIE(lp,a) stringify_in_c(.long PPC_INST_TLBIE | \
__PPC_RB(a) | __PPC_RS(lp))
+#define PPC_TLBSRX_DOT(a,b) stringify_in_c(.long PPC_INST_TLBSRX_DOT | \
+ __PPC_RA(a) | __PPC_RB(b))
+#define PPC_TLBIVAX(a,b) stringify_in_c(.long PPC_INST_TLBIVAX | \
+ __PPC_RA(a) | __PPC_RB(b))
/*
* Define what the VSX XX1 form instructions will look like, then add
^ permalink raw reply
* [PATCH 5/20] powerpc/mm: Add more bit definitions for Book3E MMU registers
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
This adds various additional bit definitions for various MMU related
SPRs used on Book3E.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/include/asm/mmu-book3e.h | 168 ++++++++++++++++++++++++----------
1 file changed, 119 insertions(+), 49 deletions(-)
--- linux-work.orig/arch/powerpc/include/asm/mmu-book3e.h 2009-07-22 15:19:22.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/mmu-book3e.h 2009-07-22 15:30:58.000000000 +1000
@@ -38,58 +38,128 @@
#define BOOK3E_PAGESZ_1TB 30
#define BOOK3E_PAGESZ_2TB 31
-#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000)
-#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000)
-#define MAS0_NV(x) ((x) & 0x00000FFF)
-
-#define MAS1_VALID 0x80000000
-#define MAS1_IPROT 0x40000000
-#define MAS1_TID(x) ((x << 16) & 0x3FFF0000)
-#define MAS1_IND 0x00002000
-#define MAS1_TS 0x00001000
-#define MAS1_TSIZE(x) ((x << 7) & 0x00000F80)
-
-#define MAS2_EPN 0xFFFFF000
-#define MAS2_X0 0x00000040
-#define MAS2_X1 0x00000020
-#define MAS2_W 0x00000010
-#define MAS2_I 0x00000008
-#define MAS2_M 0x00000004
-#define MAS2_G 0x00000002
-#define MAS2_E 0x00000001
+/* MAS registers bit definitions */
+
+#define MAS0_TLBSEL(x) ((x << 28) & 0x30000000)
+#define MAS0_ESEL(x) ((x << 16) & 0x0FFF0000)
+#define MAS0_NV(x) ((x) & 0x00000FFF)
+#define MAS0_HES 0x00004000
+#define MAS0_WQ_ALLWAYS 0x00000000
+#define MAS0_WQ_COND 0x00001000
+#define MAS0_WQ_CLR_RSRV 0x00002000
+
+#define MAS1_VALID 0x80000000
+#define MAS1_IPROT 0x40000000
+#define MAS1_TID(x) ((x << 16) & 0x3FFF0000)
+#define MAS1_IND 0x00002000
+#define MAS1_TS 0x00001000
+#define MAS1_TSIZE_MASK 0x00000f80
+#define MAS1_TSIZE_SHIFT 7
+#define MAS1_TSIZE(x) ((x << MAS1_TSIZE_SHIFT) & MAS1_TSIZE_MASK)
+
+#define MAS2_EPN 0xFFFFF000
+#define MAS2_X0 0x00000040
+#define MAS2_X1 0x00000020
+#define MAS2_W 0x00000010
+#define MAS2_I 0x00000008
+#define MAS2_M 0x00000004
+#define MAS2_G 0x00000002
+#define MAS2_E 0x00000001
#define MAS2_EPN_MASK(size) (~0 << (size + 10))
#define MAS2_VAL(addr, size, flags) ((addr) & MAS2_EPN_MASK(size) | (flags))
-#define MAS3_RPN 0xFFFFF000
-#define MAS3_U0 0x00000200
-#define MAS3_U1 0x00000100
-#define MAS3_U2 0x00000080
-#define MAS3_U3 0x00000040
-#define MAS3_UX 0x00000020
-#define MAS3_SX 0x00000010
-#define MAS3_UW 0x00000008
-#define MAS3_SW 0x00000004
-#define MAS3_UR 0x00000002
-#define MAS3_SR 0x00000001
-
-#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
-#define MAS4_INDD 0x00008000
-#define MAS4_TSIZED(x) MAS1_TSIZE(x)
-#define MAS4_X0D 0x00000040
-#define MAS4_X1D 0x00000020
-#define MAS4_WD 0x00000010
-#define MAS4_ID 0x00000008
-#define MAS4_MD 0x00000004
-#define MAS4_GD 0x00000002
-#define MAS4_ED 0x00000001
-
-#define MAS6_SPID0 0x3FFF0000
-#define MAS6_SPID1 0x00007FFE
-#define MAS6_ISIZE(x) MAS1_TSIZE(x)
-#define MAS6_SAS 0x00000001
-#define MAS6_SPID MAS6_SPID0
-
-#define MAS7_RPN 0xFFFFFFFF
+#define MAS3_RPN 0xFFFFF000
+#define MAS3_U0 0x00000200
+#define MAS3_U1 0x00000100
+#define MAS3_U2 0x00000080
+#define MAS3_U3 0x00000040
+#define MAS3_UX 0x00000020
+#define MAS3_SX 0x00000010
+#define MAS3_UW 0x00000008
+#define MAS3_SW 0x00000004
+#define MAS3_UR 0x00000002
+#define MAS3_SR 0x00000001
+#define MAS3_SPSIZE 0x0000003e
+#define MAS3_SPSIZE_SHIFT 1
+
+#define MAS4_TLBSELD(x) MAS0_TLBSEL(x)
+#define MAS4_INDD 0x00008000 /* Default IND */
+#define MAS4_TSIZED(x) MAS1_TSIZE(x)
+#define MAS4_X0D 0x00000040
+#define MAS4_X1D 0x00000020
+#define MAS4_WD 0x00000010
+#define MAS4_ID 0x00000008
+#define MAS4_MD 0x00000004
+#define MAS4_GD 0x00000002
+#define MAS4_ED 0x00000001
+#define MAS4_WIMGED_MASK 0x0000001f /* Default WIMGE */
+#define MAS4_WIMGED_SHIFT 0
+#define MAS4_VLED MAS4_X1D /* Default VLE */
+#define MAS4_ACMD 0x000000c0 /* Default ACM */
+#define MAS4_ACMD_SHIFT 6
+#define MAS4_TSIZED_MASK 0x00000f80 /* Default TSIZE */
+#define MAS4_TSIZED_SHIFT 7
+
+#define MAS6_SPID0 0x3FFF0000
+#define MAS6_SPID1 0x00007FFE
+#define MAS6_ISIZE(x) MAS1_TSIZE(x)
+#define MAS6_SAS 0x00000001
+#define MAS6_SPID MAS6_SPID0
+#define MAS6_SIND 0x00000002 /* Indirect page */
+#define MAS6_SIND_SHIFT 1
+#define MAS6_SPID_MASK 0x3fff0000
+#define MAS6_SPID_SHIFT 16
+#define MAS6_ISIZE_MASK 0x00000f80
+#define MAS6_ISIZE_SHIFT 7
+
+#define MAS7_RPN 0xFFFFFFFF
+
+/* TLBnCFG encoding */
+#define TLBnCFG_N_ENTRY 0x00000fff /* number of entries */
+#define TLBnCFG_HES 0x00002000 /* HW select supported */
+#define TLBnCFG_IPROT 0x00008000 /* IPROT supported */
+#define TLBnCFG_GTWE 0x00010000 /* Guest can write */
+#define TLBnCFG_IND 0x00020000 /* IND entries supported */
+#define TLBnCFG_PT 0x00040000 /* Can load from page table */
+#define TLBnCFG_ASSOC 0xff000000 /* Associativity */
+
+/* TLBnPS encoding */
+#define TLBnPS_4K 0x00000004
+#define TLBnPS_8K 0x00000008
+#define TLBnPS_16K 0x00000010
+#define TLBnPS_32K 0x00000020
+#define TLBnPS_64K 0x00000040
+#define TLBnPS_128K 0x00000080
+#define TLBnPS_256K 0x00000100
+#define TLBnPS_512K 0x00000200
+#define TLBnPS_1M 0x00000400
+#define TLBnPS_2M 0x00000800
+#define TLBnPS_4M 0x00001000
+#define TLBnPS_8M 0x00002000
+#define TLBnPS_16M 0x00004000
+#define TLBnPS_32M 0x00008000
+#define TLBnPS_64M 0x00010000
+#define TLBnPS_128M 0x00020000
+#define TLBnPS_256M 0x00040000
+#define TLBnPS_512M 0x00080000
+#define TLBnPS_1G 0x00100000
+#define TLBnPS_2G 0x00200000
+#define TLBnPS_4G 0x00400000
+#define TLBnPS_8G 0x00800000
+#define TLBnPS_16G 0x01000000
+#define TLBnPS_32G 0x02000000
+#define TLBnPS_64G 0x04000000
+#define TLBnPS_128G 0x08000000
+#define TLBnPS_256G 0x10000000
+
+/* tlbilx action encoding */
+#define TLBILX_T_ALL 0
+#define TLBILX_T_TID 1
+#define TLBILX_T_FULLMATCH 3
+#define TLBILX_T_CLASS0 4
+#define TLBILX_T_CLASS1 5
+#define TLBILX_T_CLASS2 6
+#define TLBILX_T_CLASS3 7
#ifndef __ASSEMBLY__
^ permalink raw reply
* [PATCH 6/20] powerpc/mm: Add support for early ioremap on non-hash 64-bit processors
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
This adds some code to do early ioremap's using page tables instead of
bolting entries in the hash table. This will be used by the upcoming
64-bits BookE port.
The patch also changes the test for early vs. late ioremap to use
slab_is_available() instead of our old hackish mem_init_done.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/mm/pgtable_64.c | 59 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 54 insertions(+), 5 deletions(-)
--- linux-work.orig/arch/powerpc/mm/pgtable_64.c 2009-07-22 15:49:09.000000000 +1000
+++ linux-work/arch/powerpc/mm/pgtable_64.c 2009-07-23 14:56:39.000000000 +1000
@@ -33,6 +33,8 @@
#include <linux/stddef.h>
#include <linux/vmalloc.h>
#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/lmb.h>
#include <asm/pgalloc.h>
#include <asm/page.h>
@@ -55,19 +57,36 @@
unsigned long ioremap_bot = IOREMAP_BASE;
+
+#ifdef CONFIG_PPC_MMU_NOHASH
+static void *early_alloc_pgtable(unsigned long size)
+{
+ void *pt;
+
+ if (init_bootmem_done)
+ pt = __alloc_bootmem(size, size, __pa(MAX_DMA_ADDRESS));
+ else
+ pt = __va(lmb_alloc_base(size, size,
+ __pa(MAX_DMA_ADDRESS)));
+ memset(pt, 0, size);
+
+ return pt;
+}
+#endif /* CONFIG_PPC_MMU_NOHASH */
+
/*
- * map_io_page currently only called by __ioremap
- * map_io_page adds an entry to the ioremap page table
+ * map_kernel_page currently only called by __ioremap
+ * map_kernel_page adds an entry to the ioremap page table
* and adds an entry to the HPT, possibly bolting it
*/
-static int map_io_page(unsigned long ea, unsigned long pa, int flags)
+static int map_kernel_page(unsigned long ea, unsigned long pa, int flags)
{
pgd_t *pgdp;
pud_t *pudp;
pmd_t *pmdp;
pte_t *ptep;
- if (mem_init_done) {
+ if (slab_is_available()) {
pgdp = pgd_offset_k(ea);
pudp = pud_alloc(&init_mm, pgdp, ea);
if (!pudp)
@@ -81,6 +100,35 @@ static int map_io_page(unsigned long ea,
set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
__pgprot(flags)));
} else {
+#ifdef CONFIG_PPC_MMU_NOHASH
+ /* Warning ! This will blow up if bootmem is not initialized
+ * which our ppc64 code is keen to do that, we'll need to
+ * fix it and/or be more careful
+ */
+ pgdp = pgd_offset_k(ea);
+#ifdef PUD_TABLE_SIZE
+ if (pgd_none(*pgdp)) {
+ pudp = early_alloc_pgtable(PUD_TABLE_SIZE);
+ BUG_ON(pudp == NULL);
+ pgd_populate(&init_mm, pgdp, pudp);
+ }
+#endif /* PUD_TABLE_SIZE */
+ pudp = pud_offset(pgdp, ea);
+ if (pud_none(*pudp)) {
+ pmdp = early_alloc_pgtable(PMD_TABLE_SIZE);
+ BUG_ON(pmdp == NULL);
+ pud_populate(&init_mm, pudp, pmdp);
+ }
+ pmdp = pmd_offset(pudp, ea);
+ if (!pmd_present(*pmdp)) {
+ ptep = early_alloc_pgtable(PAGE_SIZE);
+ BUG_ON(ptep == NULL);
+ pmd_populate_kernel(&init_mm, pmdp, ptep);
+ }
+ ptep = pte_offset_kernel(pmdp, ea);
+ set_pte_at(&init_mm, ea, ptep, pfn_pte(pa >> PAGE_SHIFT,
+ __pgprot(flags)));
+#else /* CONFIG_PPC_MMU_NOHASH */
/*
* If the mm subsystem is not fully up, we cannot create a
* linux page table entry for this mapping. Simply bolt an
@@ -93,6 +141,7 @@ static int map_io_page(unsigned long ea,
"memory at %016lx !\n", pa);
return -ENOMEM;
}
+#endif /* !CONFIG_PPC_MMU_NOHASH */
}
return 0;
}
@@ -124,7 +173,7 @@ void __iomem * __ioremap_at(phys_addr_t
WARN_ON(size & ~PAGE_MASK);
for (i = 0; i < size; i += PAGE_SIZE)
- if (map_io_page((unsigned long)ea+i, pa+i, flags))
+ if (map_kernel_page((unsigned long)ea+i, pa+i, flags))
return NULL;
return (void __iomem *)ea;
^ permalink raw reply
* [PATCH 7/20] powerpc: Modify some ppc_asm.h macros to accomodate 64-bits Book3E
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
The way I intend to use tophys/tovirt on 64-bit BookE is different
from the "trick" that we currently play for 32-bit BookE so change
the condition of definition of these macros to make it so.
Also, make sure we only use rfid and mtmsrd instead of rfi and mtmsr
for 64-bit server processors, not all 64-bit processors.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
---
arch/powerpc/include/asm/ppc_asm.h | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)
--- linux-work.orig/arch/powerpc/include/asm/ppc_asm.h 2009-07-22 15:53:06.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/ppc_asm.h 2009-07-22 15:58:24.000000000 +1000
@@ -375,8 +375,15 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
#define PPC440EP_ERR42
#endif
-
-#if defined(CONFIG_BOOKE)
+/*
+ * toreal/fromreal/tophys/tovirt macros. 32-bit BookE makes them
+ * keep the address intact to be compatible with code shared with
+ * 32-bit classic.
+ *
+ * On the other hand, I find it useful to have them behave as expected
+ * by their name (ie always do the addition) on 64-bit BookE
+ */
+#if defined(CONFIG_BOOKE) && !defined(CONFIG_PPC64)
#define toreal(rd)
#define fromreal(rd)
@@ -426,10 +433,9 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
.previous
#endif
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_BOOK3S_64
#define RFI rfid
#define MTMSRD(r) mtmsrd r
-
#else
#define FIX_SRR1(ra, rb)
#ifndef CONFIG_40x
^ permalink raw reply
* [PATCH 8/20] powerpc/mm: Make low level TLB flush ops on BookE take additional args (v2)
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
We need to pass down whether the page is direct or indirect and we'll
need to pass the page size to _tlbil_va and _tlbivax_bcast
We also add a new low level _tlbil_pid_noind() which does a TLB flush
by PID but avoids flushing indirect entries if possible
This implements those new prototypes but defines them with inlines
or macros so that no additional arguments are actually passed on current
processors.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
v2. __tlbil_va() declaration had the wrong number of arguments
also remove a stray trailing semicolon
arch/powerpc/include/asm/tlbflush.h | 11 +++++++--
arch/powerpc/mm/mmu_decl.h | 16 +++++++++++--
arch/powerpc/mm/tlb_nohash.c | 42 ++++++++++++++++++++++++++----------
arch/powerpc/mm/tlb_nohash_low.S | 6 ++---
4 files changed, 56 insertions(+), 19 deletions(-)
--- linux-work.orig/arch/powerpc/include/asm/tlbflush.h 2009-07-24 16:24:08.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/tlbflush.h 2009-07-24 16:24:12.000000000 +1000
@@ -6,7 +6,7 @@
*
* - flush_tlb_mm(mm) flushes the specified mm context TLB's
* - flush_tlb_page(vma, vmaddr) flushes one page
- * - local_flush_tlb_mm(mm) flushes the specified mm context on
+ * - local_flush_tlb_mm(mm, full) flushes the specified mm context on
* the local processor
* - local_flush_tlb_page(vma, vmaddr) flushes one page on the local processor
* - flush_tlb_page_nohash(vma, vmaddr) flushes one page if SW loaded TLB
@@ -29,7 +29,8 @@
* specific tlbie's
*/
-#include <linux/mm.h>
+struct vm_area_struct;
+struct mm_struct;
#define MMU_NO_CONTEXT ((unsigned int)-1)
@@ -40,12 +41,18 @@ extern void flush_tlb_kernel_range(unsig
extern void local_flush_tlb_mm(struct mm_struct *mm);
extern void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+ int tsize, int ind);
+
#ifdef CONFIG_SMP
extern void flush_tlb_mm(struct mm_struct *mm);
extern void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr);
+extern void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+ int tsize, int ind);
#else
#define flush_tlb_mm(mm) local_flush_tlb_mm(mm)
#define flush_tlb_page(vma,addr) local_flush_tlb_page(vma,addr)
+#define __flush_tlb_page(mm,addr,p,i) __local_flush_tlb_page(mm,addr,p,i)
#endif
#define flush_tlb_page_nohash(vma,addr) flush_tlb_page(vma,addr)
Index: linux-work/arch/powerpc/mm/mmu_decl.h
===================================================================
--- linux-work.orig/arch/powerpc/mm/mmu_decl.h 2009-07-24 16:24:08.000000000 +1000
+++ linux-work/arch/powerpc/mm/mmu_decl.h 2009-07-24 17:04:57.000000000 +1000
@@ -36,21 +36,30 @@ static inline void _tlbil_pid(unsigned i
{
asm volatile ("sync; tlbia; isync" : : : "memory");
}
+#define _tlbil_pid_noind(pid) _tlbil_pid(pid)
+
#else /* CONFIG_40x || CONFIG_8xx */
extern void _tlbil_all(void);
extern void _tlbil_pid(unsigned int pid);
+#define _tlbil_pid_noind(pid) _tlbil_pid(pid)
#endif /* !(CONFIG_40x || CONFIG_8xx) */
/*
* On 8xx, we directly inline tlbie, on others, it's extern
*/
#ifdef CONFIG_8xx
-static inline void _tlbil_va(unsigned long address, unsigned int pid)
+static inline void _tlbil_va(unsigned long address, unsigned int pid,
+ unsigned int tsize, unsigned int ind)
{
asm volatile ("tlbie %0; sync" : : "r" (address) : "memory");
}
#else /* CONFIG_8xx */
-extern void _tlbil_va(unsigned long address, unsigned int pid);
+extern void __tlbil_va(unsigned long address, unsigned int pid);
+static inline void _tlbil_va(unsigned long address, unsigned int pid,
+ unsigned int tsize, unsigned int ind)
+{
+ __tlbil_va(address, pid);
+}
#endif /* CONIFG_8xx */
/*
@@ -58,7 +67,8 @@ extern void _tlbil_va(unsigned long addr
* implementation. When that becomes the case, this will be
* an extern.
*/
-static inline void _tlbivax_bcast(unsigned long address, unsigned int pid)
+static inline void _tlbivax_bcast(unsigned long address, unsigned int pid,
+ unsigned int tsize, unsigned int ind)
{
BUG();
}
Index: linux-work/arch/powerpc/mm/tlb_nohash.c
===================================================================
--- linux-work.orig/arch/powerpc/mm/tlb_nohash.c 2009-07-24 16:24:08.000000000 +1000
+++ linux-work/arch/powerpc/mm/tlb_nohash.c 2009-07-24 17:41:33.000000000 +1000
@@ -67,18 +67,24 @@ void local_flush_tlb_mm(struct mm_struct
}
EXPORT_SYMBOL(local_flush_tlb_mm);
-void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+void __local_flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+ int tsize, int ind)
{
unsigned int pid;
preempt_disable();
- pid = vma ? vma->vm_mm->context.id : 0;
+ pid = mm ? mm->context.id : 0;
if (pid != MMU_NO_CONTEXT)
- _tlbil_va(vmaddr, pid);
+ _tlbil_va(vmaddr, pid, tsize, ind);
preempt_enable();
}
-EXPORT_SYMBOL(local_flush_tlb_page);
+void local_flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+ __local_flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
+ 0 /* tsize unused for now */, 0);
+}
+EXPORT_SYMBOL(local_flush_tlb_page);
/*
* And here are the SMP non-local implementations
@@ -96,6 +102,8 @@ static int mm_is_core_local(struct mm_st
struct tlb_flush_param {
unsigned long addr;
unsigned int pid;
+ unsigned int tsize;
+ unsigned int ind;
};
static void do_flush_tlb_mm_ipi(void *param)
@@ -109,7 +117,7 @@ static void do_flush_tlb_page_ipi(void *
{
struct tlb_flush_param *p = param;
- _tlbil_va(p->addr, p->pid);
+ _tlbil_va(p->addr, p->pid, p->tsize, p->ind);
}
@@ -149,37 +157,49 @@ void flush_tlb_mm(struct mm_struct *mm)
}
EXPORT_SYMBOL(flush_tlb_mm);
-void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr,
+ int tsize, int ind)
{
struct cpumask *cpu_mask;
unsigned int pid;
preempt_disable();
- pid = vma ? vma->vm_mm->context.id : 0;
+ pid = mm ? mm->context.id : 0;
if (unlikely(pid == MMU_NO_CONTEXT))
goto bail;
- cpu_mask = mm_cpumask(vma->vm_mm);
+ cpu_mask = mm_cpumask(mm);
if (!mm_is_core_local(mm)) {
/* If broadcast tlbivax is supported, use it */
if (mmu_has_feature(MMU_FTR_USE_TLBIVAX_BCAST)) {
int lock = mmu_has_feature(MMU_FTR_LOCK_BCAST_INVAL);
if (lock)
spin_lock(&tlbivax_lock);
- _tlbivax_bcast(vmaddr, pid);
+ _tlbivax_bcast(vmaddr, pid, tsize, ind);
if (lock)
spin_unlock(&tlbivax_lock);
goto bail;
} else {
- struct tlb_flush_param p = { .pid = pid, .addr = vmaddr };
+ struct tlb_flush_param p = {
+ .pid = pid,
+ .addr = vmaddr,
+ .tsize = tsize,
+ .ind = ind,
+ };
/* Ignores smp_processor_id() even if set in cpu_mask */
smp_call_function_many(cpu_mask,
do_flush_tlb_page_ipi, &p, 1);
}
}
- _tlbil_va(vmaddr, pid);
+ _tlbil_va(vmaddr, pid, tsize, ind);
bail:
preempt_enable();
}
+
+void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr)
+{
+ __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr,
+ 0 /* tsize unused for now */, 0);
+}
EXPORT_SYMBOL(flush_tlb_page);
#endif /* CONFIG_SMP */
Index: linux-work/arch/powerpc/mm/tlb_nohash_low.S
===================================================================
--- linux-work.orig/arch/powerpc/mm/tlb_nohash_low.S 2009-07-24 16:24:08.000000000 +1000
+++ linux-work/arch/powerpc/mm/tlb_nohash_low.S 2009-07-24 17:04:57.000000000 +1000
@@ -39,7 +39,7 @@
/*
* 40x implementation needs only tlbil_va
*/
-_GLOBAL(_tlbil_va)
+_GLOBAL(__tlbil_va)
/* We run the search with interrupts disabled because we have to change
* the PID and I don't want to preempt when that happens.
*/
@@ -71,7 +71,7 @@ _GLOBAL(_tlbil_va)
* 440 implementation uses tlbsx/we for tlbil_va and a full sweep
* of the TLB for everything else.
*/
-_GLOBAL(_tlbil_va)
+_GLOBAL(__tlbil_va)
mfspr r5,SPRN_MMUCR
rlwimi r5,r4,0,24,31 /* Set TID */
@@ -170,7 +170,7 @@ ALT_MMU_FTR_SECTION_END_IFSET(MMU_FTR_US
* Flush MMU TLB for a particular address, but only on the local processor
* (no broadcast)
*/
-_GLOBAL(_tlbil_va)
+_GLOBAL(__tlbil_va)
mfmsr r10
wrteei 0
slwi r4,r4,16
^ permalink raw reply
* [PATCH 9/20] powerpc/mm: Call mmu_context_init() from ppc64 (v2)
From: Benjamin Herrenschmidt @ 2009-07-24 9:15 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <1248426902.401617.944220131651.qpush@grosgo>
Our 64-bit hash context handling has no init function, but 64-bit Book3E
will use the common mmu_context_nohash.c code which does, so define an
empty inline mmu_context_init() for 64-bit server and call it from
our 64-bit setup_arch()
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Acked-by: Kumar Gala <galak@kernel.crashing.org>
---
v2. Remove whitespace addition to mmu_context_hash64.c
arch/powerpc/include/asm/mmu_context.h | 7 ++++++-
arch/powerpc/kernel/setup_64.c | 4 ++++
2 files changed, 10 insertions(+), 1 deletion(-)
--- linux-work.orig/arch/powerpc/include/asm/mmu_context.h 2009-07-22 16:25:25.000000000 +1000
+++ linux-work/arch/powerpc/include/asm/mmu_context.h 2009-07-22 16:25:50.000000000 +1000
@@ -14,7 +14,6 @@
/*
* Most if the context management is out of line
*/
-extern void mmu_context_init(void);
extern int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
extern void destroy_context(struct mm_struct *mm);
@@ -23,6 +22,12 @@ extern void switch_stab(struct task_stru
extern void switch_slb(struct task_struct *tsk, struct mm_struct *mm);
extern void set_context(unsigned long id, pgd_t *pgd);
+#ifdef CONFIG_PPC_BOOK3S_64
+static inline void mmu_context_init(void) { }
+#else
+extern void mmu_context_init(void);
+#endif
+
/*
* switch_mm is the entry point called from the architecture independent
* code in kernel/sched.c
Index: linux-work/arch/powerpc/kernel/setup_64.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/setup_64.c 2009-07-22 16:26:23.000000000 +1000
+++ linux-work/arch/powerpc/kernel/setup_64.c 2009-07-22 16:26:31.000000000 +1000
@@ -534,6 +534,10 @@ void __init setup_arch(char **cmdline_p)
#endif
paging_init();
+
+ /* Initialize the MMU context management stuff */
+ mmu_context_init();
+
ppc64_boot_msg(0x15, "Setup Done");
}
^ 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