* Re: [PATCH -v2 0/7] powerpc: use asm-generic/dma-mapping-common.h
From: Benjamin Herrenschmidt @ 2009-08-27 3:12 UTC (permalink / raw)
To: Ingo Molnar; +Cc: FUJITA Tomonori, linuxppc-dev, linux-kernel, galak
In-Reply-To: <20090813085505.GA10671@elte.hu>
On Thu, 2009-08-13 at 10:55 +0200, Ingo Molnar wrote:
> Ok! We could also stage it a bit (one or two weeks) in a separate
> branch and allow a rebase, should you find any bugs during testing?
Allright so after various delays and sidetracking on my side, the
patches have been in my -test branch for long enough, I'm happy for them
to go in either way now.
I'm going to take them out of powerpc test for now and not put them in
my -next right away until I'm sure I have the right source to pull, at
which point I can just put from tip iommu.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH -v2 0/7] powerpc: use asm-generic/dma-mapping-common.h
From: Benjamin Herrenschmidt @ 2009-08-27 3:17 UTC (permalink / raw)
To: Ingo Molnar; +Cc: FUJITA Tomonori, linuxppc-dev, linux-kernel, galak
In-Reply-To: <1251342735.20467.2.camel@pasglop>
On Thu, 2009-08-27 at 13:12 +1000, Benjamin Herrenschmidt wrote:
> On Thu, 2009-08-13 at 10:55 +0200, Ingo Molnar wrote:
>
> > Ok! We could also stage it a bit (one or two weeks) in a separate
> > branch and allow a rebase, should you find any bugs during testing?
>
> Allright so after various delays and sidetracking on my side, the
> patches have been in my -test branch for long enough, I'm happy for them
> to go in either way now.
>
> I'm going to take them out of powerpc test for now and not put them in
> my -next right away until I'm sure I have the right source to pull, at
> which point I can just put from tip iommu.
IE. I think I was not clear :-)
I mean, I plan to pull tip/iommu into powerpc-next and then apply the
patches, but I want just your final word that this is a
"stable" (non-rebase) branch and from Fujita that the patches are still
good and haven't changed from those currently on patchwork.
Cheers,
Ben.
^ permalink raw reply
* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2009-08-27 3:33 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev list, Andrew Morton, Linux Kernel list
Hi Linus !
Here are a couple of last minute patches for 2.6.31. One is a regression fix
(afaik) where a PS3 driver gets incorrectly loaded on other platforms and
crashes, along with a PS3 defconfig update.
The following changes since commit f415c413f458837bd0c27086b79aca889f9435e4:
Linus Torvalds (1):
Merge git://git.kernel.org/.../davem/net-2.6
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge
Geert Uytterhoeven (1):
powerpc/ps3: Add missing check for PS3 to rtc-ps3 platform device registration
Geoff Levand (1):
powerpc/ps3: Update ps3_defconfig
arch/powerpc/configs/ps3_defconfig | 211 +++++++++++++-----------------------
arch/powerpc/platforms/ps3/time.c | 4 +
2 files changed, 79 insertions(+), 136 deletions(-)
^ permalink raw reply
* Re: [v2 PATCH 2/2]: pseries: Implement Pseries Processor Idle idle module.
From: Benjamin Herrenschmidt @ 2009-08-27 3:44 UTC (permalink / raw)
To: Peter Zijlstra
Cc: Gautham R Shenoy, linux-kernel, Paul Mackerras, arun, Ingo Molnar,
linuxppc-dev, Balbir Singh
In-Reply-To: <1251286038.1329.1.camel@twins>
On Wed, 2009-08-26 at 13:27 +0200, Peter Zijlstra wrote:
> On Wed, 2009-08-26 at 16:40 +0530, Arun R Bharadwaj wrote:
> > +void (*pm_idle)(void);
> > +EXPORT_SYMBOL_GPL(pm_idle);
>
> Seriously.. this caused plenty problems over on x86 and you're doing the
> exact same dumb thing?
I already said I didn't want this export.
First thing first: We already have a ppc_md.power_save() callback,
filled by the platform. which implements the "low level" part of idle on
powerpc (ie, the actual putting of the CPU into some kind of wait state)
and is called by our idle loop.
We -also- have a higher level ppc_md.idle_loop() which allows the
platform to completely override the idle loop, though we rarely do it (I
think only iSeries does it nowadays).
So I see no need to -add- another callback here. I'm not entirely sure
what the cpuidle framework does, it's no obvious from Arun commit
messages I must say, but it doesn't look like the right approach for
integration. In fact, pSeries already have a choice between different
powersave models depending on what kind of hypervisor is there.
So Arun, please try to fit nicely within the existing interfaces, or if
you want to add a new one, please justify very precisely what design
decisions lead you to that.
Finally, there's also a problem with your first patch 1/2: You are
setting a Kconfig flag unconditionally indicating that the arch supports
some idle wait function, but you only implement it somewhere in
arch/powerpc/platform/pseries, so you'll break the build of any other
platform. You also prevent another platform to implement a different one
and be built in the same kernel.
For such generic callbacks, if it's justified (and only if it is), you
can add a ppc_md. hook for the platform to fill, and you need to cater
for platforms that don't.
Cheers,
Ben.
^ permalink raw reply
* Re: [PATCH] powerpc: Invoke kdump for system reset exception
From: Benjamin Herrenschmidt @ 2009-08-27 3:54 UTC (permalink / raw)
To: mohan; +Cc: linuxppc-dev, kamalesh
In-Reply-To: <20090824031244.GA3590@in.ibm.com>
On Mon, 2009-08-24 at 08:42 +0530, M. Mohan Kumar wrote:
> Invoke kdump for system reset exception
>
> Dump restart operation from HMC raises system reset exception
> (0x100) and xmon is invoked(even if kdump kernel is loaded). User has to
> exit from xmon by saying 'Don't recover' to invoke kdump. Modify this
> behaviour so that xmon will return immediately for system reset
> exception and kdump kernel will be invoked (if its loaded). If kdump
> kernel is not loaded, proceed with xmon
Hi Mohan !
This is not right. The way things -should- already work is that xmon
will only kick in if it's been enabled (aka initialized). This happens
normally if either:
- CONFIG_XMON_DEFAULT is set, which forces enable it at boot. This
should not be set on distro kernels
- The command line says xmon=early or xmon=on, in which case xmon will
be enabled during early boot (and in the case of xmon=early, you'll drop
into it early during boot, for example to get a chance to set some
breakpoints).
So on a normal distro kernel, where CONFIG_XMON_DEFAULT should not be
set (if it is, they need to fix it), xmon will not be initialized, and a
System Reset exception should trigger a kdump. If it doesn't, then
there's a bug elsewhere, but the fix isn't to modify xmon.
Cheers,
Ben.
> Signed-off-by: M. Mohan Kumar <mohan@in.ibm.com>
> ---
> arch/powerpc/xmon/xmon.c | 9 +++++++++
> 1 files changed, 9 insertions(+), 0 deletions(-)
>
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index e1f33a8..6847334 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -23,6 +23,7 @@
> #include <linux/interrupt.h>
> #include <linux/irq.h>
> #include <linux/bug.h>
> +#include <linux/kexec.h>
>
> #include <asm/ptrace.h>
> #include <asm/string.h>
> @@ -348,6 +349,14 @@ static int xmon_core(struct pt_regs *regs, int fromipi)
> unsigned long timeout;
> #endif
>
> + /*
> + * If the exception is 0x100 and if kexec crash image is loaded,
> + * continue with kexec_crash
> + */
> + if (kexec_should_crash(current) && kexec_crash_image &&
> + regs->trap == 0x100)
> + return 0;
> +
> local_irq_save(flags);
>
> bp = in_breakpoint_table(regs->nip, &offset);
^ permalink raw reply
* Re: Extending virtio_console to support multiple ports
From: Benjamin Herrenschmidt @ 2009-08-27 4:07 UTC (permalink / raw)
To: Amit Shah
Cc: kvm, linuxppc-dev, linux-kernel, miltonm, qemu-devel, borntraeger,
brueckner, virtualization, alan
In-Reply-To: <20090826154552.GA31910@amit-x200.redhat.com>
On Wed, 2009-08-26 at 21:15 +0530, Amit Shah wrote:
>
> > - Convert hvc's usage of spinlocks to mutexes. I've no idea how this
> > will play out; I'm no expert here. But I did try doing this and so far
> > it all looks OK. No lockups, lockdep warnings, nothing. I have full
> > debugging enabled. But this doesn't mean it's right.
>
> So just to test this further I added the capability to have more than
> one hvc console spawn from virtio_console, created two consoles and did
> a 'cat' of a file in each of the virtio-consoles. It's been running for
> half an hour now without any badness. No spew in debug logs too.
>
> I also checked the code in hvc_console.c that takes the spin_locks.
> Nothing there that runs from (or needs to run from) interrupt context.
> So the change to mutexes does seem reasonable. Also, the spinlock code
> was added really long back -- git blame shows Linus' first git commit
> introduced them in the git history, so it's pure legacy baggage.
Two things here:
- First you seem to have completely missed the fact that hvc_poll() can
be called from interrupt time :-) Look at hvc_irq.c which is used by
some backends. Maybe that can be "fixed" by deferring to a work queue,
though it's nice to have the keyboard input have somewhat of a higher
priority than anything else here.
So unless that's fixed, or I missed something, that's a big NACK for
now.
- Then, are we certain that there's no case where the tty layer will
call us with some lock held or in an atomic context ? To be honest, I've
totally lost track of the locking rules in tty land lately so it might
well be ok, but something to verify.
Cheers,
Ben.
^ permalink raw reply
* Re: [RFC] Clock binding
From: Benjamin Herrenschmidt @ 2009-08-27 4:09 UTC (permalink / raw)
To: devicetree-discuss; +Cc: Mitch Bradley, linuxppc-dev list
In-Reply-To: <1250569288.19007.15.camel@pasglop>
On Tue, 2009-08-18 at 14:21 +1000, Benjamin Herrenschmidt wrote:
> So here's a followup to my discussion about the clock API.
Really nobody has a comment here ? :-) Not even Mitch ?
Cheers,
Ben.
> I'm cooking up a patch that replace our current primitive implementation
> in arch/powerpc/kernel/clock.c with something along the lines of what I
> described. However, I want a bit more churn here on the device-tree
> related bits.
>
> So, basically, the goal here is to define a binding so that we can link
> a device clock inputs to a clock provider clock outputs.
>
> In general, in a system, there's actually 3 "names" involved. The clock
> provider output name, the clock signal name, and the clock input name on
> the device. However, I want to avoid involving the clock signal name as
> it's a "global" name and it will just end up being a mess if we start
> exposing that.
>
> So basically, it boils down to a device having some clock inputs,
> referenced by names, that need to be linked to another node which is a
> clock provider, which has outputs, references either by number or names,
> see discussion below.
>
> First, why names, and not numbers ? IE. It's the OF "tradition" for
> resources to just be an array, like interrupts, or address ranges in
> "reg" properties, and one has to know what the Nth interrupt correspond
> too.
>
> My answer here is that maybe the tradition but it's crap :-) Names are
> much better in the long run, besides it makes it easier to represent if
> not all inputs have been wired. Also, to some extent, things like PCI do
> encode a "name" with "reg" or "assigned-addresses" properties as part of
> the config space offset in the top part of the address, and that has
> proved very useful.
>
> Thus I think using names is the way to go, and we should even generalize
> that and add a new "interrupt-names" property to name the members of an
> "interrupts" :-)
>
> So back to the subject at hand. That leaves us with having to populate
> the driver with some kind of map (I call it clock-map). Ideally, if
> everything is named, which is the best approach imho, that map would
> bind a list of:
>
> - clock input name
> - clock provider phandle
> - clock output name on provider
>
> However, it's a bit nasty to mix strings and numbers (phandles) in a
> single property. It's possible, but would likely lead to the phandle not
> being aligned and tools such as lsprop to fail miserably to display
> those properties in any kind of readable form.
>
> My earlier emails proposed an approach like this:
>
> - clock input names go into a "clock-names" property
> (which I suggest naming instead "clock-input-names" btw)
>
> - the map goes into a "clock-map" property and for each input
> provides a phandle and a one cell numerical ID that identifies
> the clock on the source.
>
> However, I really dislike that numerical clock ID. Magic numbers suck.
> It should be a string. But I don't want to add a 3rd property in there.
>
> Hence my idea below. It's not perfect but it's the less sucky i've come
> up with so far. And then we can do some small refinements.
>
> * Device has:
>
> - "clock-input-names" as above
> - "clock-map" contains list of phandle,index
>
> * Clock source has:
>
> - "clock-output-names" list of strings
>
> The "index" in the clock map thus would reference the
> "clock-output-names" array in the clock provider. That means that the
> "magic number" here is entirely local to a given device-tree, doesn't
> leak into driver code, which continues using names.
>
> In addition, we can even have some smooth "upgrade" path from existing
> "clock-frequency" properties by assuming that if "clock-output-names" is
> absent, but "clock-frequency" exist, then index 0 references a fixed
> frequency clock source without a driver. This could be generally handy
> anyway to represent crystals of fixed bus clocks without having to write
> a clock source driver for them.
>
> Any comments ?
>
> I'll post a patch, maybe later today, implementing the above (I may or
> may not have time to also convert the existing 512x code to it, we'll
> see).
>
> Cheers,
> Ben.
>
>
>
>
>
> _______________________________________________
> devicetree-discuss mailing list
> devicetree-discuss@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/devicetree-discuss
^ permalink raw reply
* Re: [PATCH] powerpc: add cascade support to xilinx intc controller
From: Benjamin Herrenschmidt @ 2009-08-27 4:15 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, john.linn
In-Reply-To: <20090825060848.3913.60710.stgit@localhost.localdomain>
On Tue, 2009-08-25 at 00:08 -0600, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
>
> This patch allows the Xilinx intc interrupt controller to be cascaded
> instead of being the master irqhost. Useful when attaching an FPGA
> to an SoC that has its own interrupt controller.
Something doesn't look quite right ...
> /*
> + * Cascaded Xilinx interrupt controller
> + */
> +static void xilinx_intc_cascade(unsigned int virq, struct irq_desc *desc)
> +{
> + struct irq_host *cascade_irqhost = get_irq_data(virq);
> + void *regs = cascade_irqhost->host_data;
> + unsigned int cascade_virq;
> +
> + pr_debug("%s(virq=%i) irq_host=%p\n", __func__, virq, cascade_irqhost);
> + cascade_virq = irq_linear_revmap(cascade_irqhost,
> + in_be32(regs + XINTC_IVR));
> + if (cascade_virq)
> + generic_handle_irq(cascade_virq);
> +}
The cascade handler generally has to be part of the -host- controller or
the platform code (we should try maybe to invent a way to make that
more transparent but today it's not) because it may need to do special
things to ack the interrupt on the host controller.
For example, if I have an MPIC based setup with a cascaded xilinx FPGA,
I want to use something that does the EOI right on the MPIC. In fact,
it's -almost- like what we need to do for a cascade, is to find a way to
stick a get_irq() function pointer somewhere in the irq-desc for the
cascaded interrupt, and have in the -host- a generic cascade handler.
Also, you seem to be trying to do the revmap of the child interrupt
using the parent host.. .that doesn't make sense. Each PIC has it's own
revmap and the child PIC uses it's own revmap as well.
The rest of the code seems to entertain a similar confusion...
Cheers,
Ben.
> +/**
> + * xilinx_intc_cascade_setup - Add a xilinx intc device as a cascaded controller
> + * @cascade_node: device node for xilinx intc controller.
> + */
> +int xilinx_intc_cascade_setup(struct device_node *cascade_node)
> +{
> + struct irq_host *cascade_irqhost;
> + int cascade_virq;
> +
> + if (!cascade_node) {
> + pr_err("%s(): cannot find xilinx intc node\n", __func__);
> + return -ENODEV;
> + }
> +
> + /* Make sure this is a xilinx intc device */
> + if (!of_match_node(xilinx_intc_match, cascade_node)) {
> + pr_err("%s(): %s is not compatible\n",
> + __func__, cascade_node->name);
> + return -EINVAL;
> + }
> +
> + /* Map a VIRQ for the cascaded handler */
> + cascade_virq = irq_of_parse_and_map(cascade_node, 0);
> + if (!cascade_virq) {
> + pr_err("%s(): error mapping cascade interrupt\n", __func__);
> + return -ENODEV;
> + }
> +
> + /* Set up the irqhost and register it */
> + cascade_irqhost = xilinx_intc_init(cascade_node);
> + set_irq_data(cascade_virq, cascade_irqhost);
> + set_irq_chained_handler(cascade_virq, xilinx_intc_cascade);
> +
> + pr_debug("%s(): cascading virq %i to irq_host %p\n",
> + __func__, cascade_virq, cascade_irqhost);
> +
> + return 0;
> +}
> +EXPORT_SYMBOL(xilinx_intc_cascade_setup);
> +
> +/*
> * Initialize master Xilinx interrupt controller
> */
> void __init xilinx_intc_init_tree(void)
^ permalink raw reply
* Re: [PATCH] powerpc: Adjust base and index registers in Altivec macros
From: Michael Neuling @ 2009-08-27 4:36 UTC (permalink / raw)
To: mjw; +Cc: linuxppc-dev
In-Reply-To: <1250810505.14522.3.camel@mx3>
> On POWER6 systems RA needs to be the base and RB the index.
> If they are reversed you take a misdirect hit.
>
> Signed-off-by: Mike Wolf <mjwolf@us.ibm.com>
Looks good.... thanks Mike!
Acked-by: Michael Neuling <mikey@neuling.org>
>
> ----
> --- altivec.orig/arch/powerpc/include/asm/ppc_asm.h 2009-08-17 15:39:52.000
000000 -0500
> +++ altivec/arch/powerpc/include/asm/ppc_asm.h 2009-08-20 18:08:30.000
000000 -0500
> @@ -98,13 +98,13 @@
> #define REST_16FPRS(n, base) REST_8FPRS(n, base); REST_8FPRS(n+8, base)
> #define REST_32FPRS(n, base) REST_16FPRS(n, base); REST_16FPRS(n+16, base)
>
> -#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,b,base
> +#define SAVE_VR(n,b,base) li b,THREAD_VR0+(16*(n)); stvx n,base,b
> #define SAVE_2VRS(n,b,base) SAVE_VR(n,b,base); SAVE_VR(n+1,b,base)
> #define SAVE_4VRS(n,b,base) SAVE_2VRS(n,b,base); SAVE_2VRS(n+2,b,base)
> #define SAVE_8VRS(n,b,base) SAVE_4VRS(n,b,base); SAVE_4VRS(n+4,b,base)
> #define SAVE_16VRS(n,b,base) SAVE_8VRS(n,b,base); SAVE_8VRS(n+8,b,base)
> #define SAVE_32VRS(n,b,base) SAVE_16VRS(n,b,base); SAVE_16VRS(n+16,b,base)
> -#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,b,base
> +#define REST_VR(n,b,base) li b,THREAD_VR0+(16*(n)); lvx n,base,b
> #define REST_2VRS(n,b,base) REST_VR(n,b,base); REST_VR(n+1,b,base)
> #define REST_4VRS(n,b,base) REST_2VRS(n,b,base); REST_2VRS(n+2,b,base)
> #define REST_8VRS(n,b,base) REST_4VRS(n,b,base); REST_4VRS(n+4,b,base)
> @@ -112,26 +112,26 @@
> #define REST_32VRS(n,b,base) REST_16VRS(n,b,base); REST_16VRS(n+16,b,base)
>
> /* Save the lower 32 VSRs in the thread VSR region */
> -#define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,b,base)
> +#define SAVE_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); STXVD2X(n,base,b)
> #define SAVE_2VSRS(n,b,base) SAVE_VSR(n,b,base); SAVE_VSR(n+1,b,base)
> #define SAVE_4VSRS(n,b,base) SAVE_2VSRS(n,b,base); SAVE_2VSRS(n+2,b,base)
> #define SAVE_8VSRS(n,b,base) SAVE_4VSRS(n,b,base); SAVE_4VSRS(n+4,b,base)
> #define SAVE_16VSRS(n,b,base) SAVE_8VSRS(n,b,base); SAVE_8VSRS(n+8,b,
base)
> #define SAVE_32VSRS(n,b,base) SAVE_16VSRS(n,b,base); SAVE_16VSRS(n+16
,b,base)
> -#define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); LXVD2X(n,b,base)
> +#define REST_VSR(n,b,base) li b,THREAD_VSR0+(16*(n)); LXVD2X(n,base,b)
> #define REST_2VSRS(n,b,base) REST_VSR(n,b,base); REST_VSR(n+1,b,base)
> #define REST_4VSRS(n,b,base) REST_2VSRS(n,b,base); REST_2VSRS(n+2,b,base)
> #define REST_8VSRS(n,b,base) REST_4VSRS(n,b,base); REST_4VSRS(n+4,b,base)
> #define REST_16VSRS(n,b,base) REST_8VSRS(n,b,base); REST_8VSRS(n+8,b,
base)
> #define REST_32VSRS(n,b,base) REST_16VSRS(n,b,base); REST_16VSRS(n+16
,b,base)
> /* Save the upper 32 VSRs (32-63) in the thread VSX region (0-31) */
> -#define SAVE_VSRU(n,b,base) li b,THREAD_VR0+(16*(n)); STXVD2X(n+32,b,base)
> +#define SAVE_VSRU(n,b,base) li b,THREAD_VR0+(16*(n)); STXVD2X(n+32,base,b)
> #define SAVE_2VSRSU(n,b,base) SAVE_VSRU(n,b,base); SAVE_VSRU(n+1,b,ba
se)
> #define SAVE_4VSRSU(n,b,base) SAVE_2VSRSU(n,b,base); SAVE_2VSRSU(n+2,
b,base)
> #define SAVE_8VSRSU(n,b,base) SAVE_4VSRSU(n,b,base); SAVE_4VSRSU(n+4,
b,base)
> #define SAVE_16VSRSU(n,b,base) SAVE_8VSRSU(n,b,base); SAVE_8VSRSU(n+8,
b,base)
> #define SAVE_32VSRSU(n,b,base) SAVE_16VSRSU(n,b,base); SAVE_16VSRSU(n+
16,b,base)
> -#define REST_VSRU(n,b,base) li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,b,base)
> +#define REST_VSRU(n,b,base) li b,THREAD_VR0+(16*(n)); LXVD2X(n+32,base,b)
> #define REST_2VSRSU(n,b,base) REST_VSRU(n,b,base); REST_VSRU(n+1,b,ba
se)
> #define REST_4VSRSU(n,b,base) REST_2VSRSU(n,b,base); REST_2VSRSU(n+2,
b,base)
> #define REST_8VSRSU(n,b,base) REST_4VSRSU(n,b,base); REST_4VSRSU(n+4,
b,base)
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>
^ permalink raw reply
* Question : about difference with bdnz and bdnz+
From: HongWoo Lee @ 2009-08-27 5:04 UTC (permalink / raw)
To: linuxppc-dev
Hi ~
I found the code in the linux kernel.
static __inline__ void clear_page(void *addr)
{
unsigned long lines, line_size;
line_size = cpu_caches.dline_size;
lines = cpu_caches.dlines_per_page;
__asm__ __volatile__(
"mtctr %1 # clear_page\n\
1: dcbz 0,%0\n\
add %0,%0,%3\n\
bdnz+ 1b"
: "=r" (addr)
: "r" (lines), "0" (addr), "r" (line_size)
: "ctr", "memory");
}
And I have a question about bdnz+ instruction.
Through googling, I learned that bdnz does decrement count register and
branch if it is still nonzero.
But I couldn't find what "bdnz+" is.
Can anybody explain to me what it is ??
Thanks in advance.
HongWoo.
^ permalink raw reply
* Re: Extending virtio_console to support multiple ports
From: Michael Ellerman @ 2009-08-27 5:04 UTC (permalink / raw)
To: Amit Shah
Cc: kvm, linuxppc-dev, linux-kernel, miltonm, qemu-devel, borntraeger,
brueckner, virtualization, alan
In-Reply-To: <20090826154552.GA31910@amit-x200.redhat.com>
[-- Attachment #1: Type: text/plain, Size: 1897 bytes --]
On Wed, 2009-08-26 at 21:15 +0530, Amit Shah wrote:
> [cc'ing some people who have made some commits in hvc_console.c]
>
> On (Wed) Aug 26 2009 [16:57:18], Amit Shah wrote:
> > On (Tue) Aug 25 2009 [11:47:20], Amit Shah wrote:
> > >
> > > Hello all,
> > >
> > > Here is a new iteration of the patch series that implements a
> > > transport for guest and host communications.
> > >
> > > The code has been updated to reuse the virtio-console device instead
> > > of creating a new virtio-serial device.
> >
> > And the problem now is that hvc calls the put_chars function with
> > spinlocks held and we now allocate pages in send_buf(), called from
> > put_chars.
> >
> > A few solutions:
>
> [snip]
>
> > - Convert hvc's usage of spinlocks to mutexes. I've no idea how this
> > will play out; I'm no expert here. But I did try doing this and so far
> > it all looks OK. No lockups, lockdep warnings, nothing. I have full
> > debugging enabled. But this doesn't mean it's right.
>
> So just to test this further I added the capability to have more than
> one hvc console spawn from virtio_console, created two consoles and did
> a 'cat' of a file in each of the virtio-consoles. It's been running for
> half an hour now without any badness. No spew in debug logs too.
>
> I also checked the code in hvc_console.c that takes the spin_locks.
> Nothing there that runs from (or needs to run from) interrupt context.
> So the change to mutexes does seem reasonable. Also, the spinlock code
> was added really long back -- git blame shows Linus' first git commit
> introduced them in the git history, so it's pure legacy baggage.
I won't tell Ryan you called his code "pure legacy baggage" if you
don't ;)
http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;a=commitdiff;h=d450b4ae023fb4be175389c18f4f87677da03020
cheers
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* Re: [RFC] Clock binding
From: Grant Likely @ 2009-08-27 5:20 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list, devicetree-discuss
In-Reply-To: <1251346157.20467.22.camel@pasglop>
On Wed, Aug 26, 2009 at 10:09 PM, Benjamin
Herrenschmidt<benh@kernel.crashing.org> wrote:
> On Tue, 2009-08-18 at 14:21 +1000, Benjamin Herrenschmidt wrote:
>> So here's a followup to my discussion about the clock API.
>
> Really nobody has a comment here ? :-) Not even Mitch ?
Been wanting too.. a little swamped with kids going back to school
tomorrow. Hopefully I'll be able to dig in before the end of the
week.
g.
^ permalink raw reply
* Re: [PATCH V2 3/3] powerpc/pci: Merge ppc32 and ppc64 versions of phb_scan()
From: Benjamin Herrenschmidt @ 2009-08-27 5:46 UTC (permalink / raw)
To: Grant Likely; +Cc: sfr, linuxppc-dev
In-Reply-To: <20090826060716.30936.40578.stgit@localhost.localdomain>
On Wed, 2009-08-26 at 00:07 -0600, Grant Likely wrote:
> From: Grant Likely <grant.likely@secretlab.ca>
>
> The two versions are doing almost exactly the same thing. No need to
> maintain them as separate files. This patch also has the side effect
> of making the PCI device tree scanning code available to 32 bit powerpc
> machines, but no board ports actually make use of this feature at this
> point.
You missed various calls to scan_phb() in arch/powerpc :-)
At least pSeries with dynamic LPAR is broken, I think iSeries might
break too. Try a ppc64_defconfig.
I tentatively applied the other patches to -test
Cheers,
Ben.
> Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
> ---
>
> arch/powerpc/include/asm/pci.h | 2 ++
> arch/powerpc/kernel/pci-common.c | 48 ++++++++++++++++++++++++++++++++++++++
> arch/powerpc/kernel/pci_32.c | 25 ++------------------
> arch/powerpc/kernel/pci_64.c | 46 +++++-------------------------------
> 4 files changed, 58 insertions(+), 63 deletions(-)
>
>
> diff --git a/arch/powerpc/include/asm/pci.h b/arch/powerpc/include/asm/pci.h
> index 9ae2e3e..feebfed 100644
> --- a/arch/powerpc/include/asm/pci.h
> +++ b/arch/powerpc/include/asm/pci.h
> @@ -233,6 +233,8 @@ extern void pci_resource_to_user(const struct pci_dev *dev, int bar,
>
> extern void pcibios_setup_bus_devices(struct pci_bus *bus);
> extern void pcibios_setup_bus_self(struct pci_bus *bus);
> +extern void pcibios_setup_phb_io_space(struct pci_controller *hose);
> +extern void pcibios_scan_phb(struct pci_controller *hose, void *data);
>
> #endif /* __KERNEL__ */
> #endif /* __ASM_POWERPC_PCI_H */
> diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
> index 44497a8..8a16dbe 100644
> --- a/arch/powerpc/kernel/pci-common.c
> +++ b/arch/powerpc/kernel/pci-common.c
> @@ -1617,3 +1617,51 @@ void __devinit pcibios_setup_phb_resources(struct pci_controller *hose)
> (unsigned long)hose->io_base_virt - _IO_BASE);
>
> }
> +
> +/**
> + * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
> + * @hose: Pointer to the PCI host controller instance structure
> + * @data: value to use for sysdata pointer. ppc32 and ppc64 differ here
> + *
> + * Note: the 'data' pointer is a temporary measure. As 32 and 64 bit
> + * pci code gets merged, this parameter should become unnecessary because
> + * both will use the same value.
> + */
> +void __devinit pcibios_scan_phb(struct pci_controller *hose, void *data)
> +{
> + struct pci_bus *bus;
> + struct device_node *node = hose->dn;
> + int mode;
> +
> + pr_debug("PCI: Scanning PHB %s\n",
> + node ? node->full_name : "<NO NAME>");
> +
> + /* Create an empty bus for the toplevel */
> + bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, data);
> + if (bus == NULL) {
> + pr_err("Failed to create bus for PCI domain %04x\n",
> + hose->global_number);
> + return;
> + }
> + bus->secondary = hose->first_busno;
> + hose->bus = bus;
> +
> + /* Get some IO space for the new PHB */
> + pcibios_setup_phb_io_space(hose);
> +
> + /* Wire up PHB bus resources */
> + pcibios_setup_phb_resources(hose);
> +
> + /* Get probe mode and perform scan */
> + mode = PCI_PROBE_NORMAL;
> + if (node && ppc_md.pci_probe_mode)
> + mode = ppc_md.pci_probe_mode(bus);
> + pr_debug(" probe mode: %d\n", mode);
> + if (mode == PCI_PROBE_DEVTREE) {
> + bus->subordinate = hose->last_busno;
> + of_scan_bus(node, bus);
> + }
> +
> + if (mode == PCI_PROBE_NORMAL)
> + hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
> +}
> diff --git a/arch/powerpc/kernel/pci_32.c b/arch/powerpc/kernel/pci_32.c
> index 1e807fe..4e415e1 100644
> --- a/arch/powerpc/kernel/pci_32.c
> +++ b/arch/powerpc/kernel/pci_32.c
> @@ -354,36 +354,15 @@ pci_create_OF_bus_map(void)
> }
> }
>
> -static void __devinit pcibios_scan_phb(struct pci_controller *hose)
> +void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
> {
> - struct pci_bus *bus;
> - struct device_node *node = hose->dn;
> unsigned long io_offset;
> struct resource *res = &hose->io_resource;
>
> - pr_debug("PCI: Scanning PHB %s\n",
> - node ? node->full_name : "<NO NAME>");
> -
> - /* Create an empty bus for the toplevel */
> - bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
> - if (bus == NULL) {
> - printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
> - hose->global_number);
> - return;
> - }
> - bus->secondary = hose->first_busno;
> - hose->bus = bus;
> -
> /* Fixup IO space offset */
> io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
> res->start = (res->start + io_offset) & 0xffffffffu;
> res->end = (res->end + io_offset) & 0xffffffffu;
> -
> - /* Wire up PHB bus resources */
> - pcibios_setup_phb_resources(hose);
> -
> - /* Scan children */
> - hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
> }
>
> static int __init pcibios_init(void)
> @@ -401,7 +380,7 @@ static int __init pcibios_init(void)
> if (pci_assign_all_buses)
> hose->first_busno = next_busno;
> hose->last_busno = 0xff;
> - pcibios_scan_phb(hose);
> + pcibios_scan_phb(hose, hose);
> pci_bus_add_devices(hose->bus);
> if (pci_assign_all_buses || next_busno <= hose->last_busno)
> next_busno = hose->last_busno + pcibios_assign_bus_offset;
> diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
> index 4d5b4ce..ba949a2 100644
> --- a/arch/powerpc/kernel/pci_64.c
> +++ b/arch/powerpc/kernel/pci_64.c
> @@ -43,45 +43,6 @@ unsigned long pci_probe_only = 1;
> unsigned long pci_io_base = ISA_IO_BASE;
> EXPORT_SYMBOL(pci_io_base);
>
> -void __devinit scan_phb(struct pci_controller *hose)
> -{
> - struct pci_bus *bus;
> - struct device_node *node = hose->dn;
> - int mode;
> -
> - pr_debug("PCI: Scanning PHB %s\n",
> - node ? node->full_name : "<NO NAME>");
> -
> - /* Create an empty bus for the toplevel */
> - bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, node);
> - if (bus == NULL) {
> - printk(KERN_ERR "Failed to create bus for PCI domain %04x\n",
> - hose->global_number);
> - return;
> - }
> - bus->secondary = hose->first_busno;
> - hose->bus = bus;
> -
> - /* Get some IO space for the new PHB */
> - pcibios_map_io_space(bus);
> -
> - /* Wire up PHB bus resources */
> - pcibios_setup_phb_resources(hose);
> -
> - /* Get probe mode and perform scan */
> - mode = PCI_PROBE_NORMAL;
> - if (node && ppc_md.pci_probe_mode)
> - mode = ppc_md.pci_probe_mode(bus);
> - pr_debug(" probe mode: %d\n", mode);
> - if (mode == PCI_PROBE_DEVTREE) {
> - bus->subordinate = hose->last_busno;
> - of_scan_bus(node, bus);
> - }
> -
> - if (mode == PCI_PROBE_NORMAL)
> - hose->last_busno = bus->subordinate = pci_scan_child_bus(bus);
> -}
> -
> static int __init pcibios_init(void)
> {
> struct pci_controller *hose, *tmp;
> @@ -103,7 +64,7 @@ static int __init pcibios_init(void)
>
> /* Scan all of the recorded PCI controllers. */
> list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
> - scan_phb(hose);
> + pcibios_scan_phb(hose, hose->dn);
> pci_bus_add_devices(hose->bus);
> }
>
> @@ -237,6 +198,11 @@ int __devinit pcibios_map_io_space(struct pci_bus *bus)
> }
> EXPORT_SYMBOL_GPL(pcibios_map_io_space);
>
> +void __devinit pcibios_setup_phb_io_space(struct pci_controller *hose)
> +{
> + pcibios_map_io_space(hose->bus);
> +}
> +
> #define IOBASE_BRIDGE_NUMBER 0
> #define IOBASE_MEMORY 1
> #define IOBASE_IO 2
^ permalink raw reply
* Re: [Qemu-devel] Re: Extending virtio_console to support multiple ports
From: Amit Shah @ 2009-08-27 6:51 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: kvm, borntraeger, qemu-devel, miltonm, linux-kernel, linuxppc-dev,
brueckner, virtualization, alan
In-Reply-To: <1251346023.20467.21.camel@pasglop>
On (Thu) Aug 27 2009 [14:07:03], Benjamin Herrenschmidt wrote:
> On Wed, 2009-08-26 at 21:15 +0530, Amit Shah wrote:
>
> >
> > > - Convert hvc's usage of spinlocks to mutexes. I've no idea how this
> > > will play out; I'm no expert here. But I did try doing this and so far
> > > it all looks OK. No lockups, lockdep warnings, nothing. I have full
> > > debugging enabled. But this doesn't mean it's right.
> >
> > So just to test this further I added the capability to have more than
> > one hvc console spawn from virtio_console, created two consoles and did
> > a 'cat' of a file in each of the virtio-consoles. It's been running for
> > half an hour now without any badness. No spew in debug logs too.
> >
> > I also checked the code in hvc_console.c that takes the spin_locks.
> > Nothing there that runs from (or needs to run from) interrupt context.
> > So the change to mutexes does seem reasonable. Also, the spinlock code
> > was added really long back -- git blame shows Linus' first git commit
> > introduced them in the git history, so it's pure legacy baggage.
>
> Two things here:
>
> - First you seem to have completely missed the fact that hvc_poll() can
> be called from interrupt time :-) Look at hvc_irq.c which is used by
Right! That's the obvious one.
> some backends. Maybe that can be "fixed" by deferring to a work queue,
> though it's nice to have the keyboard input have somewhat of a higher
> priority than anything else here.
Hm, to maintain the current behaviour of poll() returning some
poll_mask, the poll_mask could be made into an atomic variable with
khvcd() updating it. But to have read at a higher priority than the
other stuff, I don't quite see yet how that can be done.
> So unless that's fixed, or I missed something, that's a big NACK for
> now.
>
> - Then, are we certain that there's no case where the tty layer will
> call us with some lock held or in an atomic context ? To be honest, I've
The other routines are open(), close(), write(), etc., and other kernel
context (hvc_instantiate() and the khvcd thread).
> totally lost track of the locking rules in tty land lately so it might
> well be ok, but something to verify.
Yes.
Thanks for the response!
Amit
^ permalink raw reply
* Re: Extending virtio_console to support multiple ports
From: Amit Shah @ 2009-08-27 6:52 UTC (permalink / raw)
To: Michael Ellerman
Cc: kvm, linuxppc-dev, linux-kernel, miltonm, qemu-devel, borntraeger,
brueckner, virtualization, alan
In-Reply-To: <1251349485.6267.6.camel@concordia>
On (Thu) Aug 27 2009 [15:04:45], Michael Ellerman wrote:
> On Wed, 2009-08-26 at 21:15 +0530, Amit Shah wrote:
> > [cc'ing some people who have made some commits in hvc_console.c]
> >
> > On (Wed) Aug 26 2009 [16:57:18], Amit Shah wrote:
> > > On (Tue) Aug 25 2009 [11:47:20], Amit Shah wrote:
> > > >
> > > > Hello all,
> > > >
> > > > Here is a new iteration of the patch series that implements a
> > > > transport for guest and host communications.
> > > >
> > > > The code has been updated to reuse the virtio-console device instead
> > > > of creating a new virtio-serial device.
> > >
> > > And the problem now is that hvc calls the put_chars function with
> > > spinlocks held and we now allocate pages in send_buf(), called from
> > > put_chars.
> > >
> > > A few solutions:
> >
> > [snip]
> >
> > > - Convert hvc's usage of spinlocks to mutexes. I've no idea how this
> > > will play out; I'm no expert here. But I did try doing this and so far
> > > it all looks OK. No lockups, lockdep warnings, nothing. I have full
> > > debugging enabled. But this doesn't mean it's right.
> >
> > So just to test this further I added the capability to have more than
> > one hvc console spawn from virtio_console, created two consoles and did
> > a 'cat' of a file in each of the virtio-consoles. It's been running for
> > half an hour now without any badness. No spew in debug logs too.
> >
> > I also checked the code in hvc_console.c that takes the spin_locks.
> > Nothing there that runs from (or needs to run from) interrupt context.
> > So the change to mutexes does seem reasonable. Also, the spinlock code
> > was added really long back -- git blame shows Linus' first git commit
> > introduced them in the git history, so it's pure legacy baggage.
>
> I won't tell Ryan you called his code "pure legacy baggage" if you
> don't ;)
>
> http://git.kernel.org/?p=linux/kernel/git/torvalds/old-2.6-bkcvs.git;a=commitdiff;h=d450b4ae023fb4be175389c18f4f87677da03020
Thanks for the link!
(and this general area might be the one that doesn't get major upheavals
in 5-yr spans :-)
Amit
^ permalink raw reply
* [PATCH] powerpc: Properly start decrementer on BookE secondary CPUs
From: Benjamin Herrenschmidt @ 2009-08-27 7:00 UTC (permalink / raw)
To: linuxppc-dev list; +Cc: Kumar Gala
This moves the code to start the decrementer on 40x and BookE into
a separate function which is now called from time_init() and
secondary_time_init(), before the respective clock sources are
registered. We also remove the 85xx specific code for doing it
from the platform code.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/time.c | 30 ++++++++++++++++++++++--------
arch/powerpc/platforms/85xx/smp.c | 12 ------------
2 files changed, 22 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index edb1edb..e9404b6 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -727,6 +727,18 @@ static int __init get_freq(char *name, int cells, unsigned long *val)
return found;
}
+/* should become __cpuinit when start_secondary also is */
+void __devinit start_cpu_decrementer(void)
+{
+#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
+ /* Clear any pending timer interrupts */
+ mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
+
+ /* Enable decrementer interrupt */
+ mtspr(SPRN_TCR, TCR_DIE);
+#endif /* defined(CONFIG_BOOKE) || defined(CONFIG_40x) */
+}
+
void __init generic_calibrate_decr(void)
{
ppc_tb_freq = DEFAULT_TB_FREQ; /* hardcoded default */
@@ -746,14 +758,6 @@ void __init generic_calibrate_decr(void)
printk(KERN_ERR "WARNING: Estimating processor frequency "
"(not found)\n");
}
-
-#if defined(CONFIG_BOOKE) || defined(CONFIG_40x)
- /* Clear any pending timer interrupts */
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
-
- /* Enable decrementer interrupt */
- mtspr(SPRN_TCR, TCR_DIE);
-#endif
}
int update_persistent_clock(struct timespec now)
@@ -914,6 +918,11 @@ static void __init init_decrementer_clockevent(void)
void secondary_cpu_time_init(void)
{
+ /* Start the decrementer on CPUs that have manual control
+ * such as BookE
+ */
+ start_cpu_decrementer();
+
/* FIME: Should make unrelatred change to move snapshot_timebase
* call here ! */
register_decrementer_clockevent(smp_processor_id());
@@ -1017,6 +1026,11 @@ void __init time_init(void)
write_sequnlock_irqrestore(&xtime_lock, flags);
+ /* Start the decrementer on CPUs that have manual control
+ * such as BookE
+ */
+ start_cpu_decrementer();
+
/* Register the clocksource, if we're not running on iSeries */
if (!firmware_has_feature(FW_FEATURE_ISERIES))
clocksource_init();
diff --git a/arch/powerpc/platforms/85xx/smp.c b/arch/powerpc/platforms/85xx/smp.c
index 9f526ba..94f901d 100644
--- a/arch/powerpc/platforms/85xx/smp.c
+++ b/arch/powerpc/platforms/85xx/smp.c
@@ -79,21 +79,9 @@ smp_85xx_kick_cpu(int nr)
}
static void __init
-smp_85xx_basic_setup(int cpu_nr)
-{
- /* Clear any pending timer interrupts */
- mtspr(SPRN_TSR, TSR_ENW | TSR_WIS | TSR_DIS | TSR_FIS);
-
- /* Enable decrementer interrupt */
- mtspr(SPRN_TCR, TCR_DIE);
-}
-
-static void __init
smp_85xx_setup_cpu(int cpu_nr)
{
mpic_setup_this_cpu();
-
- smp_85xx_basic_setup(cpu_nr);
}
struct smp_ops_t smp_85xx_ops = {
--
1.6.1.2.14.gf26b5
^ permalink raw reply related
* ppc64 allnoconfig build warning
From: Stephen Rothwell @ 2009-08-27 7:10 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: ppc-dev
[-- Attachment #1: Type: text/plain, Size: 497 bytes --]
Hi Ben,
WARNING: vmlinux.o(.text+0x1d864): Section mismatch in reference from the function .dma_direct_dma_supported() to the function .init.text:.lmb_end_of_DRAM()
The function .dma_direct_dma_supported() references
the function __init .lmb_end_of_DRAM().
This is often because .dma_direct_dma_supported lacks a __init
annotation or the annotation of .lmb_end_of_DRAM is wrong.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 197 bytes --]
^ permalink raw reply
* [PATCH] lmb: Remove __init from lmb_end_of_DRAM()
From: Benjamin Herrenschmidt @ 2009-08-27 7:20 UTC (permalink / raw)
To: Linus Torvalds; +Cc: linuxppc-dev list, David Woodhouse, David S. Miller
We call lmb_end_of_DRAM() to test whether a DMA mask
is ok on a machine without IOMMU, but this function is
marked as __init.
I don't think there's a clean way to get the top of RAM
max_pfn doesn't appear to include highmem or I missed
(or we have a bug :-) so for now, let's just avoid having
a broken 2.6.31 by making this function non-__init and we
can revisit later.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
David, you use lmb too, any objection there ?
diff --git a/lib/lmb.c b/lib/lmb.c
index e4a6482..0343c05 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -429,7 +429,7 @@ u64 __init lmb_phys_mem_size(void)
return lmb.memory.size;
}
-u64 __init lmb_end_of_DRAM(void)
+u64 lmb_end_of_DRAM(void)
{
int idx = lmb.memory.cnt - 1;
^ permalink raw reply related
* Re: [PATCH -v2 0/7] powerpc: use asm-generic/dma-mapping-common.h
From: Ingo Molnar @ 2009-08-27 7:22 UTC (permalink / raw)
To: Benjamin Herrenschmidt; +Cc: FUJITA Tomonori, linuxppc-dev, linux-kernel, galak
In-Reply-To: <1251343070.20467.3.camel@pasglop>
* Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> On Thu, 2009-08-27 at 13:12 +1000, Benjamin Herrenschmidt wrote:
> > On Thu, 2009-08-13 at 10:55 +0200, Ingo Molnar wrote:
> >
> > > Ok! We could also stage it a bit (one or two weeks) in a
> > > separate branch and allow a rebase, should you find any bugs
> > > during testing?
> >
> > Allright so after various delays and sidetracking on my side,
> > the patches have been in my -test branch for long enough, I'm
> > happy for them to go in either way now.
> >
> > I'm going to take them out of powerpc test for now and not put
> > them in my -next right away until I'm sure I have the right
> > source to pull, at which point I can just put from tip iommu.
>
> IE. I think I was not clear :-)
>
> I mean, I plan to pull tip/iommu into powerpc-next and then apply
> the patches, but I want just your final word that this is a
> "stable" (non-rebase) branch and from Fujita that the patches are
> still good and haven't changed from those currently on patchwork.
ah, yes, they are stable/fine. I've put it into a separate branch
for you.
Ben, please pull the latest iommu-for-powerpc git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git iommu-for-powerpc
And i could pull back the new bits from you once you have the new
patches added and are happy with them. [I suspect you dont want the
diffstat below in the powerpc tree]
That was the plan, right?
Thanks,
Ingo
------------------>
Arnd Bergmann (1):
dma-ops: Remove flush_write_buffers() in dma-mapping-common.h
Casey Dahlin (1):
lib/swiotlb.c: Fix strange panic message selection logic when swiotlb fills up
FUJITA Tomonori (22):
swiotlb: remove unused swiotlb_alloc_boot()
swiotlb: remove unused swiotlb_alloc()
swiotlb: remove swiotlb_arch_range_needs_mapping
swiotlb: remove unnecessary swiotlb_bus_to_virt
x86: add dma_capable() to replace is_buffer_dma_capable()
x86: replace is_buffer_dma_capable() with dma_capable
ia64: add dma_capable() to replace is_buffer_dma_capable()
powerpc: add dma_capable() to replace is_buffer_dma_capable()
swiotlb: use dma_capable()
powerpc: remove unncesary swiotlb_arch_address_needs_mapping
remove is_buffer_dma_capable()
x86, IA64, powerpc: add phys_to_dma() and dma_to_phys()
swiotlb: use phys_to_dma and dma_to_phys
powerpc: remove unused swiotlb_phys_to_bus() and swiotlb_bus_to_phys()
x86: remove unused swiotlb_phys_to_bus() and swiotlb_bus_to_phys()
IA64: Remove NULL flush_write_buffers
sparc: Use dma_map_ops struct
sparc: Use asm-generic/dma-mapping-common.h
sparc: Remove no-op dma_4v_sync_single_for_cpu and dma_4v_sync_sg_for_cpu
sparc: Replace sbus_map_single and sbus_unmap_single with sbus_map_page and sbus_unmap_page
sparc: Use asm-generic/pci-dma-compat
sparc: Add CONFIG_DMA_API_DEBUG support
arch/ia64/include/asm/dma-mapping.h | 19 +++-
arch/powerpc/include/asm/dma-mapping.h | 23 ++++
arch/powerpc/kernel/dma-swiotlb.c | 48 +--------
arch/sparc/Kconfig | 2 +
arch/sparc/include/asm/dma-mapping.h | 145 ++++-------------------
arch/sparc/include/asm/pci.h | 3 +
arch/sparc/include/asm/pci_32.h | 105 ----------------
arch/sparc/include/asm/pci_64.h | 88 --------------
arch/sparc/kernel/Makefile | 2 +-
arch/sparc/kernel/dma.c | 175 +--------------------------
arch/sparc/kernel/dma.h | 14 --
arch/sparc/kernel/iommu.c | 20 ++-
arch/sparc/kernel/ioport.c | 190 ++++++++++++++++-------------
arch/sparc/kernel/pci.c | 2 +-
arch/sparc/kernel/pci_sun4v.c | 30 ++----
arch/x86/include/asm/dma-mapping.h | 18 +++
arch/x86/kernel/pci-dma.c | 2 +-
arch/x86/kernel/pci-gart_64.c | 5 +-
arch/x86/kernel/pci-nommu.c | 29 ++++-
arch/x86/kernel/pci-swiotlb.c | 25 ----
include/asm-generic/dma-mapping-common.h | 6 -
include/linux/dma-mapping.h | 5 -
include/linux/swiotlb.h | 11 --
lib/swiotlb.c | 124 +++++++-------------
24 files changed, 291 insertions(+), 800 deletions(-)
delete mode 100644 arch/sparc/kernel/dma.h
diff --git a/arch/ia64/include/asm/dma-mapping.h b/arch/ia64/include/asm/dma-mapping.h
index 5a61b5c..8d3c79c 100644
--- a/arch/ia64/include/asm/dma-mapping.h
+++ b/arch/ia64/include/asm/dma-mapping.h
@@ -44,7 +44,6 @@ static inline void dma_free_coherent(struct device *dev, size_t size,
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
#define get_dma_ops(dev) platform_dma_get_ops(dev)
-#define flush_write_buffers()
#include <asm-generic/dma-mapping-common.h>
@@ -69,6 +68,24 @@ dma_set_mask (struct device *dev, u64 mask)
return 0;
}
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ if (!dev->dma_mask)
+ return 0;
+
+ return addr + size <= *dev->dma_mask;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+ return paddr;
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+ return daddr;
+}
+
extern int dma_get_cache_alignment(void);
static inline void
diff --git a/arch/powerpc/include/asm/dma-mapping.h b/arch/powerpc/include/asm/dma-mapping.h
index b44aaab..0c34371 100644
--- a/arch/powerpc/include/asm/dma-mapping.h
+++ b/arch/powerpc/include/asm/dma-mapping.h
@@ -424,6 +424,29 @@ static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
#endif
}
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ struct dma_mapping_ops *ops = get_dma_ops(dev);
+
+ if (ops->addr_needs_map && ops->addr_needs_map(dev, addr, size))
+ return 0;
+
+ if (!dev->dma_mask)
+ return 0;
+
+ return addr + size <= *dev->dma_mask;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+ return paddr + get_dma_direct_offset(dev);
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+ return daddr - get_dma_direct_offset(dev);
+}
+
#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)
#ifdef CONFIG_NOT_COHERENT_CACHE
diff --git a/arch/powerpc/kernel/dma-swiotlb.c b/arch/powerpc/kernel/dma-swiotlb.c
index 68ccf11..e8a57de 100644
--- a/arch/powerpc/kernel/dma-swiotlb.c
+++ b/arch/powerpc/kernel/dma-swiotlb.c
@@ -24,50 +24,12 @@
int swiotlb __read_mostly;
unsigned int ppc_swiotlb_enable;
-void *swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t addr)
-{
- unsigned long pfn = PFN_DOWN(swiotlb_bus_to_phys(hwdev, addr));
- void *pageaddr = page_address(pfn_to_page(pfn));
-
- if (pageaddr != NULL)
- return pageaddr + (addr % PAGE_SIZE);
- return NULL;
-}
-
-dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
-{
- return paddr + get_dma_direct_offset(hwdev);
-}
-
-phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
-
-{
- return baddr - get_dma_direct_offset(hwdev);
-}
-
-/*
- * Determine if an address needs bounce buffering via swiotlb.
- * Going forward I expect the swiotlb code to generalize on using
- * a dma_ops->addr_needs_map, and this function will move from here to the
- * generic swiotlb code.
- */
-int
-swiotlb_arch_address_needs_mapping(struct device *hwdev, dma_addr_t addr,
- size_t size)
-{
- struct dma_mapping_ops *dma_ops = get_dma_ops(hwdev);
-
- BUG_ON(!dma_ops);
- return dma_ops->addr_needs_map(hwdev, addr, size);
-}
-
/*
* 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)
{
- u64 mask = dma_get_mask(hwdev);
dma_addr_t max;
struct pci_controller *hose;
struct pci_dev *pdev = to_pci_dev(hwdev);
@@ -79,16 +41,9 @@ swiotlb_pci_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
if ((addr + size > max) | (addr < hose->dma_window_base_cur))
return 1;
- return !is_buffer_dma_capable(mask, addr, size);
-}
-
-static int
-swiotlb_addr_needs_map(struct device *hwdev, dma_addr_t addr, size_t size)
-{
- return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
+ return 0;
}
-
/*
* At the moment, all platforms that use this code only require
* swiotlb to be used if we're operating on HIGHMEM. Since
@@ -104,7 +59,6 @@ struct dma_mapping_ops swiotlb_dma_ops = {
.dma_supported = swiotlb_dma_supported,
.map_page = swiotlb_map_page,
.unmap_page = swiotlb_unmap_page,
- .addr_needs_map = swiotlb_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,
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig
index 3f8b6a9..233cff5 100644
--- a/arch/sparc/Kconfig
+++ b/arch/sparc/Kconfig
@@ -25,6 +25,8 @@ config SPARC
select ARCH_WANT_OPTIONAL_GPIOLIB
select RTC_CLASS
select RTC_DRV_M48T59
+ select HAVE_DMA_ATTRS
+ select HAVE_DMA_API_DEBUG
config SPARC32
def_bool !64BIT
diff --git a/arch/sparc/include/asm/dma-mapping.h b/arch/sparc/include/asm/dma-mapping.h
index 204e4bf..5a8c308 100644
--- a/arch/sparc/include/asm/dma-mapping.h
+++ b/arch/sparc/include/asm/dma-mapping.h
@@ -3,6 +3,7 @@
#include <linux/scatterlist.h>
#include <linux/mm.h>
+#include <linux/dma-debug.h>
#define DMA_ERROR_CODE (~(dma_addr_t)0x0)
@@ -13,142 +14,40 @@ extern int dma_set_mask(struct device *dev, u64 dma_mask);
#define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
#define dma_is_consistent(d, h) (1)
-struct dma_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 *cpu_addr, dma_addr_t dma_handle);
- dma_addr_t (*map_page)(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction);
- void (*unmap_page)(struct device *dev, dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction direction);
- int (*map_sg)(struct device *dev, struct scatterlist *sg, int nents,
- enum dma_data_direction direction);
- void (*unmap_sg)(struct device *dev, struct scatterlist *sg,
- int nhwentries,
- enum dma_data_direction direction);
- void (*sync_single_for_cpu)(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction);
- void (*sync_single_for_device)(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction);
- void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
- int nelems,
- enum dma_data_direction direction);
- void (*sync_sg_for_device)(struct device *dev,
- struct scatterlist *sg, int nents,
- enum dma_data_direction dir);
-};
-extern const struct dma_ops *dma_ops;
+extern struct dma_map_ops *dma_ops, pci32_dma_ops;
+extern struct bus_type pci_bus_type;
-static inline void *dma_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
-{
- return dma_ops->alloc_coherent(dev, size, dma_handle, flag);
-}
-
-static inline void dma_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
-{
- 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_ops->map_page(dev, virt_to_page(cpu_addr),
- (unsigned long)cpu_addr & ~PAGE_MASK, size,
- direction);
-}
-
-static inline void dma_unmap_single(struct device *dev, dma_addr_t dma_addr,
- size_t size,
- enum dma_data_direction direction)
-{
- dma_ops->unmap_page(dev, dma_addr, size, direction);
-}
-
-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_ops->map_page(dev, page, offset, size, direction);
-}
-
-static inline void dma_unmap_page(struct device *dev, dma_addr_t dma_address,
- size_t size,
- enum dma_data_direction direction)
-{
- dma_ops->unmap_page(dev, dma_address, size, direction);
-}
-
-static inline int dma_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
-{
- return dma_ops->map_sg(dev, sg, nents, direction);
-}
-
-static inline void dma_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
{
- dma_ops->unmap_sg(dev, sg, nents, direction);
-}
-
-static inline void dma_sync_single_for_cpu(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
- dma_ops->sync_single_for_cpu(dev, dma_handle, size, direction);
+#if defined(CONFIG_SPARC32) && defined(CONFIG_PCI)
+ if (dev->bus == &pci_bus_type)
+ return &pci32_dma_ops;
+#endif
+ return dma_ops;
}
-static inline void dma_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle,
- size_t size,
- enum dma_data_direction direction)
-{
- if (dma_ops->sync_single_for_device)
- dma_ops->sync_single_for_device(dev, dma_handle, size,
- direction);
-}
+#include <asm-generic/dma-mapping-common.h>
-static inline void dma_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+ dma_addr_t *dma_handle, gfp_t flag)
{
- dma_ops->sync_sg_for_cpu(dev, sg, nelems, direction);
-}
+ struct dma_map_ops *ops = get_dma_ops(dev);
+ void *cpu_addr;
-static inline void dma_sync_sg_for_device(struct device *dev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
- if (dma_ops->sync_sg_for_device)
- dma_ops->sync_sg_for_device(dev, sg, nelems, direction);
+ cpu_addr = ops->alloc_coherent(dev, size, dma_handle, flag);
+ debug_dma_alloc_coherent(dev, size, *dma_handle, cpu_addr);
+ return cpu_addr;
}
-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 dir)
+static inline void dma_free_coherent(struct device *dev, size_t size,
+ void *cpu_addr, dma_addr_t dma_handle)
{
- dma_sync_single_for_cpu(dev, dma_handle+offset, size, dir);
-}
+ struct dma_map_ops *ops = get_dma_ops(dev);
-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 dir)
-{
- dma_sync_single_for_device(dev, dma_handle+offset, size, dir);
+ debug_dma_free_coherent(dev, size, cpu_addr, dma_handle);
+ ops->free_coherent(dev, size, cpu_addr, dma_handle);
}
-
static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
{
return (dma_addr == DMA_ERROR_CODE);
diff --git a/arch/sparc/include/asm/pci.h b/arch/sparc/include/asm/pci.h
index 6e14fd1..d9c031f 100644
--- a/arch/sparc/include/asm/pci.h
+++ b/arch/sparc/include/asm/pci.h
@@ -5,4 +5,7 @@
#else
#include <asm/pci_32.h>
#endif
+
+#include <asm-generic/pci-dma-compat.h>
+
#endif
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h
index b41c4c1..ac0e836 100644
--- a/arch/sparc/include/asm/pci_32.h
+++ b/arch/sparc/include/asm/pci_32.h
@@ -31,42 +31,8 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
*/
#define PCI_DMA_BUS_IS_PHYS (0)
-#include <asm/scatterlist.h>
-
struct pci_dev;
-/* Allocate and map kernel buffer using consistent mode DMA for a device.
- * hwdev should be valid struct pci_dev pointer for PCI devices.
- */
-extern void *pci_alloc_consistent(struct pci_dev *hwdev, size_t size, dma_addr_t *dma_handle);
-
-/* Free and unmap a consistent DMA buffer.
- * cpu_addr is what was returned from pci_alloc_consistent,
- * size must be the same as what as passed into pci_alloc_consistent,
- * and likewise dma_addr must be the same as what *dma_addrp was set to.
- *
- * References to the memory and mappings assosciated with cpu_addr/dma_addr
- * past this call are illegal.
- */
-extern void pci_free_consistent(struct pci_dev *hwdev, size_t size, void *vaddr, dma_addr_t dma_handle);
-
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_for_cpu is performed.
- */
-extern dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size, int direction);
-
-/* Unmap a single streaming mode DMA translation. The dma_addr and size
- * must match what was provided for in a previous pci_map_single call. All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
-extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t size, int direction);
-
/* pci_unmap_{single,page} is not a nop, thus... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
@@ -81,69 +47,6 @@ extern void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t dma_addr, size_t
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
-/*
- * Same as above, only with pages instead of mapped addresses.
- */
-extern dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
- unsigned long offset, size_t size, int direction);
-extern void pci_unmap_page(struct pci_dev *hwdev,
- dma_addr_t dma_address, size_t size, int direction);
-
-/* Map a set of buffers described by scatterlist in streaming
- * mode for DMA. This is the scather-gather version of the
- * above pci_map_single interface. Here the scatter gather list
- * elements are each tagged with the appropriate dma address
- * and length. They are obtained via sg_dma_{address,length}(SG).
- *
- * NOTE: An implementation may be able to use a smaller number of
- * DMA address/length pairs than there are SG table elements.
- * (for example via virtual mapping capabilities)
- * The routine returns the number of addr/length pairs actually
- * used, at most nents.
- *
- * Device ownership issues as mentioned above for pci_map_single are
- * the same here.
- */
-extern int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nents, int direction);
-
-/* Unmap a set of streaming mode DMA translations.
- * Again, cpu read rules concerning calls here are the same as for
- * pci_unmap_single() above.
- */
-extern void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sg, int nhwents, int direction);
-
-/* Make physical memory consistent for a single
- * streaming mode DMA translation after a transfer.
- *
- * If you perform a pci_map_single() but wish to interrogate the
- * buffer using the cpu, yet do not wish to teardown the PCI dma
- * mapping, you must call this function before doing so. At the
- * next point you give the PCI dma address back to the card, you
- * must first perform a pci_dma_sync_for_device, and then the device
- * again owns the buffer.
- */
-extern void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction);
-extern void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t dma_handle, size_t size, int direction);
-
-/* Make physical memory consistent for a set of streaming
- * mode DMA translations after a transfer.
- *
- * The same as pci_dma_sync_single_* but for a scatter-gather list,
- * same rules and usage.
- */
-extern void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
-extern void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sg, int nelems, int direction);
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly. For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-static inline int pci_dma_supported(struct pci_dev *hwdev, u64 mask)
-{
- return 1;
-}
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
@@ -154,14 +57,6 @@ static inline void pci_dma_burst_advice(struct pci_dev *pdev,
}
#endif
-#define PCI_DMA_ERROR_CODE (~(dma_addr_t)0x0)
-
-static inline int pci_dma_mapping_error(struct pci_dev *pdev,
- dma_addr_t dma_addr)
-{
- return (dma_addr == PCI_DMA_ERROR_CODE);
-}
-
struct device_node;
extern struct device_node *pci_device_to_OF_node(struct pci_dev *pdev);
diff --git a/arch/sparc/include/asm/pci_64.h b/arch/sparc/include/asm/pci_64.h
index 7a1e356..5cc9f6a 100644
--- a/arch/sparc/include/asm/pci_64.h
+++ b/arch/sparc/include/asm/pci_64.h
@@ -35,37 +35,6 @@ static inline void pcibios_penalize_isa_irq(int irq, int active)
*/
#define PCI_DMA_BUS_IS_PHYS (0)
-static inline void *pci_alloc_consistent(struct pci_dev *pdev, size_t size,
- dma_addr_t *dma_handle)
-{
- return dma_alloc_coherent(&pdev->dev, size, dma_handle, GFP_ATOMIC);
-}
-
-static inline void pci_free_consistent(struct pci_dev *pdev, size_t size,
- void *vaddr, dma_addr_t dma_handle)
-{
- return dma_free_coherent(&pdev->dev, size, vaddr, dma_handle);
-}
-
-static inline dma_addr_t pci_map_single(struct pci_dev *pdev, void *ptr,
- size_t size, int direction)
-{
- return dma_map_single(&pdev->dev, ptr, size,
- (enum dma_data_direction) direction);
-}
-
-static inline void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr,
- size_t size, int direction)
-{
- dma_unmap_single(&pdev->dev, dma_addr, size,
- (enum dma_data_direction) direction);
-}
-
-#define pci_map_page(dev, page, off, size, dir) \
- pci_map_single(dev, (page_address(page) + (off)), size, dir)
-#define pci_unmap_page(dev,addr,sz,dir) \
- pci_unmap_single(dev,addr,sz,dir)
-
/* pci_unmap_{single,page} is not a nop, thus... */
#define DECLARE_PCI_UNMAP_ADDR(ADDR_NAME) \
dma_addr_t ADDR_NAME;
@@ -80,57 +49,6 @@ static inline void pci_unmap_single(struct pci_dev *pdev, dma_addr_t dma_addr,
#define pci_unmap_len_set(PTR, LEN_NAME, VAL) \
(((PTR)->LEN_NAME) = (VAL))
-static inline int pci_map_sg(struct pci_dev *pdev, struct scatterlist *sg,
- int nents, int direction)
-{
- return dma_map_sg(&pdev->dev, sg, nents,
- (enum dma_data_direction) direction);
-}
-
-static inline void pci_unmap_sg(struct pci_dev *pdev, struct scatterlist *sg,
- int nents, int direction)
-{
- dma_unmap_sg(&pdev->dev, sg, nents,
- (enum dma_data_direction) direction);
-}
-
-static inline void pci_dma_sync_single_for_cpu(struct pci_dev *pdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- dma_sync_single_for_cpu(&pdev->dev, dma_handle, size,
- (enum dma_data_direction) direction);
-}
-
-static inline void pci_dma_sync_single_for_device(struct pci_dev *pdev,
- dma_addr_t dma_handle,
- size_t size, int direction)
-{
- /* No flushing needed to sync cpu writes to the device. */
-}
-
-static inline void pci_dma_sync_sg_for_cpu(struct pci_dev *pdev,
- struct scatterlist *sg,
- int nents, int direction)
-{
- dma_sync_sg_for_cpu(&pdev->dev, sg, nents,
- (enum dma_data_direction) direction);
-}
-
-static inline void pci_dma_sync_sg_for_device(struct pci_dev *pdev,
- struct scatterlist *sg,
- int nelems, int direction)
-{
- /* No flushing needed to sync cpu writes to the device. */
-}
-
-/* Return whether the given PCI device DMA address mask can
- * be supported properly. For example, if your device can
- * only drive the low 24-bits during PCI bus mastering, then
- * you would pass 0x00ffffff as the mask to this function.
- */
-extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
-
/* PCI IOMMU mapping bypass support. */
/* PCI 64-bit addressing works for all slots on all controller
@@ -140,12 +58,6 @@ extern int pci_dma_supported(struct pci_dev *hwdev, u64 mask);
#define PCI64_REQUIRED_MASK (~(dma64_addr_t)0)
#define PCI64_ADDR_BASE 0xfffc000000000000UL
-static inline int pci_dma_mapping_error(struct pci_dev *pdev,
- dma_addr_t dma_addr)
-{
- return dma_mapping_error(&pdev->dev, dma_addr);
-}
-
#ifdef CONFIG_PCI
static inline void pci_dma_burst_advice(struct pci_dev *pdev,
enum pci_dma_burst_strategy *strat,
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile
index 475ce46..29b88a5 100644
--- a/arch/sparc/kernel/Makefile
+++ b/arch/sparc/kernel/Makefile
@@ -61,7 +61,7 @@ obj-$(CONFIG_SPARC64_SMP) += cpumap.o
obj-$(CONFIG_SPARC32) += devres.o
devres-y := ../../../kernel/irq/devres.o
-obj-$(CONFIG_SPARC32) += dma.o
+obj-y += dma.o
obj-$(CONFIG_SPARC32_PCI) += pcic.o
diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c
index 524c32f..e1ba8ee 100644
--- a/arch/sparc/kernel/dma.c
+++ b/arch/sparc/kernel/dma.c
@@ -1,178 +1,13 @@
-/* dma.c: PCI and SBUS DMA accessors for 32-bit sparc.
- *
- * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
- */
-
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/dma-mapping.h>
-#include <linux/scatterlist.h>
-#include <linux/mm.h>
-
-#ifdef CONFIG_PCI
-#include <linux/pci.h>
-#endif
+#include <linux/dma-debug.h>
-#include "dma.h"
+#define PREALLOC_DMA_DEBUG_ENTRIES (1 << 15)
-int dma_supported(struct device *dev, u64 mask)
+static int __init dma_init(void)
{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type)
- return pci_dma_supported(to_pci_dev(dev), mask);
-#endif
+ dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
return 0;
}
-EXPORT_SYMBOL(dma_supported);
-
-int dma_set_mask(struct device *dev, u64 dma_mask)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type)
- return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
-#endif
- return -EOPNOTSUPP;
-}
-EXPORT_SYMBOL(dma_set_mask);
-
-static void *dma32_alloc_coherent(struct device *dev, size_t size,
- dma_addr_t *dma_handle, gfp_t flag)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type)
- return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle);
-#endif
- return sbus_alloc_consistent(dev, size, dma_handle);
-}
-
-static void dma32_free_coherent(struct device *dev, size_t size,
- void *cpu_addr, dma_addr_t dma_handle)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_free_consistent(to_pci_dev(dev), size,
- cpu_addr, dma_handle);
- return;
- }
-#endif
- sbus_free_consistent(dev, size, cpu_addr, dma_handle);
-}
-
-static dma_addr_t dma32_map_page(struct device *dev, struct page *page,
- unsigned long offset, size_t size,
- enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type)
- return pci_map_page(to_pci_dev(dev), page, offset,
- size, (int)direction);
-#endif
- return sbus_map_single(dev, page_address(page) + offset,
- size, (int)direction);
-}
-
-static void dma32_unmap_page(struct device *dev, dma_addr_t dma_address,
- size_t size, enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_unmap_page(to_pci_dev(dev), dma_address,
- size, (int)direction);
- return;
- }
-#endif
- sbus_unmap_single(dev, dma_address, size, (int)direction);
-}
-
-static int dma32_map_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type)
- return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction);
-#endif
- return sbus_map_sg(dev, sg, nents, direction);
-}
-
-void dma32_unmap_sg(struct device *dev, struct scatterlist *sg,
- int nents, enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_unmap_sg(to_pci_dev(dev), sg, nents, (int)direction);
- return;
- }
-#endif
- sbus_unmap_sg(dev, sg, nents, (int)direction);
-}
-
-static void dma32_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
- size_t size,
- enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle,
- size, (int)direction);
- return;
- }
-#endif
- sbus_dma_sync_single_for_cpu(dev, dma_handle, size, (int) direction);
-}
-
-static void dma32_sync_single_for_device(struct device *dev,
- dma_addr_t dma_handle, size_t size,
- enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle,
- size, (int)direction);
- return;
- }
-#endif
- sbus_dma_sync_single_for_device(dev, dma_handle, size, (int) direction);
-}
-
-static void dma32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
- int nelems, enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg,
- nelems, (int)direction);
- return;
- }
-#endif
- BUG();
-}
-
-static void dma32_sync_sg_for_device(struct device *dev,
- struct scatterlist *sg, int nelems,
- enum dma_data_direction direction)
-{
-#ifdef CONFIG_PCI
- if (dev->bus == &pci_bus_type) {
- pci_dma_sync_sg_for_device(to_pci_dev(dev), sg,
- nelems, (int)direction);
- return;
- }
-#endif
- BUG();
-}
-
-static const struct dma_ops dma32_dma_ops = {
- .alloc_coherent = dma32_alloc_coherent,
- .free_coherent = dma32_free_coherent,
- .map_page = dma32_map_page,
- .unmap_page = dma32_unmap_page,
- .map_sg = dma32_map_sg,
- .unmap_sg = dma32_unmap_sg,
- .sync_single_for_cpu = dma32_sync_single_for_cpu,
- .sync_single_for_device = dma32_sync_single_for_device,
- .sync_sg_for_cpu = dma32_sync_sg_for_cpu,
- .sync_sg_for_device = dma32_sync_sg_for_device,
-};
-
-const struct dma_ops *dma_ops = &dma32_dma_ops;
-EXPORT_SYMBOL(dma_ops);
+fs_initcall(dma_init);
diff --git a/arch/sparc/kernel/dma.h b/arch/sparc/kernel/dma.h
deleted file mode 100644
index f8d8951..0000000
--- a/arch/sparc/kernel/dma.h
+++ /dev/null
@@ -1,14 +0,0 @@
-void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp);
-void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba);
-dma_addr_t sbus_map_single(struct device *dev, void *va,
- size_t len, int direction);
-void sbus_unmap_single(struct device *dev, dma_addr_t ba,
- size_t n, int direction);
-int sbus_map_sg(struct device *dev, struct scatterlist *sg,
- int n, int direction);
-void sbus_unmap_sg(struct device *dev, struct scatterlist *sg,
- int n, int direction);
-void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba,
- size_t size, int direction);
-void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba,
- size_t size, int direction);
diff --git a/arch/sparc/kernel/iommu.c b/arch/sparc/kernel/iommu.c
index 0aeaefe..7690cc2 100644
--- a/arch/sparc/kernel/iommu.c
+++ b/arch/sparc/kernel/iommu.c
@@ -353,7 +353,8 @@ static void dma_4u_free_coherent(struct device *dev, size_t size,
static dma_addr_t dma_4u_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t sz,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct iommu *iommu;
struct strbuf *strbuf;
@@ -474,7 +475,8 @@ do_flush_sync:
}
static void dma_4u_unmap_page(struct device *dev, dma_addr_t bus_addr,
- size_t sz, enum dma_data_direction direction)
+ size_t sz, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct iommu *iommu;
struct strbuf *strbuf;
@@ -520,7 +522,8 @@ static void dma_4u_unmap_page(struct device *dev, dma_addr_t bus_addr,
}
static int dma_4u_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct scatterlist *s, *outs, *segstart;
unsigned long flags, handle, prot, ctx;
@@ -691,7 +694,8 @@ static unsigned long fetch_sg_ctx(struct iommu *iommu, struct scatterlist *sg)
}
static void dma_4u_unmap_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
unsigned long flags, ctx;
struct scatterlist *sg;
@@ -822,7 +826,7 @@ static void dma_4u_sync_sg_for_cpu(struct device *dev,
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static const struct dma_ops sun4u_dma_ops = {
+static struct dma_map_ops sun4u_dma_ops = {
.alloc_coherent = dma_4u_alloc_coherent,
.free_coherent = dma_4u_free_coherent,
.map_page = dma_4u_map_page,
@@ -833,9 +837,11 @@ static const struct dma_ops sun4u_dma_ops = {
.sync_sg_for_cpu = dma_4u_sync_sg_for_cpu,
};
-const struct dma_ops *dma_ops = &sun4u_dma_ops;
+struct dma_map_ops *dma_ops = &sun4u_dma_ops;
EXPORT_SYMBOL(dma_ops);
+extern int pci64_dma_supported(struct pci_dev *pdev, u64 device_mask);
+
int dma_supported(struct device *dev, u64 device_mask)
{
struct iommu *iommu = dev->archdata.iommu;
@@ -849,7 +855,7 @@ int dma_supported(struct device *dev, u64 device_mask)
#ifdef CONFIG_PCI
if (dev->bus == &pci_bus_type)
- return pci_dma_supported(to_pci_dev(dev), device_mask);
+ return pci64_dma_supported(to_pci_dev(dev), device_mask);
#endif
return 0;
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 87ea0d0..edbea23 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -48,8 +48,6 @@
#include <asm/iommu.h>
#include <asm/io-unit.h>
-#include "dma.h"
-
#define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */
static struct resource *_sparc_find_resource(struct resource *r,
@@ -246,7 +244,8 @@ EXPORT_SYMBOL(sbus_set_sbus64);
* Typically devices use them for control blocks.
* CPU may access them without any explicit flushing.
*/
-void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp)
+static void *sbus_alloc_coherent(struct device *dev, size_t len,
+ dma_addr_t *dma_addrp, gfp_t gfp)
{
struct of_device *op = to_of_device(dev);
unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
@@ -299,7 +298,8 @@ err_nopages:
return NULL;
}
-void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba)
+static void sbus_free_coherent(struct device *dev, size_t n, void *p,
+ dma_addr_t ba)
{
struct resource *res;
struct page *pgv;
@@ -317,7 +317,7 @@ void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba)
n = (n + PAGE_SIZE-1) & PAGE_MASK;
if ((res->end-res->start)+1 != n) {
- printk("sbus_free_consistent: region 0x%lx asked 0x%lx\n",
+ printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
(long)((res->end-res->start)+1), n);
return;
}
@@ -337,8 +337,13 @@ void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba)
* CPU view of this memory may be inconsistent with
* a device view and explicit flushing is necessary.
*/
-dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int direction)
+static dma_addr_t sbus_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t len,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
+ void *va = page_address(page) + offset;
+
/* XXX why are some lengths signed, others unsigned? */
if (len <= 0) {
return 0;
@@ -350,12 +355,14 @@ dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int directi
return mmu_get_scsi_one(dev, va, len);
}
-void sbus_unmap_single(struct device *dev, dma_addr_t ba, size_t n, int direction)
+static void sbus_unmap_page(struct device *dev, dma_addr_t ba, size_t n,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
{
mmu_release_scsi_one(dev, ba, n);
}
-int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction)
+static int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
{
mmu_get_scsi_sgl(dev, sg, n);
@@ -366,19 +373,38 @@ int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction
return n;
}
-void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direction)
+static void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n,
+ enum dma_data_direction dir, struct dma_attrs *attrs)
{
mmu_release_scsi_sgl(dev, sg, n);
}
-void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction)
+static void sbus_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
+ int n, enum dma_data_direction dir)
{
+ BUG();
}
-void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction)
+static void sbus_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
+ int n, enum dma_data_direction dir)
{
+ BUG();
}
+struct dma_map_ops sbus_dma_ops = {
+ .alloc_coherent = sbus_alloc_coherent,
+ .free_coherent = sbus_free_coherent,
+ .map_page = sbus_map_page,
+ .unmap_page = sbus_unmap_page,
+ .map_sg = sbus_map_sg,
+ .unmap_sg = sbus_unmap_sg,
+ .sync_sg_for_cpu = sbus_sync_sg_for_cpu,
+ .sync_sg_for_device = sbus_sync_sg_for_device,
+};
+
+struct dma_map_ops *dma_ops = &sbus_dma_ops;
+EXPORT_SYMBOL(dma_ops);
+
static int __init sparc_register_ioport(void)
{
register_proc_sparc_ioport();
@@ -395,7 +421,8 @@ arch_initcall(sparc_register_ioport);
/* Allocate and map kernel buffer using consistent mode DMA for a device.
* hwdev should be valid struct pci_dev pointer for PCI devices.
*/
-void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
+static void *pci32_alloc_coherent(struct device *dev, size_t len,
+ dma_addr_t *pba, gfp_t gfp)
{
unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
unsigned long va;
@@ -439,7 +466,6 @@ void *pci_alloc_consistent(struct pci_dev *pdev, size_t len, dma_addr_t *pba)
*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
return (void *) res->start;
}
-EXPORT_SYMBOL(pci_alloc_consistent);
/* Free and unmap a consistent DMA buffer.
* cpu_addr is what was returned from pci_alloc_consistent,
@@ -449,7 +475,8 @@ EXPORT_SYMBOL(pci_alloc_consistent);
* References to the memory and mappings associated with cpu_addr/dma_addr
* past this call are illegal.
*/
-void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
+static void pci32_free_coherent(struct device *dev, size_t n, void *p,
+ dma_addr_t ba)
{
struct resource *res;
unsigned long pgp;
@@ -481,60 +508,18 @@ void pci_free_consistent(struct pci_dev *pdev, size_t n, void *p, dma_addr_t ba)
free_pages(pgp, get_order(n));
}
-EXPORT_SYMBOL(pci_free_consistent);
-
-/* Map a single buffer of the indicated size for DMA in streaming mode.
- * The 32-bit bus address to use is returned.
- *
- * Once the device is given the dma address, the device owns this memory
- * until either pci_unmap_single or pci_dma_sync_single_* is performed.
- */
-dma_addr_t pci_map_single(struct pci_dev *hwdev, void *ptr, size_t size,
- int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- /* IIep is write-through, not flushing. */
- return virt_to_phys(ptr);
-}
-EXPORT_SYMBOL(pci_map_single);
-
-/* Unmap a single streaming mode DMA translation. The dma_addr and size
- * must match what was provided for in a previous pci_map_single call. All
- * other usages are undefined.
- *
- * After this call, reads by the cpu to the buffer are guaranteed to see
- * whatever the device wrote there.
- */
-void pci_unmap_single(struct pci_dev *hwdev, dma_addr_t ba, size_t size,
- int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- if (direction != PCI_DMA_TODEVICE) {
- mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
- (size + PAGE_SIZE-1) & PAGE_MASK);
- }
-}
-EXPORT_SYMBOL(pci_unmap_single);
/*
* Same as pci_map_single, but with pages.
*/
-dma_addr_t pci_map_page(struct pci_dev *hwdev, struct page *page,
- unsigned long offset, size_t size, int direction)
+static dma_addr_t pci32_map_page(struct device *dev, struct page *page,
+ unsigned long offset, size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
- BUG_ON(direction == PCI_DMA_NONE);
/* IIep is write-through, not flushing. */
return page_to_phys(page) + offset;
}
-EXPORT_SYMBOL(pci_map_page);
-
-void pci_unmap_page(struct pci_dev *hwdev,
- dma_addr_t dma_address, size_t size, int direction)
-{
- BUG_ON(direction == PCI_DMA_NONE);
- /* mmu_inval_dma_area XXX */
-}
-EXPORT_SYMBOL(pci_unmap_page);
/* Map a set of buffers described by scatterlist in streaming
* mode for DMA. This is the scather-gather version of the
@@ -551,13 +536,13 @@ EXPORT_SYMBOL(pci_unmap_page);
* Device ownership issues as mentioned above for pci_map_single are
* the same here.
*/
-int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
- int direction)
+static int pci32_map_sg(struct device *device, struct scatterlist *sgl,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
struct scatterlist *sg;
int n;
- BUG_ON(direction == PCI_DMA_NONE);
/* IIep is write-through, not flushing. */
for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL);
@@ -566,20 +551,19 @@ int pci_map_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
}
return nents;
}
-EXPORT_SYMBOL(pci_map_sg);
/* Unmap a set of streaming mode DMA translations.
* Again, cpu read rules concerning calls here are the same as for
* pci_unmap_single() above.
*/
-void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
- int direction)
+static void pci32_unmap_sg(struct device *dev, struct scatterlist *sgl,
+ int nents, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
{
struct scatterlist *sg;
int n;
- BUG_ON(direction == PCI_DMA_NONE);
- if (direction != PCI_DMA_TODEVICE) {
+ if (dir != PCI_DMA_TODEVICE) {
for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL);
mmu_inval_dma_area(
@@ -588,7 +572,6 @@ void pci_unmap_sg(struct pci_dev *hwdev, struct scatterlist *sgl, int nents,
}
}
}
-EXPORT_SYMBOL(pci_unmap_sg);
/* Make physical memory consistent for a single
* streaming mode DMA translation before or after a transfer.
@@ -600,25 +583,23 @@ EXPORT_SYMBOL(pci_unmap_sg);
* must first perform a pci_dma_sync_for_device, and then the
* device again owns the buffer.
*/
-void pci_dma_sync_single_for_cpu(struct pci_dev *hwdev, dma_addr_t ba, size_t size, int direction)
+static void pci32_sync_single_for_cpu(struct device *dev, dma_addr_t ba,
+ size_t size, enum dma_data_direction dir)
{
- BUG_ON(direction == PCI_DMA_NONE);
- if (direction != PCI_DMA_TODEVICE) {
+ if (dir != PCI_DMA_TODEVICE) {
mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
(size + PAGE_SIZE-1) & PAGE_MASK);
}
}
-EXPORT_SYMBOL(pci_dma_sync_single_for_cpu);
-void pci_dma_sync_single_for_device(struct pci_dev *hwdev, dma_addr_t ba, size_t size, int direction)
+static void pci32_sync_single_for_device(struct device *dev, dma_addr_t ba,
+ size_t size, enum dma_data_direction dir)
{
- BUG_ON(direction == PCI_DMA_NONE);
- if (direction != PCI_DMA_TODEVICE) {
+ if (dir != PCI_DMA_TODEVICE) {
mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
(size + PAGE_SIZE-1) & PAGE_MASK);
}
}
-EXPORT_SYMBOL(pci_dma_sync_single_for_device);
/* Make physical memory consistent for a set of streaming
* mode DMA translations after a transfer.
@@ -626,13 +607,13 @@ EXPORT_SYMBOL(pci_dma_sync_single_for_device);
* The same as pci_dma_sync_single_* but for a scatter-gather list,
* same rules and usage.
*/
-void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction)
+static void pci32_sync_sg_for_cpu(struct device *dev, struct scatterlist *sgl,
+ int nents, enum dma_data_direction dir)
{
struct scatterlist *sg;
int n;
- BUG_ON(direction == PCI_DMA_NONE);
- if (direction != PCI_DMA_TODEVICE) {
+ if (dir != PCI_DMA_TODEVICE) {
for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL);
mmu_inval_dma_area(
@@ -641,15 +622,14 @@ void pci_dma_sync_sg_for_cpu(struct pci_dev *hwdev, struct scatterlist *sgl, int
}
}
}
-EXPORT_SYMBOL(pci_dma_sync_sg_for_cpu);
-void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl, int nents, int direction)
+static void pci32_sync_sg_for_device(struct device *device, struct scatterlist *sgl,
+ int nents, enum dma_data_direction dir)
{
struct scatterlist *sg;
int n;
- BUG_ON(direction == PCI_DMA_NONE);
- if (direction != PCI_DMA_TODEVICE) {
+ if (dir != PCI_DMA_TODEVICE) {
for_each_sg(sgl, sg, nents, n) {
BUG_ON(page_address(sg_page(sg)) == NULL);
mmu_inval_dma_area(
@@ -658,9 +638,49 @@ void pci_dma_sync_sg_for_device(struct pci_dev *hwdev, struct scatterlist *sgl,
}
}
}
-EXPORT_SYMBOL(pci_dma_sync_sg_for_device);
+
+struct dma_map_ops pci32_dma_ops = {
+ .alloc_coherent = pci32_alloc_coherent,
+ .free_coherent = pci32_free_coherent,
+ .map_page = pci32_map_page,
+ .map_sg = pci32_map_sg,
+ .unmap_sg = pci32_unmap_sg,
+ .sync_single_for_cpu = pci32_sync_single_for_cpu,
+ .sync_single_for_device = pci32_sync_single_for_device,
+ .sync_sg_for_cpu = pci32_sync_sg_for_cpu,
+ .sync_sg_for_device = pci32_sync_sg_for_device,
+};
+EXPORT_SYMBOL(pci32_dma_ops);
+
#endif /* CONFIG_PCI */
+/*
+ * Return whether the given PCI device DMA address mask can be
+ * supported properly. For example, if your device can only drive the
+ * low 24-bits during PCI bus mastering, then you would pass
+ * 0x00ffffff as the mask to this function.
+ */
+int dma_supported(struct device *dev, u64 mask)
+{
+#ifdef CONFIG_PCI
+ if (dev->bus == &pci_bus_type)
+ return 1;
+#endif
+ return 0;
+}
+EXPORT_SYMBOL(dma_supported);
+
+int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+#ifdef CONFIG_PCI
+ if (dev->bus == &pci_bus_type)
+ return pci_set_dma_mask(to_pci_dev(dev), dma_mask);
+#endif
+ return -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(dma_set_mask);
+
+
#ifdef CONFIG_PROC_FS
static int
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 57859ad..c686486 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -1039,7 +1039,7 @@ static void ali_sound_dma_hack(struct pci_dev *pdev, int set_bit)
pci_dev_put(ali_isa_bridge);
}
-int pci_dma_supported(struct pci_dev *pdev, u64 device_mask)
+int pci64_dma_supported(struct pci_dev *pdev, u64 device_mask)
{
u64 dma_addr_mask;
diff --git a/arch/sparc/kernel/pci_sun4v.c b/arch/sparc/kernel/pci_sun4v.c
index 2485eaa..23c33ff 100644
--- a/arch/sparc/kernel/pci_sun4v.c
+++ b/arch/sparc/kernel/pci_sun4v.c
@@ -232,7 +232,8 @@ static void dma_4v_free_coherent(struct device *dev, size_t size, void *cpu,
static dma_addr_t dma_4v_map_page(struct device *dev, struct page *page,
unsigned long offset, size_t sz,
- enum dma_data_direction direction)
+ enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct iommu *iommu;
unsigned long flags, npages, oaddr;
@@ -296,7 +297,8 @@ iommu_map_fail:
}
static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
- size_t sz, enum dma_data_direction direction)
+ size_t sz, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct pci_pbm_info *pbm;
struct iommu *iommu;
@@ -336,7 +338,8 @@ static void dma_4v_unmap_page(struct device *dev, dma_addr_t bus_addr,
}
static int dma_4v_map_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct scatterlist *s, *outs, *segstart;
unsigned long flags, handle, prot;
@@ -478,7 +481,8 @@ iommu_map_failed:
}
static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
- int nelems, enum dma_data_direction direction)
+ int nelems, enum dma_data_direction direction,
+ struct dma_attrs *attrs)
{
struct pci_pbm_info *pbm;
struct scatterlist *sg;
@@ -521,29 +525,13 @@ static void dma_4v_unmap_sg(struct device *dev, struct scatterlist *sglist,
spin_unlock_irqrestore(&iommu->lock, flags);
}
-static void dma_4v_sync_single_for_cpu(struct device *dev,
- dma_addr_t bus_addr, size_t sz,
- enum dma_data_direction direction)
-{
- /* Nothing to do... */
-}
-
-static void dma_4v_sync_sg_for_cpu(struct device *dev,
- struct scatterlist *sglist, int nelems,
- enum dma_data_direction direction)
-{
- /* Nothing to do... */
-}
-
-static const struct dma_ops sun4v_dma_ops = {
+static struct dma_map_ops sun4v_dma_ops = {
.alloc_coherent = dma_4v_alloc_coherent,
.free_coherent = dma_4v_free_coherent,
.map_page = dma_4v_map_page,
.unmap_page = dma_4v_unmap_page,
.map_sg = dma_4v_map_sg,
.unmap_sg = dma_4v_unmap_sg,
- .sync_single_for_cpu = dma_4v_sync_single_for_cpu,
- .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu,
};
static void __devinit pci_sun4v_scan_bus(struct pci_pbm_info *pbm,
diff --git a/arch/x86/include/asm/dma-mapping.h b/arch/x86/include/asm/dma-mapping.h
index 1c3f943..0ee770d 100644
--- a/arch/x86/include/asm/dma-mapping.h
+++ b/arch/x86/include/asm/dma-mapping.h
@@ -55,6 +55,24 @@ extern int dma_set_mask(struct device *dev, u64 mask);
extern void *dma_generic_alloc_coherent(struct device *dev, size_t size,
dma_addr_t *dma_addr, gfp_t flag);
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+ if (!dev->dma_mask)
+ return 0;
+
+ return addr + size <= *dev->dma_mask;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+ return paddr;
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+ return daddr;
+}
+
static inline void
dma_cache_sync(struct device *dev, void *vaddr, size_t size,
enum dma_data_direction dir)
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 1a041bc..3c945c0 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -147,7 +147,7 @@ again:
return NULL;
addr = page_to_phys(page);
- if (!is_buffer_dma_capable(dma_mask, addr, size)) {
+ if (addr + size > dma_mask) {
__free_pages(page, get_order(size));
if (dma_mask < DMA_BIT_MASK(32) && !(flag & GFP_DMA)) {
diff --git a/arch/x86/kernel/pci-gart_64.c b/arch/x86/kernel/pci-gart_64.c
index d2e56b8..98a827e 100644
--- a/arch/x86/kernel/pci-gart_64.c
+++ b/arch/x86/kernel/pci-gart_64.c
@@ -190,14 +190,13 @@ static void iommu_full(struct device *dev, size_t size, int dir)
static inline int
need_iommu(struct device *dev, unsigned long addr, size_t size)
{
- return force_iommu ||
- !is_buffer_dma_capable(*dev->dma_mask, addr, size);
+ return force_iommu || !dma_capable(dev, addr, size);
}
static inline int
nonforced_iommu(struct device *dev, unsigned long addr, size_t size)
{
- return !is_buffer_dma_capable(*dev->dma_mask, addr, size);
+ return !dma_capable(dev, addr, size);
}
/* Map a single continuous physical area into the IOMMU.
diff --git a/arch/x86/kernel/pci-nommu.c b/arch/x86/kernel/pci-nommu.c
index 71d412a..a3933d4 100644
--- a/arch/x86/kernel/pci-nommu.c
+++ b/arch/x86/kernel/pci-nommu.c
@@ -14,7 +14,7 @@
static int
check_addr(char *name, struct device *hwdev, dma_addr_t bus, size_t size)
{
- if (hwdev && !is_buffer_dma_capable(*hwdev->dma_mask, bus, size)) {
+ if (hwdev && !dma_capable(hwdev, bus, size)) {
if (*hwdev->dma_mask >= DMA_BIT_MASK(32))
printk(KERN_ERR
"nommu_%s: overflow %Lx+%zu of device mask %Lx\n",
@@ -79,12 +79,29 @@ static void nommu_free_coherent(struct device *dev, size_t size, void *vaddr,
free_pages((unsigned long)vaddr, get_order(size));
}
+static void nommu_sync_single_for_device(struct device *dev,
+ dma_addr_t addr, size_t size,
+ enum dma_data_direction dir)
+{
+ flush_write_buffers();
+}
+
+
+static void nommu_sync_sg_for_device(struct device *dev,
+ struct scatterlist *sg, int nelems,
+ enum dma_data_direction dir)
+{
+ flush_write_buffers();
+}
+
struct dma_map_ops nommu_dma_ops = {
- .alloc_coherent = dma_generic_alloc_coherent,
- .free_coherent = nommu_free_coherent,
- .map_sg = nommu_map_sg,
- .map_page = nommu_map_page,
- .is_phys = 1,
+ .alloc_coherent = dma_generic_alloc_coherent,
+ .free_coherent = nommu_free_coherent,
+ .map_sg = nommu_map_sg,
+ .map_page = nommu_map_page,
+ .sync_single_for_device = nommu_sync_single_for_device,
+ .sync_sg_for_device = nommu_sync_sg_for_device,
+ .is_phys = 1,
};
void __init no_iommu_init(void)
diff --git a/arch/x86/kernel/pci-swiotlb.c b/arch/x86/kernel/pci-swiotlb.c
index 6af96ee..e8a3501 100644
--- a/arch/x86/kernel/pci-swiotlb.c
+++ b/arch/x86/kernel/pci-swiotlb.c
@@ -13,31 +13,6 @@
int swiotlb __read_mostly;
-void * __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
-{
- return alloc_bootmem_low_pages(size);
-}
-
-void *swiotlb_alloc(unsigned order, unsigned long nslabs)
-{
- return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
-}
-
-dma_addr_t swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
-{
- return paddr;
-}
-
-phys_addr_t swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
-{
- return baddr;
-}
-
-int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return 0;
-}
-
static void *x86_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags)
{
diff --git a/include/asm-generic/dma-mapping-common.h b/include/asm-generic/dma-mapping-common.h
index 5406a60..e694263 100644
--- a/include/asm-generic/dma-mapping-common.h
+++ b/include/asm-generic/dma-mapping-common.h
@@ -103,7 +103,6 @@ static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
if (ops->sync_single_for_cpu)
ops->sync_single_for_cpu(dev, addr, size, dir);
debug_dma_sync_single_for_cpu(dev, addr, size, dir);
- flush_write_buffers();
}
static inline void dma_sync_single_for_device(struct device *dev,
@@ -116,7 +115,6 @@ static inline void dma_sync_single_for_device(struct device *dev,
if (ops->sync_single_for_device)
ops->sync_single_for_device(dev, addr, size, dir);
debug_dma_sync_single_for_device(dev, addr, size, dir);
- flush_write_buffers();
}
static inline void dma_sync_single_range_for_cpu(struct device *dev,
@@ -132,7 +130,6 @@ static inline void dma_sync_single_range_for_cpu(struct device *dev,
ops->sync_single_range_for_cpu(dev, addr, offset, size, dir);
debug_dma_sync_single_range_for_cpu(dev, addr, offset, size, dir);
- flush_write_buffers();
} else
dma_sync_single_for_cpu(dev, addr, size, dir);
}
@@ -150,7 +147,6 @@ static inline void dma_sync_single_range_for_device(struct device *dev,
ops->sync_single_range_for_device(dev, addr, offset, size, dir);
debug_dma_sync_single_range_for_device(dev, addr, offset, size, dir);
- flush_write_buffers();
} else
dma_sync_single_for_device(dev, addr, size, dir);
}
@@ -165,7 +161,6 @@ dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg,
if (ops->sync_sg_for_cpu)
ops->sync_sg_for_cpu(dev, sg, nelems, dir);
debug_dma_sync_sg_for_cpu(dev, sg, nelems, dir);
- flush_write_buffers();
}
static inline void
@@ -179,7 +174,6 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,
ops->sync_sg_for_device(dev, sg, nelems, dir);
debug_dma_sync_sg_for_device(dev, sg, nelems, dir);
- flush_write_buffers();
}
#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 07dfd46..c0f6c3c 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -98,11 +98,6 @@ static inline int is_device_dma_capable(struct device *dev)
return dev->dma_mask != NULL && *dev->dma_mask != DMA_MASK_NONE;
}
-static inline int is_buffer_dma_capable(u64 mask, dma_addr_t addr, size_t size)
-{
- return addr + size <= mask;
-}
-
#ifdef CONFIG_HAS_DMA
#include <asm/dma-mapping.h>
#else
diff --git a/include/linux/swiotlb.h b/include/linux/swiotlb.h
index cb1a663..73b1f1c 100644
--- a/include/linux/swiotlb.h
+++ b/include/linux/swiotlb.h
@@ -14,7 +14,6 @@ struct scatterlist;
*/
#define IO_TLB_SEGSIZE 128
-
/*
* log of the size of each IO TLB slab. The number of slabs is command line
* controllable.
@@ -24,16 +23,6 @@ struct scatterlist;
extern void
swiotlb_init(void);
-extern void *swiotlb_alloc_boot(size_t bytes, unsigned long nslabs);
-extern void *swiotlb_alloc(unsigned order, unsigned long nslabs);
-
-extern dma_addr_t swiotlb_phys_to_bus(struct device *hwdev,
- phys_addr_t address);
-extern phys_addr_t swiotlb_bus_to_phys(struct device *hwdev,
- dma_addr_t address);
-
-extern int swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size);
-
extern void
*swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_addr_t *dma_handle, gfp_t flags);
diff --git a/lib/swiotlb.c b/lib/swiotlb.c
index bffe6d7..ac25cd2 100644
--- a/lib/swiotlb.c
+++ b/lib/swiotlb.c
@@ -114,46 +114,11 @@ setup_io_tlb_npages(char *str)
__setup("swiotlb=", setup_io_tlb_npages);
/* make io_tlb_overflow tunable too? */
-void * __weak __init swiotlb_alloc_boot(size_t size, unsigned long nslabs)
-{
- return alloc_bootmem_low_pages(size);
-}
-
-void * __weak swiotlb_alloc(unsigned order, unsigned long nslabs)
-{
- return (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN, order);
-}
-
-dma_addr_t __weak swiotlb_phys_to_bus(struct device *hwdev, phys_addr_t paddr)
-{
- return paddr;
-}
-
-phys_addr_t __weak swiotlb_bus_to_phys(struct device *hwdev, dma_addr_t baddr)
-{
- return baddr;
-}
-
+/* Note that this doesn't work with highmem page */
static dma_addr_t swiotlb_virt_to_bus(struct device *hwdev,
volatile void *address)
{
- return swiotlb_phys_to_bus(hwdev, virt_to_phys(address));
-}
-
-void * __weak swiotlb_bus_to_virt(struct device *hwdev, dma_addr_t address)
-{
- return phys_to_virt(swiotlb_bus_to_phys(hwdev, address));
-}
-
-int __weak swiotlb_arch_address_needs_mapping(struct device *hwdev,
- dma_addr_t addr, size_t size)
-{
- return !is_buffer_dma_capable(dma_get_mask(hwdev), addr, size);
-}
-
-int __weak swiotlb_arch_range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return 0;
+ return phys_to_dma(hwdev, virt_to_phys(address));
}
static void swiotlb_print_info(unsigned long bytes)
@@ -189,7 +154,7 @@ swiotlb_init_with_default_size(size_t default_size)
/*
* Get IO TLB memory from the low pages
*/
- io_tlb_start = swiotlb_alloc_boot(bytes, io_tlb_nslabs);
+ io_tlb_start = alloc_bootmem_low_pages(bytes);
if (!io_tlb_start)
panic("Cannot allocate SWIOTLB buffer");
io_tlb_end = io_tlb_start + bytes;
@@ -245,7 +210,8 @@ swiotlb_late_init_with_default_size(size_t default_size)
bytes = io_tlb_nslabs << IO_TLB_SHIFT;
while ((SLABS_PER_PAGE << order) > IO_TLB_MIN_SLABS) {
- io_tlb_start = swiotlb_alloc(order, io_tlb_nslabs);
+ io_tlb_start = (void *)__get_free_pages(GFP_DMA | __GFP_NOWARN,
+ order);
if (io_tlb_start)
break;
order--;
@@ -315,20 +281,10 @@ cleanup1:
return -ENOMEM;
}
-static inline int
-address_needs_mapping(struct device *hwdev, dma_addr_t addr, size_t size)
+static int is_swiotlb_buffer(phys_addr_t paddr)
{
- return swiotlb_arch_address_needs_mapping(hwdev, addr, size);
-}
-
-static inline int range_needs_mapping(phys_addr_t paddr, size_t size)
-{
- return swiotlb_force || swiotlb_arch_range_needs_mapping(paddr, size);
-}
-
-static int is_swiotlb_buffer(char *addr)
-{
- return addr >= io_tlb_start && addr < io_tlb_end;
+ return paddr >= virt_to_phys(io_tlb_start) &&
+ paddr < virt_to_phys(io_tlb_end);
}
/*
@@ -561,9 +517,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dma_mask = hwdev->coherent_dma_mask;
ret = (void *)__get_free_pages(flags, order);
- if (ret &&
- !is_buffer_dma_capable(dma_mask, swiotlb_virt_to_bus(hwdev, ret),
- size)) {
+ if (ret && swiotlb_virt_to_bus(hwdev, ret) + size > dma_mask) {
/*
* The allocated memory isn't reachable by the device.
*/
@@ -585,7 +539,7 @@ swiotlb_alloc_coherent(struct device *hwdev, size_t size,
dev_addr = swiotlb_virt_to_bus(hwdev, ret);
/* Confirm address can be DMA'd by device */
- if (!is_buffer_dma_capable(dma_mask, dev_addr, size)) {
+ if (dev_addr + size > dma_mask) {
printk("hwdev DMA mask = 0x%016Lx, dev_addr = 0x%016Lx\n",
(unsigned long long)dma_mask,
(unsigned long long)dev_addr);
@@ -601,11 +555,13 @@ EXPORT_SYMBOL(swiotlb_alloc_coherent);
void
swiotlb_free_coherent(struct device *hwdev, size_t size, void *vaddr,
- dma_addr_t dma_handle)
+ dma_addr_t dev_addr)
{
+ phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
+
WARN_ON(irqs_disabled());
- if (!is_swiotlb_buffer(vaddr))
- free_pages((unsigned long) vaddr, get_order(size));
+ if (!is_swiotlb_buffer(paddr))
+ free_pages((unsigned long)vaddr, get_order(size));
else
/* DMA_TO_DEVICE to avoid memcpy in unmap_single */
do_unmap_single(hwdev, vaddr, size, DMA_TO_DEVICE);
@@ -625,12 +581,15 @@ swiotlb_full(struct device *dev, size_t size, int dir, int do_panic)
printk(KERN_ERR "DMA: Out of SW-IOMMU space for %zu bytes at "
"device %s\n", size, dev ? dev_name(dev) : "?");
- if (size > io_tlb_overflow && do_panic) {
- if (dir == DMA_FROM_DEVICE || dir == DMA_BIDIRECTIONAL)
- panic("DMA: Memory would be corrupted\n");
- if (dir == DMA_TO_DEVICE || dir == DMA_BIDIRECTIONAL)
- panic("DMA: Random memory would be DMAed\n");
- }
+ if (size <= io_tlb_overflow || !do_panic)
+ return;
+
+ if (dir == DMA_BIDIRECTIONAL)
+ panic("DMA: Random memory could be DMA accessed\n");
+ if (dir == DMA_FROM_DEVICE)
+ panic("DMA: Random memory could be DMA written\n");
+ if (dir == DMA_TO_DEVICE)
+ panic("DMA: Random memory could be DMA read\n");
}
/*
@@ -646,7 +605,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
struct dma_attrs *attrs)
{
phys_addr_t phys = page_to_phys(page) + offset;
- dma_addr_t dev_addr = swiotlb_phys_to_bus(dev, phys);
+ dma_addr_t dev_addr = phys_to_dma(dev, phys);
void *map;
BUG_ON(dir == DMA_NONE);
@@ -655,8 +614,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
* we can safely return the device addr and not worry about bounce
* buffering it.
*/
- if (!address_needs_mapping(dev, dev_addr, size) &&
- !range_needs_mapping(phys, size))
+ if (dma_capable(dev, dev_addr, size) && !swiotlb_force)
return dev_addr;
/*
@@ -673,7 +631,7 @@ dma_addr_t swiotlb_map_page(struct device *dev, struct page *page,
/*
* Ensure that the address returned is DMA'ble
*/
- if (address_needs_mapping(dev, dev_addr, size))
+ if (!dma_capable(dev, dev_addr, size))
panic("map_single: bounce buffer is not DMA'ble");
return dev_addr;
@@ -691,19 +649,25 @@ EXPORT_SYMBOL_GPL(swiotlb_map_page);
static void unmap_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, int dir)
{
- char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
+ phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dma_addr)) {
- do_unmap_single(hwdev, dma_addr, size, dir);
+ if (is_swiotlb_buffer(paddr)) {
+ do_unmap_single(hwdev, phys_to_virt(paddr), size, dir);
return;
}
if (dir != DMA_FROM_DEVICE)
return;
- dma_mark_clean(dma_addr, size);
+ /*
+ * phys_to_virt doesn't work with hihgmem page but we could
+ * call dma_mark_clean() with hihgmem page here. However, we
+ * are fine since dma_mark_clean() is null on POWERPC. We can
+ * make dma_mark_clean() take a physical address if necessary.
+ */
+ dma_mark_clean(phys_to_virt(paddr), size);
}
void swiotlb_unmap_page(struct device *hwdev, dma_addr_t dev_addr,
@@ -728,19 +692,19 @@ static void
swiotlb_sync_single(struct device *hwdev, dma_addr_t dev_addr,
size_t size, int dir, int target)
{
- char *dma_addr = swiotlb_bus_to_virt(hwdev, dev_addr);
+ phys_addr_t paddr = dma_to_phys(hwdev, dev_addr);
BUG_ON(dir == DMA_NONE);
- if (is_swiotlb_buffer(dma_addr)) {
- sync_single(hwdev, dma_addr, size, dir, target);
+ if (is_swiotlb_buffer(paddr)) {
+ sync_single(hwdev, phys_to_virt(paddr), size, dir, target);
return;
}
if (dir != DMA_FROM_DEVICE)
return;
- dma_mark_clean(dma_addr, size);
+ dma_mark_clean(phys_to_virt(paddr), size);
}
void
@@ -817,10 +781,10 @@ swiotlb_map_sg_attrs(struct device *hwdev, struct scatterlist *sgl, int nelems,
for_each_sg(sgl, sg, nelems, i) {
phys_addr_t paddr = sg_phys(sg);
- dma_addr_t dev_addr = swiotlb_phys_to_bus(hwdev, paddr);
+ dma_addr_t dev_addr = phys_to_dma(hwdev, paddr);
- if (range_needs_mapping(paddr, sg->length) ||
- address_needs_mapping(hwdev, dev_addr, sg->length)) {
+ if (swiotlb_force ||
+ !dma_capable(hwdev, dev_addr, sg->length)) {
void *map = map_single(hwdev, sg_phys(sg),
sg->length, dir);
if (!map) {
^ permalink raw reply related
* Re: [PATCH -v2 0/7] powerpc: use asm-generic/dma-mapping-common.h
From: Benjamin Herrenschmidt @ 2009-08-27 7:36 UTC (permalink / raw)
To: Ingo Molnar; +Cc: FUJITA Tomonori, linuxppc-dev, linux-kernel, galak
In-Reply-To: <20090827072208.GA2131@elte.hu>
On Thu, 2009-08-27 at 09:22 +0200, Ingo Molnar wrote:
>
> ah, yes, they are stable/fine. I've put it into a separate branch
> for you.
>
> Ben, please pull the latest iommu-for-powerpc git tree from:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git
> iommu-for-powerpc
>
> And i could pull back the new bits from you once you have the new
> patches added and are happy with them. [I suspect you dont want the
> diffstat below in the powerpc tree]
>
> That was the plan, right?
Sure, no problem. I'll stick that in powerpc-next tomorrow hopefully.
Cheers,
Ben.
^ permalink raw reply
* LITE5200 configuration
From: FIXED-TERM Seeh Thomas (BEG/EMS1) @ 2009-08-27 8:01 UTC (permalink / raw)
To: linuxppc-dev@lists.ozlabs.org
[-- Attachment #1: Type: text/plain, Size: 19675 bytes --]
Hello everyone,
I'll try to run a 2.6.31-rc7 kernel on my Lite5200 board.
For the device tree I use lite5200.dts and compiled it simply with
make ARCH=powerpc CROSS_COMPILE=ppc_6xx- lite5200.dtb
But I'm not sure what configuration for the kernel I should choose. There is no
lite5200_defconfig only one for the lite5200b.
I tried it with mpc5200_defconfig and lite5200b_defconfig, but I'm not sure which
is the right way.
For compiling the kernel I use:
make ARCH=powerpc CROSS_COMPILE=ppc_6xx- "CONFIG_FILE"
make ARCH=powerpc CROSS_COMPILE=ppc_6xx- uImage
make ARCH=powerpc CROSS_COMPILE=ppc_6xx- modules
make ARCH=powerpc CROSS_COMPILE=ppc_6xx- modules_install
Can anyone tell me?
I use U-Boot 2009.06, with the following settings for bootup:
=> print kernel_addr fdt_addr dtbfile bootfile bootargs
kernel_addr=900000
fdt_addr=b00000
dtbfile=/tftpboot/lite5200.dtb
bootfile=/tftpboot/uImage
bootargs=console=ttyPSC0,115200 root=/dev/nfs rw nfsroot=10.10.0.2:/opt/eldk/ppc
_82xx ip=10.10.0.99:10.10.0.2::255.255.255.0:icecube::off panic=1
=> tftp ${kernel_addr} ${boofile}; tftp ${fdt_addr} ${dtbfile}
=> bootm ${kernel_addr} - ${fdt_addr}
With lite5200b_defconfig config the last message I see is:
=> tftp ${kernel_addr} ${boofile}; tftp ${fdt_addr} ${dtbfile}
Using FEC ETHERNET device
TFTP from server 10.10.0.2; our IP address is 10.10.0.99
Filename '/tftpboot/uImage'.
Load address: 0x900000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
###################################
done
Bytes transferred = 1507908 (170244 hex)
Using FEC ETHERNET device
TFTP from server 10.10.0.2; our IP address is 10.10.0.99
Filename '/tftpboot/lite5200.dtb'.
Load address: 0xb00000
Loading: ##
done
Bytes transferred = 5375 (14ff hex)
=> bootm ${kernel_addr} - ${fdt_addr}
## Booting kernel from Legacy Image at 00900000 ...
Image Name: Linux-2.6.31-rc7-01406-g83e0360-
Created: 2009-08-27 7:58:32 UTC
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 1507844 Bytes = 1.4 MB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
## Flattened Device Tree blob at 00b00000
Booting using the fdt blob at 0xb00000
Uncompressing Kernel Image ... OK
Loading Device Tree to 007fb000, end 007ff4fe ... OK
[ 0.000000] Using lite5200 machine description
[ 0.000000] Linux version 2.6.31-rc7-01406-g83e0360-dirty (root@user-laptop)
(gcc version 4.2.2) #6 Thu Aug 27 09:58:17 CEST 2009
[ 0.000000] PCI host bridge /pci@f0000d00 (primary) ranges:
[ 0.000000] MEM 0x0000000080000000..0x000000009fffffff -> 0x0000000080000000
Prefetch
[ 0.000000] MEM 0x00000000a0000000..0x00000000afffffff -> 0x00000000a0000000
[ 0.000000] IO 0x00000000b0000000..0x00000000b0ffffff -> 0x0000000000000000
[ 0.000000] Zone PFN ranges:
[ 0.000000] DMA 0x00000000 -> 0x00004000
[ 0.000000] Normal 0x00004000 -> 0x00004000
[ 0.000000] Movable zone start PFN for each node
[ 0.000000] early_node_map[1] active PFN ranges
[ 0.000000] 0: 0x00000000 -> 0x00004000
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pag
es: 16256
[ 0.000000] Kernel command line: console=ttyPSC0,115200 root=/dev/nfs rw nfsr
oot=10.10.0.2:/opt/eldk/ppc_82xx ip=10.10.0.99:10.10.0.2::255.255.255.0:icecube:
:off panic=1
[ 0.000000] PID hash table entries: 256 (order: 8, 1024 bytes)
[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.000000] Memory: 61612k/65536k available (2972k kernel code, 3864k reserve
d, 144k data, 108k bss, 160k init)
[ 0.000000] Kernel virtual memory layout:
[ 0.000000] * 0xffffe000..0xfffff000 : fixmap
[ 0.000000] * 0xfcffa000..0xfe000000 : early ioremap
[ 0.000000] * 0xc5000000..0xfcffa000 : vmalloc & ioremap
[ 0.000000] SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, N
odes=1
[ 0.000000] NR_IRQS:512
[ 0.000000] MPC52xx PIC is up and running!
[ 0.000000] clocksource: timebase mult[f26c9b2] shift[22] registered
[ 0.000738] console [ttyPSC0] enabled
[ 0.169172] Mount-cache hash table entries: 512
[ 0.184911] NET: Registered protocol family 16
[ 0.240784] PCI: Probing PCI hardware
[ 0.248600] DMA: MPC52xx BestComm driver
[ 0.253306] DMA: MPC52xx BestComm engine @f0001200 ok !
[ 0.309563] bio: create slab <bio-0> at 0
[ 0.320464] SCSI subsystem initialized
[ 0.345661] NET: Registered protocol family 2
[ 0.350793] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.359384] TCP established hash table entries: 2048 (order: 2, 16384 bytes)
[ 0.367176] TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.374059] TCP: Hash tables configured (established 2048 bind 2048)
[ 0.380734] TCP reno registered
[ 0.384910] NET: Registered protocol family 1
[ 0.498050] msgmni has been set to 120
[ 0.506553] alg: No test for stdrng (krng)
[ 0.511415] io scheduler noop registered
[ 0.515636] io scheduler anticipatory registered (default)
[ 0.521491] io scheduler deadline registered
[ 0.526513] io scheduler cfq registered
[ 1.706240] Generic RTC Driver v1.07
[ 1.712363] Serial: MPC52xx PSC UART driver
[ 1.717645] f0002000.serial: ttyPSC0 at MMIO 0xf0002000 (irq = 129) is a MPC5
2xx PSC
[ 1.779407] brd: module loaded
[ 1.808029] loop: module loaded
[ 1.814012] ata: MPC52xx IDE/ATA libata driver
[ 1.821144] scsi0 : mpc52xx_ata
[ 1.826559] ata1: PATA max PIO4 ata_regs 0xf0003a00 irq 135
[ 1.838948] mpc52xx MII bus: probed
[ 1.864150] i2c /dev entries driver
[ 1.883715] TCP cubic registered
[ 1.887261] NET: Registered protocol family 17
[ 1.895154] RPC: Registered udp transport module.
[ 1.900177] RPC: Registered tcp transport module.
[ 3.450019] IP-Config: Complete:
[ 3.453333] device=eth0, addr=10.10.0.99, mask=255.255.255.0, gw=255.255
.255.255,
[ 3.461661] host=icecube, domain=, nis-domain=(none),
[ 3.467407] bootserver=10.10.0.2, rootserver=10.10.0.2, rootpath=
[ 3.489436] Looking up port of RPC 100003/2 on 10.10.0.2
[ 3.530495] Looking up port of RPC 100005/1 on 10.10.0.2
[ 3.667558] VFS: Mounted root (nfs filesystem) on device 0:11.
[ 3.674123] Freeing unused kernel memory: 160k init
[ 4.085086] net eth0: FEC_IEVENT_RFIFO_ERROR
[ 4.091135] ------------[ cut here ]------------
[ 4.095874] Kernel BUG at c01b7d4c [verbose debug info unavailable]
[ 4.102285] Oops: Exception in kernel mode, sig: 5 [#1]
[ 4.107615] lite5200
[ 4.109842] Modules linked in:
[ 4.112965] NIP: c01b7d4c LR: c01b900c CTR: c0011220
[ 4.118035] REGS: c030da20 TRAP: 0700 Not tainted (2.6.31-rc7-01406-g83e03
60-dirty)
[ 4.126106] MSR: 00029032 <EE,ME,CE,IR,DR> CR: 22000024 XER: 00000000
[ 4.132907] TASK = c02e93e8[0] 'swapper' THREAD: c030c000
[ 4.138235] GPR00: 00010200 c030dad0 c02e93e8 c391fe00 00000001 00000000 0000
8000 00000000
[ 4.146798] GPR08: 00000006 c030c000 c0335000 000734e0 22000022 ffcf5fff 03fb
8000 03fa8878
[ 4.155357] GPR16: 03f81ae8 03fa8854 03f45dcc 03f45ccc 03f45bee c0328428 c386
fe00 0a0a0063
[ 4.163920] GPR24: 0000106c 00008000 00000000 00000001 00000000 c391fe00 c387
7c00 c3877ec0
[ 4.172666] Call Trace:
[ 4.175165] [c030dad0] [c01b8ec0] 0xc01b8ec0 (unreliable)
[ 4.180677] [c030db00] [c01b900c] 0xc01b900c
[ 4.185034] [c030db20] [c01b9310] 0xc01b9310
[ 4.189394] [c030db40] [c004fd08] 0xc004fd08
[ 4.193753] [c030db60] [c0051f14] 0xc0051f14
[ 4.198113] [c030db70] [c0006590] 0xc0006590
[ 4.202473] [c030db90] [c0012084] 0xc0012084
[ 4.206833] --- Exception: 501 at 0xc023d1a4
[ 4.206846] LR = 0xc023dcac
[ 4.214387] [c030dc50] [c02395e4] 0xc02395e4 (unreliable)
[ 4.219904] [c030dc80] [c023dcac] 0xc023dcac
[ 4.224262] [c030dc90] [c0237e2c] 0xc0237e2c
[ 4.228622] [c030dcb0] [c023c120] 0xc023c120
[ 4.232982] [c030dce0] [c01c5514] 0xc01c5514
[ 4.237341] [c030dd00] [c020ea08] 0xc020ea08
[ 4.241701] [c030dd20] [c0210008] 0xc0210008
[ 4.246059] [c030dd70] [c01eda24] 0xc01eda24
[ 4.250418] [c030dd90] [c01ede54] 0xc01ede54
[ 4.254775] --- Exception: c at 0xc030de50
[ 4.254789] LR = 0x00000a
[ 4.261973] [c030ddc0] [c01d18ec] 0xc01d18ec (unreliable)
[ 4.267490] [c030ddf0] [c01d4454] 0xc01d4454
[ 4.271850] [c030de20] [c01d47fc] 0xc01d47fc
[ 4.276209] [c030de50] [c0029c48] 0xc0029c48
[ 4.280570] [c030de90] [c00064f4] 0xc00064f4
[ 4.284929] [c030dea0] [c0029a98] 0xc0029a98
[ 4.289288] [c030deb0] [c0006594] 0xc0006594
[ 4.293645] [c030ded0] [c0012084] 0xc0012084
[ 4.298004] --- Exception: 501 at 0xc0009398
[ 4.298020] LR = 0xc0009398
[ 4.305561] [c030df90] [c0009348] 0xc0009348 (unreliable)
[ 4.311077] [c030dfb0] [c0003e40] 0xc0003e40
[ 4.315436] [c030dfc0] [c02bf850] 0xc02bf850
[ 4.319795] [c030dff0] [00003438] 0x003438
[ 4.323972] Instruction dump:
[ 4.326999] 4e800020 9421ffd0 7c0802a6 bf210014 54290024 7c7d1b78 90010034 7c
9b2378
[ 4.334947] 7cba2b78 7cd93378 8009000c 5400016e <0f000000> 3b830028 7f83e378
4809e8dd
[ 4.343083] Kernel panic - not syncing: Fatal exception in interrupt
[ 4.349564] Rebooting in 1 seconds.
And with mpc5200_defconfig config it is:
Using FEC ETHERNET device
TFTP from server 10.10.0.2; our IP address is 10.10.0.99
Filename '/tftpboot/uImage'.
Load address: 0x900000
Loading: #################################################################
#################################################################
#################################################################
#################################################################
#################################################################
#######################################################
done
Bytes transferred = 1945203 (1dae73 hex)
Using FEC ETHERNET device
TFTP from server 10.10.0.2; our IP address is 10.10.0.99
Filename '/tftpboot/lite5200.dtb'.
Load address: 0xb00000
Loading: ##
done
Bytes transferred = 5375 (14ff hex)
=> bootm ${kernel_addr} - ${fdt_addr}
## Booting kernel from Legacy Image at 00900000 ...
Image Name: Linux-2.6.31-rc7-01406-g83e0360
Created: 2009-08-27 6:51:07 UTC
Image Type: PowerPC Linux Kernel Image (gzip compressed)
Data Size: 1945139 Bytes = 1.9 MB
Load Address: 00000000
Entry Point: 00000000
Verifying Checksum ... OK
## Flattened Device Tree blob at 00b00000
Booting using the fdt blob at 0xb00000
Uncompressing Kernel Image ... OK
Loading Device Tree to 007fb000, end 007ff4fe ... OK
[ 0.000000] Using lite5200 machine description
[ 0.000000] Linux version 2.6.31-rc7-01406-g83e0360 (root@user-laptop) (gcc v
ersion 4.2.2) #3 Thu Aug 27 08:50:54 CEST 2009
[ 0.000000] PCI host bridge /pci@f0000d00 (primary) ranges:
[ 0.000000] MEM 0x0000000080000000..0x000000009fffffff -> 0x0000000080000000
Prefetch
[ 0.000000] MEM 0x00000000a0000000..0x00000000afffffff -> 0x00000000a0000000
[ 0.000000] IO 0x00000000b0000000..0x00000000b0ffffff -> 0x0000000000000000
[ 0.000000] Zone PFN ranges:
[ 0.000000] DMA 0x00000000 -> 0x00004000
[ 0.000000] Normal 0x00004000 -> 0x00004000
[ 0.000000] Movable zone start PFN for each node
[ 0.000000] early_node_map[1] active PFN ranges
[ 0.000000] 0: 0x00000000 -> 0x00004000
[ 0.000000] Built 1 zonelists in Zone order, mobility grouping on. Total pag
es: 16256
[ 0.000000] Kernel command line: console=ttyPSC0,115200 root=/dev/nfs rw nfsr
oot=10.10.0.2:/opt/eldk/ppc_82xx ip=10.10.0.99:10.10.0.2::255.255.255.0:icecube:
:off panic=1
[ 0.000000] PID hash table entries: 256 (order: 8, 1024 bytes)
[ 0.000000] Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
[ 0.000000] Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
[ 0.000000] Memory: 60588k/65536k available (3888k kernel code, 4884k reserve
d, 188k data, 164k bss, 188k init)
[ 0.000000] Kernel virtual memory layout:
[ 0.000000] * 0xffffe000..0xfffff000 : fixmap
[ 0.000000] * 0xfcffa000..0xfe000000 : early ioremap
[ 0.000000] * 0xc5000000..0xfcffa000 : vmalloc & ioremap
[ 0.000000] SLUB: Genslabs=13, HWalign=32, Order=0-3, MinObjects=0, CPUs=1, N
odes=1
[ 0.000000] NR_IRQS:512
[ 0.000000] MPC52xx PIC is up and running!
[ 0.000000] clocksource: timebase mult[f26c9b2] shift[22] registered
[ 0.000467] Console: colour dummy device 80x25
[ 0.001126] console [ttyPSC0] enabled
[ 0.173540] Mount-cache hash table entries: 512
[ 0.188342] NET: Registered protocol family 16
[ 0.251292] PCI: Probing PCI hardware
[ 0.259136] DMA: MPC52xx BestComm driver
[ 0.263847] DMA: MPC52xx BestComm engine @f0001200 ok !
[ 0.356705] bio: create slab <bio-0> at 0
[ 0.368969] SCSI subsystem initialized
[ 0.380298] usbcore: registered new interface driver usbfs
[ 0.387488] usbcore: registered new interface driver hub
[ 0.394699] usbcore: registered new device driver usb
[ 0.420014] NET: Registered protocol family 2
[ 0.425101] IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
[ 0.433699] TCP established hash table entries: 2048 (order: 2, 16384 bytes)
[ 0.441486] TCP bind hash table entries: 2048 (order: 1, 8192 bytes)
[ 0.448407] TCP: Hash tables configured (established 2048 bind 2048)
[ 0.455022] TCP reno registered
[ 0.459100] NET: Registered protocol family 1
[ 0.574734] JFFS2 version 2.2. (NAND) © 2001-2006 Red Hat, Inc.
[ 0.589702] msgmni has been set to 118
[ 0.598135] alg: No test for stdrng (krng)
[ 0.602904] io scheduler noop registered
[ 0.607201] io scheduler anticipatory registered (default)
[ 0.612979] io scheduler deadline registered
[ 0.618008] io scheduler cfq registered
[ 2.034926] [drm] Initialized drm 1.1.0 20060810
[ 2.039933] Serial: MPC52xx PSC UART driver
[ 2.045071] f0002000.serial: ttyPSC0 at MMIO 0xf0002000 (irq = 129) is a MPC5
2xx PSC
[ 2.107178] brd: module loaded
[ 2.135950] loop: module loaded
[ 2.149599] ata: MPC52xx IDE/ATA libata driver
[ 2.156669] scsi0 : mpc52xx_ata
[ 2.162242] ata1: PATA max PIO4 ata_regs 0xf0003a00 irq 135
[ 2.175746] mpc52xx MII bus: probed
[ 2.203297] usbmon: debugfs is not available
[ 2.207880] ohci_hcd: USB 1.1 'Open' Host Controller (OHCI) Driver
[ 2.216515] ppc-of-ohci f0001000.usb: OF OHCI
[ 2.221581] ppc-of-ohci f0001000.usb: new USB bus registered, assigned bus nu
mber 1
[ 2.229777] ppc-of-ohci f0001000.usb: irq 134, io mem 0xf0001000
[ 2.295284] usb usb1: configuration #1 chosen from 1 choice
[ 2.303126] hub 1-0:1.0: USB hub found
[ 2.307386] hub 1-0:1.0: 2 ports detected
[ 2.315260] Initializing USB Mass Storage driver...
[ 2.321842] usbcore: registered new interface driver usb-storage
[ 2.328414] USB Mass Storage support registered.
[ 2.349763] mice: PS/2 mouse device common for all mice
[ 2.356703] i2c /dev entries driver
[ 2.384164] usbcore: registered new interface driver usbhid
[ 2.390132] usbhid: v2.6:USB HID core driver
[ 2.397686] TCP cubic registered
[ 2.401412] NET: Registered protocol family 17
[ 2.409581] RPC: Registered udp transport module.
[ 2.414646] RPC: Registered tcp transport module.
[ 2.427827] drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
[ 3.969764] IP-Config: Complete:
[ 3.973082] device=eth0, addr=10.10.0.99, mask=255.255.255.0, gw=255.255
.255.255,
[ 3.981401] host=icecube, domain=, nis-domain=(none),
[ 3.987140] bootserver=10.10.0.2, rootserver=10.10.0.2, rootpath=
[ 4.009033] Looking up port of RPC 100003/2 on 10.10.0.2
[ 4.055286] Looking up port of RPC 100005/1 on 10.10.0.2
[ 4.226838] VFS: Mounted root (nfs filesystem) on device 0:12.
[ 4.233384] Freeing unused kernel memory: 188k init
[ 4.351275] net eth0: FEC_IEVENT_RFIFO_ERROR
[ 4.357356] ------------[ cut here ]------------
[ 4.362100] Kernel BUG at c0229440 [verbose debug info unavailable]
[ 4.368517] Oops: Exception in kernel mode, sig: 5 [#1]
[ 4.373853] lite5200
[ 4.376085] Modules linked in:
[ 4.379219] NIP: c0229440 LR: c022a700 CTR: c0013720
[ 4.384300] REGS: c03fd980 TRAP: 0700 Not tainted (2.6.31-rc7-01406-g83e03
60)
[ 4.391848] MSR: 00029032 <EE,ME,CE,IR,DR> CR: 22000024 XER: 00000000
[ 4.398659] TASK = c03ce3e8[0] 'swapper' THREAD: c03fc000
[ 4.403993] GPR00: 00010100 c03fda30 c03ce3e8 c397ec00 00000001 00000000 0000
8000 00000000
[ 4.412574] GPR08: 00000021 c03fc000 c0434000 00073d80 82000022 ffcf5fff 03fb
8000 03fa8878
[ 4.421148] GPR16: 03f81ae8 03fa8854 03f45dcc 03f45ccc c03f9e54 c39b2d80 0000
0000 c03c2b24
[ 4.429718] GPR24: 00000064 00008000 00000000 00000001 00000000 c397ec00 c39a
2000 c39a22c0
[ 4.438468] Call Trace:
[ 4.440977] [c03fda30] [c022a5b4] 0xc022a5b4 (unreliable)
[ 4.446497] [c03fda60] [c022a700] 0xc022a700
[ 4.450863] [c03fda80] [c022aa04] 0xc022aa04
[ 4.455227] [c03fdaa0] [c00528b4] 0xc00528b4
[ 4.459593] [c03fdac0] [c0054ac0] 0xc0054ac0
[ 4.463960] [c03fdad0] [c0006590] 0xc0006590
[ 4.468326] [c03fdaf0] [c0014584] 0xc0014584
[ 4.472690] --- Exception: 501 at 0xc0018b84
[ 4.472708] LR = 0xc027e5ac
[ 4.480252] [c03fdbb0] [c39a2000] 0xc39a2000 (unreliable)
[ 4.485772] [c03fdbf0] [c027e748] 0xc027e748
[ 4.490139] [c03fdc30] [c02ef9e8] 0xc02ef9e8
[ 4.494505] [c03fdc50] [c02ef620] 0xc02ef620
[ 4.498871] [c03fdc90] [c02ef820] 0xc02ef820
[ 4.503237] [c03fdcb0] [c02f20a8] 0xc02f20a8
[ 4.507601] [c03fdce0] [c027b550] 0xc027b550
[ 4.511968] [c03fdd00] [c02c4a44] 0xc02c4a44
[ 4.516334] [c03fdd20] [c02c6044] 0xc02c6044
[ 4.520700] [c03fdd70] [c02a3a60] 0xc02a3a60
[ 4.525066] [c03fdd90] [c02a3e90] 0xc02a3e90
[ 4.529433] [c03fddc0] [c0287928] 0xc0287928
[ 4.533798] [c03fddf0] [c028a490] 0xc028a490
[ 4.538164] [c03fde20] [c028a838] 0xc028a838
[ 4.542527] [c03fde50] [c002c91c] 0xc002c91c
[ 4.546894] [c03fde90] [c00064f4] 0xc00064f4
[ 4.551257] [c03fdea0] [c002c76c] 0xc002c76c
[ 4.555623] [c03fdeb0] [c0006594] 0xc0006594
[ 4.559989] [c03fded0] [c0014584] 0xc0014584
[ 4.564356] --- Exception: 501 at 0xc0009398
[ 4.564375] LR = 0xc0009398
[ 4.571919] [c03fdf90] [c0009348] 0xc0009348 (unreliable)
[ 4.577439] [c03fdfb0] [c0003e40] 0xc0003e40
[ 4.581802] [c03fdfc0] [c039d850] 0xc039d850
[ 4.586168] [c03fdff0] [00003438] 0x003438
[ 4.590352] Instruction dump:
[ 4.593390] 4e800020 9421ffd0 7c0802a6 bf210014 54290024 7c7d1b78 90010034 7c
9b2378
[ 4.601358] 7cba2b78 7cd93378 8009000c 5400016e <0f000000> 3b830028 7f83e378
480e3221
[ 4.609519] Kernel panic - not syncing: Fatal exception in interrupt
[ 4.616013] Rebooting in 1 seconds..
Best regards
Thomas
[-- Attachment #2: Type: text/html, Size: 30286 bytes --]
^ permalink raw reply
* powerpc/ps3: Add missing check for PS3 to rtc-ps3 platform device registration (fwd)
From: Geert Uytterhoeven @ 2009-08-27 8:45 UTC (permalink / raw)
To: stable; +Cc: Linux/PPC Development, Linux Kernel Development
For stable/linux-2.6.30.y
---------- Forwarded message ----------
Date: Thu, 27 Aug 2009 03:59:28 GMT
From: Linux Kernel Mailing List <linux-kernel@vger.kernel.org>
To: git-commits-head@vger.kernel.org
Subject: powerpc/ps3: Add missing check for PS3 to rtc-ps3 platform device
registration
Gitweb: http://git.kernel.org/linus/7b6a09f3d6aedeaac923824af2a5df30300b56e9
Commit: 7b6a09f3d6aedeaac923824af2a5df30300b56e9
Parent: f415c413f458837bd0c27086b79aca889f9435e4
Author: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
AuthorDate: Sun Aug 23 22:54:32 2009 +0000
Committer: Benjamin Herrenschmidt <benh@kernel.crashing.org>
CommitDate: Thu Aug 27 13:25:46 2009 +1000
powerpc/ps3: Add missing check for PS3 to rtc-ps3 platform device registration
On non-PS3, we get:
| kernel BUG at drivers/rtc/rtc-ps3.c:36!
because the rtc-ps3 platform device is registered unconditionally in a kernel
with builtin support for PS3.
Reported-by: Sachin Sant <sachinp@in.ibm.com>
Signed-off-by: Geert Uytterhoeven <Geert.Uytterhoeven@sonycom.com>
Acked-by: Geoff Levand <geoffrey.levand@am.sony.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/platforms/ps3/time.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
index b178a1e..40b5cb4 100644
--- a/arch/powerpc/platforms/ps3/time.c
+++ b/arch/powerpc/platforms/ps3/time.c
@@ -21,6 +21,7 @@
#include <linux/kernel.h>
#include <linux/platform_device.h>
+#include <asm/firmware.h>
#include <asm/rtc.h>
#include <asm/lv1call.h>
#include <asm/ps3.h>
@@ -84,6 +85,9 @@ static int __init ps3_rtc_init(void)
{
struct platform_device *pdev;
+ if (!firmware_has_feature(FW_FEATURE_PS3_LV1))
+ return -ENODEV;
+
pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
if (IS_ERR(pdev))
return PTR_ERR(pdev);
^ permalink raw reply related
* Re: Extending virtio_console to support multiple ports
From: Alan Cox @ 2009-08-27 9:08 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: kvm, linuxppc-dev, linux-kernel, miltonm, qemu-devel, borntraeger,
brueckner, Amit Shah, virtualization
In-Reply-To: <1251346023.20467.21.camel@pasglop>
> - Then, are we certain that there's no case where the tty layer will
> call us with some lock held or in an atomic context ? To be honest,
> I've totally lost track of the locking rules in tty land lately so it
> might well be ok, but something to verify.
Some of the less well behaved line disciplines do this and always have
done.
Alan
^ permalink raw reply
* Re: Extending virtio_console to support multiple ports
From: Benjamin Herrenschmidt @ 2009-08-27 9:27 UTC (permalink / raw)
To: Alan Cox
Cc: kvm, linuxppc-dev, linux-kernel, miltonm, qemu-devel, borntraeger,
brueckner, Amit Shah, virtualization
In-Reply-To: <20090827100809.5f0aa0a7@linux.intel.com>
On Thu, 2009-08-27 at 10:08 +0100, Alan Cox wrote:
> > - Then, are we certain that there's no case where the tty layer will
> > call us with some lock held or in an atomic context ? To be honest,
> > I've totally lost track of the locking rules in tty land lately so it
> > might well be ok, but something to verify.
>
> Some of the less well behaved line disciplines do this and always have
> done.
That was also my understanding but heh, I though that maybe you may have
fixed all of that already :-)
So at this stage, I think the reasonably thing to do is to stick to the
spinlock, but we can try to make it a bit smarter, and we can definitely
attempt to fix the case Amit pointed out where we call resize without a
lock while it seems to expect it (though we also need to be careful
about re-entrancy I believe).
Cheers,
Ben.
^ permalink raw reply
* Re: Question : about difference with bdnz and bdnz+
From: Benjamin Herrenschmidt @ 2009-08-27 9:30 UTC (permalink / raw)
To: HongWoo Lee; +Cc: linuxppc-dev
In-Reply-To: <4A9613E3.8020700@gmail.com>
On Thu, 2009-08-27 at 14:04 +0900, HongWoo Lee wrote:
> And I have a question about bdnz+ instruction.
> Through googling, I learned that bdnz does decrement count register
> and
> branch if it is still nonzero.
> But I couldn't find what "bdnz+" is.
> Can anybody explain to me what it is ??
On PowerPC, branch instructions can have a "hint" (+ or - added to the
mnemonic) which indicates to the processor whether the branch is likely
to be taken or not, and overrides the dynamic branch prediction.
In most case, it's not necessary though I suppose in the case at hand,
we are pretty confident that we're going to loop a lot more times than
exit from the loop so it won't hurt to put the hint in there.
Note that there have been subtle changes in the way those hints work
between earlier and modern PowerPC processors and the way they are
encoded will be different depending on what CPU you are building for,
but that's an entirely different headache :-)
Cheers,
Ben.
^ 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