* Re: [PATCH 1/3] ps3: vuart: fix error path locking
From: Geoff Levand @ 2007-12-13 2:00 UTC (permalink / raw)
To: akpm
Cc: Daniel Walker, matthias.kaehlcke, linux-kernel, linux,
linuxppc-dev, mingo, kjwinchester
In-Reply-To: <20071213003028.676998182@mvista.com>
> This stray down would cause a permanent sleep which doesn't seem correct.
> The other uses of this semaphore appear fairly mutex like it's even initialized
> with init_MUTEX() .. So here a patch for removing this one down().
>
> Signed-off-by: Daniel Walker <dwalker@mvista.com>
>
> ---
> drivers/ps3/ps3-vuart.c | 1 -
> 1 file changed, 1 deletion(-)
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
Looks, good.
Andrew, Please apply.
-Geoff
^ permalink raw reply
* RE: initrd - console
From: Siva Prasad @ 2007-12-13 2:06 UTC (permalink / raw)
To: michael; +Cc: linuxppc-dev, linuxppc-embedded
In-Reply-To: <1197336860.7378.29.camel@concordia>
Thanks for the response Michael.
Yes!... I do have /dev/console
I also have the following line in /etc/inittab (::respawn:/sbin/getty -L
ttyS0 115200 VT100)
Still it does not print any thing from the user land. All the kernel
printk's are working fine.
I tried to print the arguments and environment variables for getty and
echo /dev/console. Below is the info.
sys_execve - filename=3D/sbin/getty.
copy_strings: kaddr =3D /sbin/getty.
copy_strings: kaddr =3D USER=3Droot.
copy_strings: kaddr =3D SHELL=3D/bin/sh.
copy_strings: kaddr =3D PATH=3D/usr/bin:/bin:/usr/sbin:/sbin.
copy_strings: kaddr =3D TERM=3Dvt102.
copy_strings: kaddr =3D HOME=3D/.
copy_strings: kaddr =3D VT100.
copy_strings: kaddr =3D 115200.
copy_strings: kaddr =3D ttyS0.
copy_strings: kaddr =3D -L.
copy_strings: kaddr =3D /sbin/getty.
sys_execve - filename=3D/bin/echo.
copy_strings: kaddr =3D /bin/echo.
copy_strings: kaddr =3D GATEWAY0=3D172.27.255.254.
copy_strings: kaddr =3D NETMASK0=3D255.255.0.0.
copy_strings: kaddr =3D PWD=3D/.
copy_strings: kaddr =3D SMBD_ARGS=3D.
copy_strings: kaddr =3D NAMESERVER0=3D172.27.0.1.
copy_strings: kaddr =3D NTP_SERVER=3D.
copy_strings: kaddr =3D SHELL=3D/bin/sh.
copy_strings: kaddr =3D INETD_ARGS=3D.
copy_strings: kaddr =3D BOA_ARGS=3D.
copy_strings: kaddr =3D NMBD_ARGS=3D.
copy_strings: kaddr =3D TMPFS=3Dtmpfs.
copy_strings: kaddr =3D PATH=3D/usr/bin:/bin:/usr/sbin:/sbin.
copy_strings: kaddr =3D READONLY_FS=3D.
copy_strings: kaddr =3D TERM=3Dvt102.
copy_strings: kaddr =3D MODLIST=3D.
copy_strings: kaddr =3D SYSCFG_IFACE0=3Dy.
copy_strings: kaddr =3D IPADDR0=3D172.27.180.41.
copy_strings: kaddr =3D DEPLOYMENT_STYLE=3DRAMDISK.
copy_strings: kaddr =3D SYSCFG_DHCPC_CMD=3Dudhcpc -b -i .
copy_strings: kaddr =3D DHCP_ARG=3D.
copy_strings: kaddr =3D RAMDIRS=3D.
copy_strings: kaddr =3D BROADCAST0=3D172.27.255.255.
copy_strings: kaddr =3D HOME=3D/.
copy_strings: kaddr =3D HOSTNAME=3Dmpc8641hpcn.
copy_strings: kaddr =3D USER=3Droot.
copy_strings: kaddr =3D INTERFACE0=3Deth0.
copy_strings: kaddr =3D /dev/console.
copy_strings: kaddr =3D echo.
Thanks
Siva
-----Original Message-----
From: Michael Ellerman [mailto:michael@ellerman.id.au]=20
Sent: Monday, December 10, 2007 5:34 PM
To: Siva Prasad
Cc: linuxppc-dev@ozlabs.org; linuxppc-embedded@ozlabs.org
Subject: Re: initrd - console
On Mon, 2007-12-10 at 17:26 -0800, Siva Prasad wrote:
> Hi,
>=20
> I am trying to boot kernel with initrd. However, it hangs in
> run_init_process("/sbin/init"). I went into the system calls to see
what
> it is doing.=20
>=20
> As part of debugging, I ended up adding a printk statement in
> arch/powerpc/kernel/process.c:sys_execve() routine. Noticed that all
the
> calls are coming here, however nothing is printed on the screen. I
think
> initrd is executing fine (unless one of you says otherwise). See the
> capture below for boot log.
>=20
> Question 1: how come nothing is printed from ramdisk (userland
programs)
> to the serial console, while all the kernel printk's are working
> perfectly?
Do you have a /dev/console etc. in your initrd?
> Question 2: How important is to have interrupts working for just
> printing. I know that interrupts are must to enter input.
Depends on what your console is, but if it's something simple then you
should be able to write to it without taking interrupts.
cheers
--=20
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
^ permalink raw reply
* RE: Xilinx devicetrees
From: Koss, Mike (Mission Systems) @ 2007-12-13 2:40 UTC (permalink / raw)
To: Stephen Neuendorffer, David H. Lynch Jr., Grant Likely,
linuxppc-embedded
In-Reply-To: <20071125235855.95B9999804D@mail138-cpk.bigfish.com>
[-- Attachment #1: Type: text/plain, Size: 7713 bytes --]
Time for my $.02, since I am heavily weighting my future designs on the
use of the device trees. :) (and b/c I don't check my work e-mail from
home ;P)
________________________________
From: Stephen Neuendorffer [mailto:stephen.neuendorffer@xilinx.com]
Sent: Sunday, November 25, 2007 6:59 PM
To: David H. Lynch Jr.; Grant Likely; linuxppc-embedded
Subject: RE: Xilinx devicetrees
DL> I am not expert on this, but at Pico we already store our boot
monitor in the .bit files in BRAM.
DL> But that is not free. It is one of the reasons we do not use
u-boot. Our boot monitor must fit into 16K of BRAM.
DL> Must be able to perform selftests on critical hardware, support
a flash file system, load bit files from flash to the FGA, load and
exectute elf files, allow a small set of user commands,
DL> and handle hosted vs. standalone operation.
DL> And aparently extract the devicetree from a bit file and pass it
to a linux kernel.
SN> Once you can load a bitstream from flash, loading the device tree
from flash
SN> should be practically free. In any event, why do you do this rather
than just run out of the flash (or a ram copy of the flash?)
This is the approach that I am currently taking with our future design.
In our system, we actually have 2 physical systems running Linux inside
the V4 (that's why there are 2 PowerPCs :) ). My current plan would be
to have the device trees stored in FLASH along w/ a single linux image.
Our bootloader on the board would then copy that information from FLASH
to RAM for both systems. This allows us to have two physically different
systems setup with different hardware, but have one linux image with two
different device trees. With a standard linux kernel weighing it at ~
3-5MB (including initramfs) that's a hefty savings in FLASH for us. Plus
it can considerably lower boot time instead of having to verify multiple
large images.
DL> In static or fairly static hardware, that's fine. Even in somewhat
dynamic hardware with large quantities of startup resources - like a PC.
DL> But in highly dynamic hardware with fairly limited resources it
starts to become an issue.
SN> As Grant says, the dynamic detection doesn't have to be done in the
boot loader, it could be done in the platform code. You can largely
ignore
SN> the device trees, or always boot with a core device tree and figure
it all out later (perhaps using version registers). I anticipate that
SN> the 'standard flow' will have standard platform code for any board
that uses a complete device tree. If you have the need to do something
SN> extraordinary, then you should feel free to hack away... However,
It doesn't seem to me to be really necessary in your case, assuming that
SN> the device tree is packaged (somehow, TBD) along with the bitstream.
I don't know if packaging the device tree with the bitstream is the best
way to go. It's possible that it could lead to headaches for certain
systems that have security restrictions. The same could be said for
using it w/ the SystemACE to load it into RAM after the image. (which is
what I'm currently doing for my 2 linux images in lieu of a true on-chip
bootloader). I am already taking the security concerns into account for
future revisions of the hardware wrt to using a SystemACE, and am
planning on moving the device trees into NV storage like FLASH.
GL> No, unfortunately they don't deal with the problem you're facing
GL> (which I'm facing also). But it will be solved if we figure out a
GL> sane way to bind the device tree up with the FPGA bitstream without
GL> consuming FPGA resources.
DL> Note to Xilinx:
DL> There MUST be some way of binding a device description to a
bit file.
DL> neither building it into the FPGA fabric nor appending it to the
end
DL> of the bit file are perfect solutions,
DL> The former is more powerfull and flexible but wastes precious
DL> resources. The later is more complex and puts more burdens on
DL> software developers, and may be completely unfeasible in some
DL> environments - not mine fortunately.
SN> I don't understand the 'burden on software developers'. The code to
do this will just be standard code. The worst that one can say is:
SN> 1) I need several KB additional non volatile storage. Given the
size of the FPGA bitstream, this can't be a huge constraint.
SN> 2) I can't use compile time optimization based on xparameters as
easily. Anyone want to implement the alternatives mechanism on ppc and
microblaze?
SN> 3) Some additional boot time. However, again, this seems marginal.
I do agree that using more FPGA resources is not a solution to the
problem. I'm already hitting 80% usage on a FX60 and trying to squeeze
more real estate for storage of the device tree seems silly. Especially
since that would require that every image have this extra hardware built
into it just to support booting a Linux kernel. Why should I have to
have different hardware to boot linux, versus non-kernel, xilkernel, or
other (GHS, LynxOS, etc..)?
DL> Regardless, something must be done. An odd collection of
devicetree
DL> files co-mingled with a collection of bit files, is little better
than
DL> xparameter files all over the place.
SN> Certainly.. But in a sense, these are all intermediate files on the
path to the image on the board. That
SN> (and how it is interpreted by the platform code) should be generated
in a consistent fashion by EDK.
SN> See my other email for some of the possibilities. Are there
specific reasons why you think those
SN> proposals are inadequate? Now is the time when we can take
criticism, with the goal towards making
SN> a good end solution.
One solution I've been thinking through (in lieu of direct support from
EDK) is to use a tcl script with xps to traverse the hardware tree and
generate the device tree. It seems like it should be relatively trivial
to obtain the information. It's just going to be a pain to write all the
handlers for each different linux driver: temac, interrupt controller,
DMA controller, etc.
In reality the best way to handle this would be to have EDK generate the
device tree as part of the library/bsp build process. Now, what I'd like
to see with regards to this is the ability to change the handler for the
generating a specific device information. An example could be the temac.
If at some point in the future the temac needs new/more information to
support its configuration/run-time then having to get a patch from
Xilinx for a EDK is way too slow. The developers should be giving the
opportunity to inject a new handler into the various parts of the device
tree generation. That way when the kernel patch is submitted, an EDK
device generator patch will be submitted at the same time to keep
everything in sync.
DL> And once again a plea to ALWAYS make version/capabilities
registers
DL> atleast an optional part of every design.
DL> Embeddeding a device tree into a design might be fairly
expensive. a
DL> pair of read only 32 bit registers is damn near free - basically the
DL> FPGA equivalent of atmost 64 diodes or resistors.
SN> Actually, device trees actually seem to be cheaper (in the whole
system sense) than such registers. Unless there is something I don't
understand?
The issue here is that the hardware changed and the driver doesn't
support it. I think this would be fixed by having information passed to
the driver in the platform_device struct to specify information, since
its not able to be discerned by the physical hardware information:
version registers, etc.
[-- Attachment #2: Type: text/html, Size: 11617 bytes --]
^ permalink raw reply
* Re: [PATCH RFC 0/7] "NAND on UPM" and related patches
From: Chris Fester @ 2007-12-13 3:01 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <20071210204705.GA31263@localhost.localdomain>
On Mon, 2007-12-10 at 23:47 +0300, Anton Vorontsov wrote:
> Hi all,
>
> Here are patches to support NAND on UPM. That driver is generic for
> all processors with FSL UPMs. And because of that, few more patches are
> needed -- GPIO API and generic FSL UPM functions.
> I would appreciate any comments and suggestions, thanks!
Hi Anton,
Apologies for not getting back sooner to comment...
We've been using a home-brewed UPM driver for our NAND for a while now.
There's several issues we've hit that I figured I would share. The
issues involve deficiencies of both the UPM and the NAND part itself.
We modeled our driver loosely after the suggestions in this white paper:
http://www.freescale.com/files/32bit/doc/white_paper/NANDFLASHWP.pdf?fpsp=1&WT_TYPE=WhitePapers&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=pdf&WT_ASSET=Documentation
We also connected the NAND according to the suggestions in the above
document.
Something that you should be made aware of right away about the UPM -
you do not have control of the logic lines all of the time. You only
can control them during a transaction (in our case, a byte transaction).
In other words, the time that is between reading/writing bytes, or
putting the address on the bus, or asserting commands you are not able
to hold the lines to a certain state. Most of the control lines coming
from the UPM default to a logic 1 when unused (I believe only one
defaults to a logic 0).
The first issue is timings between versions of processors. We've got
one board using an MPC8349 running a 1Gb ST micro part (NAND01G-B).
Another board is an MPC8347 using the same 1Gb ST micro part. After
much time analyzing logic analyzer captures we found that write pulses
with the 8349 had to be shifted to the left a half clock in order to
properly latch the data on the bus. This was unexpected given the two
boards are very similar and the processors are in the same family. I
suppose the fix was easy enough, we just had to make a new version of
the microcode. What's interesting is that Freescale said that there's
nothing different between the two processors' UPMs. Yet there is a
distinct difference between local bus behavior on the 2 cpus, our LA
captures prove it.
The second issue was with interrupts during reads. We noticed that some
of our boards experienced ECC errors while reading the NAND. Logic
analyzer captures and debugging revealed that when an interrupt happened
while the driver's read code was executing, the UPM went into an idle
state, and the chip select of the part went high. This may not be a
problem for other NAND parts, but for our ST Micro parts, the spec says
that if CS is held high for more than 100us, the part will exit page
read mode. The default state of the UPM pins are high, so when the UPM
is idle all the signals are at logic 1.
Anyways, when the interrupt had completed, or driver wasn't aware that
an interrupt had occurred, so it continued to do it's read loop. The ST
Micro part was now in an undefined state. The page read appeared to
continue just fine, but we almost always had one or more bits corrupted
for the very first resuming data byte.
The fix that we ultimately did was to move the chip select control from
the UPM to a GPIO from the processor. This forced the chip to never
"sleep" during an interrupt, because we could keep the chip select low
for the entire page read transaction. This brought up other minor
issues. You must make sure that your boot loader (U-Boot in our case)
sets the GPIO data BEFORE it sets the GPIO direction. Otherwise the
NAND will automatically enter a start up read condition that will drive
the local bus, causing anything else on the local bus (such as a NOR
flash) to be useless...
The latest version of the app note online (link above) does not mention
the problem you may experience with interrupts. I requested from our
Freescale support contact that Freescale document this fact and make it
available to others such that they won't bump into the same problems we
did!
The THIRD issue we had (actually, are having) is very related to our
second issue. Our customer now wants a 2Gb NAND on our board. We
swapped the chip out. We included one more address byte transaction
that is needed with the larger part in the driver. And it doesn't work.
The part is considered to be the "bigger brother" to the 1Gb part, but
apparently enough of it's state machine has changed that it doesn't
tolerate the AL and CL lines going high while chip select is low.
Incidentally, when debugging our second issue we were told by ST Micro
support that the only time AL and CL were sampled by the NAND was when
W# and R# were driven low. Had we known that the 2Gb part wouldn't have
worked, we would have done much more major reworking to the NAND
subsystem when we respun our board.
This mail isn't meant to be a rant. Everyone knows that this kind of
low-level hardware/software work is difficult. This mail is meant to
caution you against using the NAND with the UPM. Freescale may say that
it works, and present you a pretty looking white paper, but it's really
kludgy and you are pretty guaranteed to have problems. Please encourage
your board designers to hook the NAND to some sort of CPLD device rather
than the UPM. At least with a CPLD you have some real control over the
state of the control lines.
If you for whatever reason are stuck with the UPM...
1.) Get your hardware people to stick inverters on the AL and CL lines.
Adjust your UPM microcode accordingly.
2.) Put your CS under control of a GPIO pin.
3.) Buy a nice logic analyzer, because you're going to need it!!!
I hope this helps someone out there... I've been spending a lot of time
on-and-off on this. Every time we think we have it right one little
seemingly benign change throws the whole thing out the window...
Okie, happy coding,
Chris Fester
^ permalink raw reply
* [PATCH] Convert media-bay.c to use the kthread API
From: Paul Mackerras @ 2007-12-13 3:12 UTC (permalink / raw)
To: linuxppc-dev
We aren't supposed to use kernel_thread directly in drivers any more,
and in fact using kthread_run is a bit simpler.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/mediabay.c b/drivers/macintosh/mediabay.c
index 48d647a..080844b 100644
--- a/drivers/macintosh/mediabay.c
+++ b/drivers/macintosh/mediabay.c
@@ -20,6 +20,7 @@
#include <linux/stddef.h>
#include <linux/init.h>
#include <linux/ide.h>
+#include <linux/kthread.h>
#include <asm/prom.h>
#include <asm/pgtable.h>
#include <asm/io.h>
@@ -35,7 +36,6 @@
#define MB_DEBUG
-#define MB_IGNORE_SIGNALS
#ifdef MB_DEBUG
#define MBDBG(fmt, arg...) printk(KERN_INFO fmt , ## arg)
@@ -622,12 +622,7 @@ static int media_bay_task(void *x)
{
int i;
- strcpy(current->comm, "media-bay");
-#ifdef MB_IGNORE_SIGNALS
- sigfillset(¤t->blocked);
-#endif
-
- for (;;) {
+ while (!kthread_should_stop()) {
for (i = 0; i < media_bay_count; ++i) {
down(&media_bays[i].lock);
if (!media_bays[i].sleeping)
@@ -636,8 +631,6 @@ static int media_bay_task(void *x)
}
msleep_interruptible(MB_POLL_DELAY);
- if (signal_pending(current))
- return 0;
}
}
@@ -699,7 +692,7 @@ static int __devinit media_bay_attach(struct macio_dev *mdev, const struct of_de
/* Startup kernel thread */
if (i == 0)
- kernel_thread(media_bay_task, NULL, CLONE_KERNEL);
+ kthread_run(media_bay_task, NULL, "media-bay");
return 0;
^ permalink raw reply related
* [PATCH 0/2] Add crashdump shutdown hooks
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
In-Reply-To: <20071212054512.A02B062C153@localhost.localdomain>
The following patches add crashdump shutdown hooks for POWERPC.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
This is an updated series following comments from the first post.
Adds some documentation, better code flow, fixes 32 bit compiles and
other updates based on feedback
Again these are based on paulus' for 2.6.25 tree.
^ permalink raw reply
* [PATCH 1/2] Make setjmp/longjmp code generic
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
In-Reply-To: <1197515777.834799.307108384755.qpush@coopers>
This makes the setjmp/longjmp code used by xmon, generically available
to other code. It also removes the requirement for debugger hooks to
be only called on 0x300 (data storage) exception and adds some
documentation.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/misc.S | 128 ++++++++++++++++++++++++++++++++++++++++
arch/powerpc/mm/fault.c | 6 -
arch/powerpc/xmon/Makefile | 2
arch/powerpc/xmon/setjmp.S | 135 -------------------------------------------
arch/powerpc/xmon/xmon.c | 38 ++++--------
include/asm-powerpc/setjmp.h | 19 ++++++
6 files changed, 164 insertions(+), 164 deletions(-)
Index: clone3/arch/powerpc/kernel/misc.S
===================================================================
--- clone3.orig/arch/powerpc/kernel/misc.S
+++ clone3/arch/powerpc/kernel/misc.S
@@ -8,6 +8,8 @@
* Adapted for iSeries by Mike Corrigan (mikejc@us.ibm.com)
* PPC64 updates by Dave Engebretsen (engebret@us.ibm.com)
*
+ * setjmp/longjmp and xmon_save_regs code by Paul Mackerras.
+ *
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
@@ -15,6 +17,8 @@
*/
#include <asm/ppc_asm.h>
#include <asm/unistd.h>
+#include <asm/asm-compat.h>
+#include <asm/asm-offsets.h>
.text
@@ -51,3 +55,127 @@ _GLOBAL(kernel_execve)
bnslr
neg r3,r3
blr
+
+_GLOBAL(setjmp)
+ mflr r0
+ PPC_STL r0,0(r3)
+ PPC_STL r1,SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ mfcr r0
+ PPC_STL r0,3*SZL(r3)
+ PPC_STL r13,4*SZL(r3)
+ PPC_STL r14,5*SZL(r3)
+ PPC_STL r15,6*SZL(r3)
+ PPC_STL r16,7*SZL(r3)
+ PPC_STL r17,8*SZL(r3)
+ PPC_STL r18,9*SZL(r3)
+ PPC_STL r19,10*SZL(r3)
+ PPC_STL r20,11*SZL(r3)
+ PPC_STL r21,12*SZL(r3)
+ PPC_STL r22,13*SZL(r3)
+ PPC_STL r23,14*SZL(r3)
+ PPC_STL r24,15*SZL(r3)
+ PPC_STL r25,16*SZL(r3)
+ PPC_STL r26,17*SZL(r3)
+ PPC_STL r27,18*SZL(r3)
+ PPC_STL r28,19*SZL(r3)
+ PPC_STL r29,20*SZL(r3)
+ PPC_STL r30,21*SZL(r3)
+ PPC_STL r31,22*SZL(r3)
+ li r3,0
+ blr
+
+_GLOBAL(longjmp)
+ PPC_LCMPI r4,0
+ bne 1f
+ li r4,1
+1: PPC_LL r13,4*SZL(r3)
+ PPC_LL r14,5*SZL(r3)
+ PPC_LL r15,6*SZL(r3)
+ PPC_LL r16,7*SZL(r3)
+ PPC_LL r17,8*SZL(r3)
+ PPC_LL r18,9*SZL(r3)
+ PPC_LL r19,10*SZL(r3)
+ PPC_LL r20,11*SZL(r3)
+ PPC_LL r21,12*SZL(r3)
+ PPC_LL r22,13*SZL(r3)
+ PPC_LL r23,14*SZL(r3)
+ PPC_LL r24,15*SZL(r3)
+ PPC_LL r25,16*SZL(r3)
+ PPC_LL r26,17*SZL(r3)
+ PPC_LL r27,18*SZL(r3)
+ PPC_LL r28,19*SZL(r3)
+ PPC_LL r29,20*SZL(r3)
+ PPC_LL r30,21*SZL(r3)
+ PPC_LL r31,22*SZL(r3)
+ PPC_LL r0,3*SZL(r3)
+ mtcrf 0x38,r0
+ PPC_LL r0,0(r3)
+ PPC_LL r1,SZL(r3)
+ PPC_LL r2,2*SZL(r3)
+ mtlr r0
+ mr r3,r4
+ blr
+
+#ifdef CONFIG_XMON
+/*
+ * Grab the register values as they are now.
+ * This won't do a particularily good job because we really
+ * want our caller's caller's registers, and our caller has
+ * already executed its prologue.
+ * ToDo: We could reach back into the caller's save area to do
+ * a better job of representing the caller's state (note that
+ * that will be different for 32-bit and 64-bit, because of the
+ * different ABIs, though).
+ */
+_GLOBAL(xmon_save_regs)
+ PPC_STL r0,0*SZL(r3)
+ PPC_STL r2,2*SZL(r3)
+ PPC_STL r3,3*SZL(r3)
+ PPC_STL r4,4*SZL(r3)
+ PPC_STL r5,5*SZL(r3)
+ PPC_STL r6,6*SZL(r3)
+ PPC_STL r7,7*SZL(r3)
+ PPC_STL r8,8*SZL(r3)
+ PPC_STL r9,9*SZL(r3)
+ PPC_STL r10,10*SZL(r3)
+ PPC_STL r11,11*SZL(r3)
+ PPC_STL r12,12*SZL(r3)
+ PPC_STL r13,13*SZL(r3)
+ PPC_STL r14,14*SZL(r3)
+ PPC_STL r15,15*SZL(r3)
+ PPC_STL r16,16*SZL(r3)
+ PPC_STL r17,17*SZL(r3)
+ PPC_STL r18,18*SZL(r3)
+ PPC_STL r19,19*SZL(r3)
+ PPC_STL r20,20*SZL(r3)
+ PPC_STL r21,21*SZL(r3)
+ PPC_STL r22,22*SZL(r3)
+ PPC_STL r23,23*SZL(r3)
+ PPC_STL r24,24*SZL(r3)
+ PPC_STL r25,25*SZL(r3)
+ PPC_STL r26,26*SZL(r3)
+ PPC_STL r27,27*SZL(r3)
+ PPC_STL r28,28*SZL(r3)
+ PPC_STL r29,29*SZL(r3)
+ PPC_STL r30,30*SZL(r3)
+ PPC_STL r31,31*SZL(r3)
+ /* go up one stack frame for SP */
+ PPC_LL r4,0(r1)
+ PPC_STL r4,1*SZL(r3)
+ /* get caller's LR */
+ PPC_LL r0,LRSAVE(r4)
+ PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
+ PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
+ mfmsr r0
+ PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
+ mfctr r0
+ PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
+ mfxer r0
+ PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
+ mfcr r0
+ PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
+ li r0,0
+ PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
+ blr
+#endif
Index: clone3/arch/powerpc/mm/fault.c
===================================================================
--- clone3.orig/arch/powerpc/mm/fault.c
+++ clone3/arch/powerpc/mm/fault.c
@@ -167,10 +167,8 @@ int __kprobes do_page_fault(struct pt_re
if (notify_page_fault(regs))
return 0;
- if (trap == 0x300) {
- if (debugger_fault_handler(regs))
- return 0;
- }
+ if (unlikely(debugger_fault_handler(regs)))
+ return 0;
/* On a kernel SLB miss we can only check for a valid exception entry */
if (!user_mode(regs) && (address >= TASK_SIZE))
Index: clone3/arch/powerpc/xmon/Makefile
===================================================================
--- clone3.orig/arch/powerpc/xmon/Makefile
+++ clone3/arch/powerpc/xmon/Makefile
@@ -4,7 +4,7 @@ ifdef CONFIG_PPC64
EXTRA_CFLAGS += -mno-minimal-toc
endif
-obj-y += xmon.o setjmp.o start.o nonstdio.o
+obj-y += xmon.o start.o nonstdio.o
ifdef CONFIG_XMON_DISASSEMBLY
obj-y += ppc-dis.o ppc-opc.o
Index: clone3/arch/powerpc/xmon/setjmp.S
===================================================================
--- clone3.orig/arch/powerpc/xmon/setjmp.S
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * Copyright (C) 1996 Paul Mackerras.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
- * NOTE: assert(sizeof(buf) > 23 * sizeof(long))
- */
-#include <asm/processor.h>
-#include <asm/ppc_asm.h>
-#include <asm/asm-offsets.h>
-
-_GLOBAL(xmon_setjmp)
- mflr r0
- PPC_STL r0,0(r3)
- PPC_STL r1,SZL(r3)
- PPC_STL r2,2*SZL(r3)
- mfcr r0
- PPC_STL r0,3*SZL(r3)
- PPC_STL r13,4*SZL(r3)
- PPC_STL r14,5*SZL(r3)
- PPC_STL r15,6*SZL(r3)
- PPC_STL r16,7*SZL(r3)
- PPC_STL r17,8*SZL(r3)
- PPC_STL r18,9*SZL(r3)
- PPC_STL r19,10*SZL(r3)
- PPC_STL r20,11*SZL(r3)
- PPC_STL r21,12*SZL(r3)
- PPC_STL r22,13*SZL(r3)
- PPC_STL r23,14*SZL(r3)
- PPC_STL r24,15*SZL(r3)
- PPC_STL r25,16*SZL(r3)
- PPC_STL r26,17*SZL(r3)
- PPC_STL r27,18*SZL(r3)
- PPC_STL r28,19*SZL(r3)
- PPC_STL r29,20*SZL(r3)
- PPC_STL r30,21*SZL(r3)
- PPC_STL r31,22*SZL(r3)
- li r3,0
- blr
-
-_GLOBAL(xmon_longjmp)
- PPC_LCMPI r4,0
- bne 1f
- li r4,1
-1: PPC_LL r13,4*SZL(r3)
- PPC_LL r14,5*SZL(r3)
- PPC_LL r15,6*SZL(r3)
- PPC_LL r16,7*SZL(r3)
- PPC_LL r17,8*SZL(r3)
- PPC_LL r18,9*SZL(r3)
- PPC_LL r19,10*SZL(r3)
- PPC_LL r20,11*SZL(r3)
- PPC_LL r21,12*SZL(r3)
- PPC_LL r22,13*SZL(r3)
- PPC_LL r23,14*SZL(r3)
- PPC_LL r24,15*SZL(r3)
- PPC_LL r25,16*SZL(r3)
- PPC_LL r26,17*SZL(r3)
- PPC_LL r27,18*SZL(r3)
- PPC_LL r28,19*SZL(r3)
- PPC_LL r29,20*SZL(r3)
- PPC_LL r30,21*SZL(r3)
- PPC_LL r31,22*SZL(r3)
- PPC_LL r0,3*SZL(r3)
- mtcrf 0x38,r0
- PPC_LL r0,0(r3)
- PPC_LL r1,SZL(r3)
- PPC_LL r2,2*SZL(r3)
- mtlr r0
- mr r3,r4
- blr
-
-/*
- * Grab the register values as they are now.
- * This won't do a particularily good job because we really
- * want our caller's caller's registers, and our caller has
- * already executed its prologue.
- * ToDo: We could reach back into the caller's save area to do
- * a better job of representing the caller's state (note that
- * that will be different for 32-bit and 64-bit, because of the
- * different ABIs, though).
- */
-_GLOBAL(xmon_save_regs)
- PPC_STL r0,0*SZL(r3)
- PPC_STL r2,2*SZL(r3)
- PPC_STL r3,3*SZL(r3)
- PPC_STL r4,4*SZL(r3)
- PPC_STL r5,5*SZL(r3)
- PPC_STL r6,6*SZL(r3)
- PPC_STL r7,7*SZL(r3)
- PPC_STL r8,8*SZL(r3)
- PPC_STL r9,9*SZL(r3)
- PPC_STL r10,10*SZL(r3)
- PPC_STL r11,11*SZL(r3)
- PPC_STL r12,12*SZL(r3)
- PPC_STL r13,13*SZL(r3)
- PPC_STL r14,14*SZL(r3)
- PPC_STL r15,15*SZL(r3)
- PPC_STL r16,16*SZL(r3)
- PPC_STL r17,17*SZL(r3)
- PPC_STL r18,18*SZL(r3)
- PPC_STL r19,19*SZL(r3)
- PPC_STL r20,20*SZL(r3)
- PPC_STL r21,21*SZL(r3)
- PPC_STL r22,22*SZL(r3)
- PPC_STL r23,23*SZL(r3)
- PPC_STL r24,24*SZL(r3)
- PPC_STL r25,25*SZL(r3)
- PPC_STL r26,26*SZL(r3)
- PPC_STL r27,27*SZL(r3)
- PPC_STL r28,28*SZL(r3)
- PPC_STL r29,29*SZL(r3)
- PPC_STL r30,30*SZL(r3)
- PPC_STL r31,31*SZL(r3)
- /* go up one stack frame for SP */
- PPC_LL r4,0(r1)
- PPC_STL r4,1*SZL(r3)
- /* get caller's LR */
- PPC_LL r0,LRSAVE(r4)
- PPC_STL r0,_NIP-STACK_FRAME_OVERHEAD(r3)
- PPC_STL r0,_LINK-STACK_FRAME_OVERHEAD(r3)
- mfmsr r0
- PPC_STL r0,_MSR-STACK_FRAME_OVERHEAD(r3)
- mfctr r0
- PPC_STL r0,_CTR-STACK_FRAME_OVERHEAD(r3)
- mfxer r0
- PPC_STL r0,_XER-STACK_FRAME_OVERHEAD(r3)
- mfcr r0
- PPC_STL r0,_CCR-STACK_FRAME_OVERHEAD(r3)
- li r0,0
- PPC_STL r0,_TRAP-STACK_FRAME_OVERHEAD(r3)
- blr
Index: clone3/arch/powerpc/xmon/xmon.c
===================================================================
--- clone3.orig/arch/powerpc/xmon/xmon.c
+++ clone3/arch/powerpc/xmon/xmon.c
@@ -40,6 +40,7 @@
#include <asm/spu.h>
#include <asm/spu_priv1.h>
#include <asm/firmware.h>
+#include <asm/setjmp.h>
#ifdef CONFIG_PPC64
#include <asm/hvcall.h>
@@ -71,12 +72,9 @@ static unsigned long ncsum = 4096;
static int termch;
static char tmpstr[128];
-#define JMP_BUF_LEN 23
-static long bus_error_jmp[JMP_BUF_LEN];
+static long bus_error_jmp[SETJMP_BUF_LEN];
static int catch_memory_errors;
static long *xmon_fault_jmp[NR_CPUS];
-#define setjmp xmon_setjmp
-#define longjmp xmon_longjmp
/* Breakpoint stuff */
struct bpt {
@@ -162,8 +160,6 @@ int xmon_no_auto_backtrace;
extern void xmon_enter(void);
extern void xmon_leave(void);
-extern long setjmp(long *);
-extern void longjmp(long *, long);
extern void xmon_save_regs(struct pt_regs *);
#ifdef CONFIG_PPC64
@@ -338,7 +334,7 @@ static int xmon_core(struct pt_regs *reg
{
int cmd = 0;
struct bpt *bp;
- long recurse_jmp[JMP_BUF_LEN];
+ long recurse_jmp[SETJMP_BUF_LEN];
unsigned long offset;
unsigned long flags;
#ifdef CONFIG_SMP
@@ -1428,7 +1424,7 @@ void prregs(struct pt_regs *fp)
sync();
regs = *(struct pt_regs *)base;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error reading registers from "REG"\n",
@@ -1497,8 +1493,7 @@ void cacheflush(void)
cinval((void *) adrs);
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
}
@@ -1533,8 +1528,7 @@ read_spr(int n)
ret = code();
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
@@ -1569,8 +1563,7 @@ write_spr(int n, unsigned long val)
code(val);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
}
@@ -1676,8 +1669,7 @@ mread(unsigned long adrs, void *buf, int
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
}
catch_memory_errors = 0;
@@ -1713,8 +1705,7 @@ mwrite(unsigned long adrs, void *buf, in
}
}
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
n = size;
} else {
printf("*** Error writing address %x\n", adrs + n);
@@ -2521,8 +2512,7 @@ static void xmon_print_symbol(unsigned l
name = kallsyms_lookup(address, &size, &offset, &modname,
tmpstr);
sync();
- /* wait a little while to see if we get a machine check */
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
}
catch_memory_errors = 0;
@@ -2777,7 +2767,7 @@ static void stop_spus(void)
spu_mfc_sr1_set(spu, tmp);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
spu_info[i].stopped_ok = 1;
@@ -2817,7 +2807,7 @@ static void restart_spus(void)
spu_info[i].saved_spu_runcntl_RW);
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
printf("Restarted spu %.2d\n", i);
} else {
@@ -2837,7 +2827,7 @@ do { \
printf(" %-*s = "format"\n", DUMP_WIDTH, \
#field, value); \
sync(); \
- __delay(200); \
+ __delay(SETJMP_MACHINE_CHECK_DELAY); \
} else { \
catch_memory_errors = 0; \
printf(" %-*s = *** Error reading field.\n", \
@@ -2899,7 +2889,7 @@ static void dump_spu_ls(unsigned long nu
sync();
ls_addr = (unsigned long)spu_info[num].spu->local_store;
sync();
- __delay(200);
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
} else {
catch_memory_errors = 0;
printf("*** Error: accessing spu info for spu %d\n", num);
Index: clone3/include/asm-powerpc/setjmp.h
===================================================================
--- /dev/null
+++ clone3/include/asm-powerpc/setjmp.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2007 Michael Neuling
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+#ifndef _ASM_POWERPC_SETJMP_H
+#define _ASM_POWERPC_SETJMP_H
+
+#define SETJMP_BUF_LEN 23
+#define SETJMP_MACHINE_CHECK_DELAY 200
+
+extern long setjmp(long *);
+extern void longjmp(long *, long);
+
+#endif /* _ASM_POWERPC_SETJMP_H */
^ permalink raw reply
* [PATCH 2/2] kdump shutdown hook support
From: Michael Neuling @ 2007-12-13 3:16 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Michael Neuling, RAISCH, THEMANN
In-Reply-To: <1197515777.834799.307108384755.qpush@coopers>
This adds hooks into the default_machine_crash_shutdown so drivers can
register a function to be run in the first kernel before we hand off
to the second kernel. This should only be used in exceptional
circumstances, like where the device can't be reset in the second
kernel alone (as is the case with eHEA). To emphasize this, the
number of handles allowed to be registered is currently #def to 1.
This uses the setjmp/longjmp code to call out to the registered hooks,
so any bogus exceptions we encounter will hopefully be recoverable.
Tested with bogus data and instruction exceptions.
Signed-off-by: Michael Neuling <mikey@neuling.org>
---
arch/powerpc/kernel/crash.c | 102 +++++++++++++++++++++++++++++++++++++++++---
include/asm-powerpc/kexec.h | 3 +
2 files changed, 100 insertions(+), 5 deletions(-)
Index: clone3/arch/powerpc/kernel/crash.c
===================================================================
--- clone3.orig/arch/powerpc/kernel/crash.c
+++ clone3/arch/powerpc/kernel/crash.c
@@ -32,6 +32,8 @@
#include <asm/lmb.h>
#include <asm/firmware.h>
#include <asm/smp.h>
+#include <asm/system.h>
+#include <asm/setjmp.h>
#ifdef DEBUG
#include <asm/udbg.h>
@@ -45,6 +47,11 @@ int crashing_cpu = -1;
static cpumask_t cpus_in_crash = CPU_MASK_NONE;
cpumask_t cpus_in_sr = CPU_MASK_NONE;
+#define CRASH_HANDLER_MAX 1
+/* NULL terminated list of shutdown handles */
+static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
+static DEFINE_SPINLOCK(crash_handers_lock);
+
#ifdef CONFIG_SMP
static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
@@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
}
#endif /* CONFIG_SPU_BASE */
+/*
+ * Register a function to be called on shutdown. Only use this if you
+ * can't reset your device in the second kernel.
+ */
+int crash_shutdown_register(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (!crash_shutdown_handles[i]) {
+ /* Insert handle at first empty entry */
+ crash_shutdown_handles[i] = handler;
+ rc = 0;
+ break;
+ }
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handles full, "
+ "not registered.\n");
+ rc = 1;
+ }
+
+ spin_unlock(&crash_handers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_register);
+
+int crash_shutdown_unregister(crash_shutdown_t handler)
+{
+ unsigned int i, rc;
+
+ spin_lock(&crash_handers_lock);
+ for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
+ if (crash_shutdown_handles[i] == handler)
+ break;
+
+ if (i == CRASH_HANDLER_MAX) {
+ printk(KERN_ERR "Crash shutdown handle not found\n");
+ rc = 1;
+ } else {
+ /* Shift handles down */
+ for (; crash_shutdown_handles[i]; i++)
+ crash_shutdown_handles[i] =
+ crash_shutdown_handles[i+1];
+ rc = 0;
+ }
+
+ spin_unlock(&crash_handers_lock);
+ return rc;
+}
+EXPORT_SYMBOL(crash_shutdown_unregister);
+
+static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
+
+static int handle_fault(struct pt_regs *regs)
+{
+ longjmp(crash_shutdown_buf, 1);
+ return 0;
+}
+
void default_machine_crash_shutdown(struct pt_regs *regs)
{
- unsigned int irq;
+ unsigned int i;
+ int (*old_handler)(struct pt_regs *regs);
+
/*
* This function is only called after the system
@@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
*/
hard_irq_disable();
- for_each_irq(irq) {
- struct irq_desc *desc = irq_desc + irq;
+ for_each_irq(i) {
+ struct irq_desc *desc = irq_desc + i;
if (desc->status & IRQ_INPROGRESS)
- desc->chip->eoi(irq);
+ desc->chip->eoi(i);
if (!(desc->status & IRQ_DISABLED))
- desc->chip->disable(irq);
+ desc->chip->disable(i);
+ }
+
+ /*
+ * Call registered shutdown routines savely. Swap out
+ * __debugger_fault_handler, and replace on exit.
+ */
+ old_handler = __debugger_fault_handler;
+ __debugger_fault_handler = handle_fault;
+ for (i = 0; crash_shutdown_handles[i]; i++) {
+ if (setjmp(crash_shutdown_buf) == 0) {
+ /*
+ * Insert syncs and delay to ensure
+ * instructions in the dangerous region don't
+ * leak away from this protected region.
+ */
+ asm volatile("sync; isync");
+ /* dangerous region */
+ crash_shutdown_handles[i]();
+ asm volatile("sync; isync");
+ __delay(SETJMP_MACHINE_CHECK_DELAY);
+ }
}
+ __debugger_fault_handler = old_handler;
/*
* Make a note of crashing cpu. Will be used in machine_kexec
Index: clone3/include/asm-powerpc/kexec.h
===================================================================
--- clone3.orig/include/asm-powerpc/kexec.h
+++ clone3/include/asm-powerpc/kexec.h
@@ -123,6 +123,9 @@ struct pt_regs;
extern void default_machine_kexec(struct kimage *image);
extern int default_machine_kexec_prepare(struct kimage *image);
extern void default_machine_crash_shutdown(struct pt_regs *regs);
+typedef void (*crash_shutdown_t)(void);
+extern int crash_shutdown_register(crash_shutdown_t handler);
+extern int crash_shutdown_unregister(crash_shutdown_t handler);
extern void machine_kexec_simple(struct kimage *image);
extern void crash_kexec_secondary(struct pt_regs *regs);
^ permalink raw reply
* printf - How does it work?
From: Siva Prasad @ 2007-12-13 3:23 UTC (permalink / raw)
To: linuxppc-dev
[-- Attachment #1: Type: text/plain, Size: 385 bytes --]
Hi,
Can some one point me to an URL or some thing that explains how exactly
the characters from printf in user program gets printed on to the
console. Some thing like "it goes to /dev/console, and kernel reads from
....." would be great, so that I can trace it out.
Is there any way, we can get access to those prints from the kernel?
Thanks
Siva
[-- Attachment #2: Type: text/html, Size: 2490 bytes --]
^ permalink raw reply
* [PATCH] Convert adb.c to use kthread API and not spin on ADB requests
From: Paul Mackerras @ 2007-12-13 4:11 UTC (permalink / raw)
To: linuxppc-dev
This converts adb.c to use the kthread API.
It also changes adb_request so that if the ADBREQ_SYNC flag is
specified, we now sleep waiting for the request to finish using an
on-stack completion rather than spinning. To implement this, we now
require that if the ADBREQ_SYNC flag is set, the `done' parameter must
be NULL. All of the existing callers of adb_request that pass
ADBREQ_SYNC appear to be in process context and have done == NULL.
Doing this allows us to get rid of an awful hack in adb_request()
where we used to test whether the request was coming from the adb
probe task and use a completion if it was, and otherwise spin.
This also gets rid of a static request block that was used if the req
parameter to adb_request was NULL. None of the callers do that any
more, so the static request block is no longer necessary.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/adb.c b/drivers/macintosh/adb.c
index 7b892f4..5ae28f0 100644
--- a/drivers/macintosh/adb.c
+++ b/drivers/macintosh/adb.c
@@ -35,6 +35,7 @@
#include <linux/spinlock.h>
#include <linux/completion.h>
#include <linux/device.h>
+#include <linux/kthread.h>
#include <asm/uaccess.h>
#include <asm/semaphore.h>
@@ -82,9 +83,7 @@ struct adb_driver *adb_controller;
BLOCKING_NOTIFIER_HEAD(adb_client_list);
static int adb_got_sleep;
static int adb_inited;
-static pid_t adb_probe_task_pid;
static DECLARE_MUTEX(adb_probe_mutex);
-static struct completion adb_probe_task_comp;
static int sleepy_trackpad;
static int autopoll_devs;
int __adb_probe_sync;
@@ -126,16 +125,6 @@ static void printADBreply(struct adb_request *req)
}
#endif
-
-static __inline__ void adb_wait_ms(unsigned int ms)
-{
- if (current->pid && adb_probe_task_pid &&
- adb_probe_task_pid == current->pid)
- msleep(ms);
- else
- mdelay(ms);
-}
-
static int adb_scan_bus(void)
{
int i, highFree=0, noMovement;
@@ -240,13 +229,10 @@ static int adb_scan_bus(void)
static int
adb_probe_task(void *x)
{
- strcpy(current->comm, "kadbprobe");
-
printk(KERN_INFO "adb: starting probe task...\n");
do_adb_reset_bus();
printk(KERN_INFO "adb: finished probe task...\n");
- adb_probe_task_pid = 0;
up(&adb_probe_mutex);
return 0;
@@ -255,7 +241,7 @@ adb_probe_task(void *x)
static void
__adb_probe_task(struct work_struct *bullshit)
{
- adb_probe_task_pid = kernel_thread(adb_probe_task, NULL, SIGCHLD | CLONE_KERNEL);
+ kthread_run(adb_probe_task, NULL, "kadbprobe");
}
static DECLARE_WORK(adb_reset_work, __adb_probe_task);
@@ -341,7 +327,6 @@ int __init adb_init(void)
sleepy_trackpad = 1;
#endif /* CONFIG_PPC */
- init_completion(&adb_probe_task_comp);
adbdev_init();
adb_reset_bus();
}
@@ -366,7 +351,7 @@ do_adb_reset_bus(void)
if (sleepy_trackpad) {
/* Let the trackpad settle down */
- adb_wait_ms(500);
+ msleep(500);
}
down(&adb_handler_sem);
@@ -382,7 +367,7 @@ do_adb_reset_bus(void)
if (sleepy_trackpad) {
/* Let the trackpad settle down */
- adb_wait_ms(1500);
+ msleep(1500);
}
if (!ret) {
@@ -406,41 +391,27 @@ adb_poll(void)
adb_controller->poll();
}
-static void
-adb_probe_wakeup(struct adb_request *req)
+static void adb_sync_req_done(struct adb_request *req)
{
- complete(&adb_probe_task_comp);
-}
+ struct completion *comp = req->arg;
-/* Static request used during probe */
-static struct adb_request adb_sreq;
-static unsigned long adb_sreq_lock; // Use semaphore ! */
+ complete(comp);
+}
int
adb_request(struct adb_request *req, void (*done)(struct adb_request *),
int flags, int nbytes, ...)
{
va_list list;
- int i, use_sreq;
+ int i;
int rc;
+ struct completion comp;
if ((adb_controller == NULL) || (adb_controller->send_request == NULL))
return -ENXIO;
if (nbytes < 1)
return -EINVAL;
- if (req == NULL && (flags & ADBREQ_NOSEND))
- return -EINVAL;
-
- if (req == NULL) {
- if (test_and_set_bit(0,&adb_sreq_lock)) {
- printk("adb.c: Warning: contention on static request !\n");
- return -EPERM;
- }
- req = &adb_sreq;
- flags |= ADBREQ_SYNC;
- use_sreq = 1;
- } else
- use_sreq = 0;
+
req->nbytes = nbytes+1;
req->done = done;
req->reply_expected = flags & ADBREQ_REPLY;
@@ -453,25 +424,18 @@ adb_request(struct adb_request *req, void (*done)(struct adb_request *),
if (flags & ADBREQ_NOSEND)
return 0;
- /* Synchronous requests send from the probe thread cause it to
- * block. Beware that the "done" callback will be overriden !
- */
- if ((flags & ADBREQ_SYNC) &&
- (current->pid && adb_probe_task_pid &&
- adb_probe_task_pid == current->pid)) {
- req->done = adb_probe_wakeup;
- rc = adb_controller->send_request(req, 0);
- if (rc || req->complete)
- goto bail;
- wait_for_completion(&adb_probe_task_comp);
- rc = 0;
- goto bail;
+ /* Synchronous requests block using an on-stack completion */
+ if (flags & ADBREQ_SYNC) {
+ WARN_ON(done);
+ req->done = adb_sync_req_done;
+ req->arg = ∁
+ init_completion(&comp);
}
- rc = adb_controller->send_request(req, flags & ADBREQ_SYNC);
-bail:
- if (use_sreq)
- clear_bit(0, &adb_sreq_lock);
+ rc = adb_controller->send_request(req, 0);
+
+ if ((flags & ADBREQ_SYNC) && !rc && !req->complete)
+ wait_for_completion(&comp);
return rc;
}
^ permalink raw reply related
* RE: Xilinx devicetrees
From: Stephen Neuendorffer @ 2007-12-13 4:52 UTC (permalink / raw)
To: Koss, Mike (Mission Systems), David H. Lynch Jr., Grant Likely,
linuxppc-embedded
In-Reply-To: <EDAE140DF1B2FC42B5867C22CA0B333F0A58E4@XMBIL132.northgrum.com>
[-- Attachment #1: Type: text/plain, Size: 3699 bytes --]
-----Original Message-----
From: Koss, Mike (Mission Systems) [mailto:mike.koss@ngc.com]
Sent: Mon 11/26/2007 7:31 AM
To: Stephen Neuendorffer; David H. Lynch Jr.; Grant Likely; linuxppc-embedded
Subject: RE: Xilinx devicetrees
Time for my $.02, since I am heavily weighting my future designs on the
use of the device trees. :) (and b/c I don't check my work e-mail from
home ;P)
________________________________
SN> As Grant says, the dynamic detection doesn't have to be done in the
boot loader, it could be done in the platform code. You can largely
ignore
SN> the device trees, or always boot with a core device tree and figure
it all out later (perhaps using version registers). I anticipate that
SN> the 'standard flow' will have standard platform code for any board
that uses a complete device tree. If you have the need to do something
SN> extraordinary, then you should feel free to hack away... However,
It doesn't seem to me to be really necessary in your case, assuming that
SN> the device tree is packaged (somehow, TBD) along with the bitstream.
> I don't know if packaging the device tree with the bitstream is the best
> way to go. It's possible that it could lead to headaches for certain
> systems that have security restrictions. The same could be said for
> using it w/ the SystemACE to load it into RAM after the image. (which is
> what I'm currently doing for my 2 linux images in lieu of a true on-chip
> bootloader). I am already taking the security concerns into account for
> future revisions of the hardware wrt to using a SystemACE, and am
> planning on moving the device trees into NV storage like FLASH.
'with' not 'in'. either using SystemAce, or a flash image.
> One solution I've been thinking through (in lieu of direct support from
> EDK) is to use a tcl script with xps to traverse the hardware tree and
> generate the device tree. It seems like it should be relatively trivial
> to obtain the information. It's just going to be a pain to write all the
> handlers for each different linux driver: temac, interrupt controller,
> DMA controller, etc.
> In reality the best way to handle this would be to have EDK generate the
> device tree as part of the library/bsp build process.
We have a python script to do this. The main problem with just looking at the mhs file is that you lose all the defaults for each IP. Hence, we've also written a BSP generator to do this. both are at git://git.xilinx.com/gen-mhs-devtree.py
Once I can verify that they work in the mainline tree, I'll be sending out the patches that make this all work.
> Now, what I'd like
> to see with regards to this is the ability to change the handler for the
> generating a specific device information. An example could be the temac.
> If at some point in the future the temac needs new/more information to
> support its configuration/run-time then having to get a patch from
> Xilinx for a EDK is way too slow. The developers should be giving the
> opportunity to inject a new handler into the various parts of the device
> tree generation. That way when the kernel patch is submitted, an EDK
> device generator patch will be submitted at the same time to keep
> everything in sync.
Interesting idea.. I've been trying to figure out how to architect this better, but it requires some information passing within EDK that isnot today supported. I don't see at all how to synchronize this with patches to the kernel, tho. My approach is to describe the hardware as completely and faithfully as we can (given the information in EDK), and let the drivers do whatever with it that they want to.
Steve
[-- Attachment #2: Type: text/html, Size: 4504 bytes --]
^ permalink raw reply
* [PATCH] Convert therm_pm72.c to use the kthread API
From: Paul Mackerras @ 2007-12-13 4:54 UTC (permalink / raw)
To: linuxppc-dev
This converts the therm_pm72.c driver to use the kthread API. I
thought about making it use kthread_stop() instead of the `state'
variable and the `ctrl_complete' completion, but that isn't simple and
will require changing the way that `state' is used.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index e43554e..6fadc9a 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -121,6 +121,7 @@
#include <linux/reboot.h>
#include <linux/kmod.h>
#include <linux/i2c.h>
+#include <linux/kthread.h>
#include <asm/prom.h>
#include <asm/machdep.h>
#include <asm/io.h>
@@ -161,7 +162,7 @@ static struct slots_pid_state slots_state;
static int state;
static int cpu_count;
static int cpu_pid_type;
-static pid_t ctrl_task;
+static struct task_struct *ctrl_task;
static struct completion ctrl_complete;
static int critical_state;
static int rackmac;
@@ -1779,8 +1780,6 @@ static int call_critical_overtemp(void)
*/
static int main_control_loop(void *x)
{
- daemonize("kfand");
-
DBG("main_control_loop started\n");
down(&driver_lock);
@@ -1956,7 +1955,7 @@ static void start_control_loops(void)
{
init_completion(&ctrl_complete);
- ctrl_task = kernel_thread(main_control_loop, NULL, SIGCHLD | CLONE_KERNEL);
+ ctrl_task = kthread_run(main_control_loop, NULL, "kfand");
}
/*
@@ -1964,7 +1963,7 @@ static void start_control_loops(void)
*/
static void stop_control_loops(void)
{
- if (ctrl_task != 0)
+ if (ctrl_task)
wait_for_completion(&ctrl_complete);
}
^ permalink raw reply related
* [PATCH] Convert therm_windtunnel.c to use the kthread API
From: Paul Mackerras @ 2007-12-13 4:57 UTC (permalink / raw)
To: linuxppc-dev
This is fairly straightforward, and lets us get rid of x.completion
as well.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 5452da1..3722402 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -36,6 +36,7 @@
#include <linux/i2c.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/kthread.h>
#include <asm/prom.h>
#include <asm/machdep.h>
@@ -61,8 +62,7 @@ I2C_CLIENT_INSMOD;
static struct {
volatile int running;
- struct completion completion;
- pid_t poll_task;
+ struct task_struct *poll_task;
struct semaphore lock;
struct of_device *of_dev;
@@ -282,27 +282,27 @@ restore_regs( void )
write_reg( x.fan, 0x00, x.r0, 1 );
}
-static int
-control_loop( void *dummy )
+static int control_loop(void *dummy)
{
- daemonize("g4fand");
-
- down( &x.lock );
+ down(&x.lock);
setup_hardware();
+ up(&x.lock);
- while( x.running ) {
- up( &x.lock );
-
+ for (;;) {
msleep_interruptible(8000);
-
- down( &x.lock );
+ if (kthread_should_stop())
+ break;
+
+ down(&x.lock);
poll_temp();
+ up(&x.lock);
}
+ down(&x.lock);
restore_regs();
- up( &x.lock );
+ up(&x.lock);
- complete_and_exit( &x.completion, 0 );
+ return 0;
}
@@ -322,8 +322,7 @@ do_attach( struct i2c_adapter *adapter )
ret = i2c_probe( adapter, &addr_data, &do_probe );
if( x.thermostat && x.fan ) {
x.running = 1;
- init_completion( &x.completion );
- x.poll_task = kernel_thread( control_loop, NULL, SIGCHLD | CLONE_KERNEL );
+ x.poll_task = kthread_run(control_loop, NULL, "g4fand");
}
}
return ret;
@@ -339,7 +338,8 @@ do_detach( struct i2c_client *client )
else {
if( x.running ) {
x.running = 0;
- wait_for_completion( &x.completion );
+ kthread_stop(x.poll_task);
+ x.poll_task = NULL;
}
if( client == x.thermostat )
x.thermostat = NULL;
^ permalink raw reply related
* Re: [PATCH 2/2] kdump shutdown hook support
From: Olof Johansson @ 2007-12-13 5:12 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <20071213031618.DBD207038C@localhost.localdomain>
Hi,
On Thu, Dec 13, 2007 at 02:16:18PM +1100, Michael Neuling wrote:
> Index: clone3/arch/powerpc/kernel/crash.c
> ===================================================================
> --- clone3.orig/arch/powerpc/kernel/crash.c
> +++ clone3/arch/powerpc/kernel/crash.c
> @@ -32,6 +32,8 @@
> #include <asm/lmb.h>
> #include <asm/firmware.h>
> #include <asm/smp.h>
> +#include <asm/system.h>
> +#include <asm/setjmp.h>
>
> #ifdef DEBUG
> #include <asm/udbg.h>
> @@ -45,6 +47,11 @@ int crashing_cpu = -1;
> static cpumask_t cpus_in_crash = CPU_MASK_NONE;
> cpumask_t cpus_in_sr = CPU_MASK_NONE;
>
> +#define CRASH_HANDLER_MAX 1
> +/* NULL terminated list of shutdown handles */
> +static crash_shutdown_t crash_shutdown_handles[CRASH_HANDLER_MAX+1];
> +static DEFINE_SPINLOCK(crash_handers_lock);
How about just using 'handlers' instead of 'handers' and 'handles'? :)
> static atomic_t enter_on_soft_reset = ATOMIC_INIT(0);
>
> @@ -285,9 +292,72 @@ static inline void crash_kexec_stop_spus
> }
> #endif /* CONFIG_SPU_BASE */
>
> +/*
> + * Register a function to be called on shutdown. Only use this if you
> + * can't reset your device in the second kernel.
> + */
> +int crash_shutdown_register(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handers_lock);
> + for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
> + if (!crash_shutdown_handles[i]) {
> + /* Insert handle at first empty entry */
> + crash_shutdown_handles[i] = handler;
> + rc = 0;
> + break;
> + }
> +
> + if (i == CRASH_HANDLER_MAX) {
> + printk(KERN_ERR "Crash shutdown handles full, "
> + "not registered.\n");
> + rc = 1;
> + }
> +
> + spin_unlock(&crash_handers_lock);
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_register);
> +
> +int crash_shutdown_unregister(crash_shutdown_t handler)
> +{
> + unsigned int i, rc;
> +
> + spin_lock(&crash_handers_lock);
> + for (i = 0 ; i < CRASH_HANDLER_MAX; i++)
> + if (crash_shutdown_handles[i] == handler)
> + break;
> +
> + if (i == CRASH_HANDLER_MAX) {
> + printk(KERN_ERR "Crash shutdown handle not found\n");
> + rc = 1;
> + } else {
> + /* Shift handles down */
> + for (; crash_shutdown_handles[i]; i++)
> + crash_shutdown_handles[i] =
> + crash_shutdown_handles[i+1];
> + rc = 0;
> + }
> +
> + spin_unlock(&crash_handers_lock);
> + return rc;
> +}
> +EXPORT_SYMBOL(crash_shutdown_unregister);
> +
> +static unsigned long crash_shutdown_buf[SETJMP_BUF_LEN];
> +
> +static int handle_fault(struct pt_regs *regs)
> +{
> + longjmp(crash_shutdown_buf, 1);
> + return 0;
> +}
> +
> void default_machine_crash_shutdown(struct pt_regs *regs)
> {
> - unsigned int irq;
> + unsigned int i;
> + int (*old_handler)(struct pt_regs *regs);
> +
>
> /*
> * This function is only called after the system
> @@ -301,15 +371,37 @@ void default_machine_crash_shutdown(stru
> */
> hard_irq_disable();
>
> - for_each_irq(irq) {
> - struct irq_desc *desc = irq_desc + irq;
> + for_each_irq(i) {
> + struct irq_desc *desc = irq_desc + i;
>
> if (desc->status & IRQ_INPROGRESS)
> - desc->chip->eoi(irq);
> + desc->chip->eoi(i);
>
> if (!(desc->status & IRQ_DISABLED))
> - desc->chip->disable(irq);
> + desc->chip->disable(i);
> + }
> +
> + /*
> + * Call registered shutdown routines savely. Swap out
> + * __debugger_fault_handler, and replace on exit.
> + */
> + old_handler = __debugger_fault_handler;
> + __debugger_fault_handler = handle_fault;
> + for (i = 0; crash_shutdown_handles[i]; i++) {
> + if (setjmp(crash_shutdown_buf) == 0) {
> + /*
> + * Insert syncs and delay to ensure
> + * instructions in the dangerous region don't
> + * leak away from this protected region.
> + */
> + asm volatile("sync; isync");
> + /* dangerous region */
> + crash_shutdown_handles[i]();
> + asm volatile("sync; isync");
> + __delay(SETJMP_MACHINE_CHECK_DELAY);
Where is this defined?
> + }
> }
> + __debugger_fault_handler = old_handler;
>
> /*
> * Make a note of crashing cpu. Will be used in machine_kexec
> Index: clone3/include/asm-powerpc/kexec.h
> ===================================================================
> --- clone3.orig/include/asm-powerpc/kexec.h
> +++ clone3/include/asm-powerpc/kexec.h
> @@ -123,6 +123,9 @@ struct pt_regs;
> extern void default_machine_kexec(struct kimage *image);
> extern int default_machine_kexec_prepare(struct kimage *image);
> extern void default_machine_crash_shutdown(struct pt_regs *regs);
> +typedef void (*crash_shutdown_t)(void);
> +extern int crash_shutdown_register(crash_shutdown_t handler);
> +extern int crash_shutdown_unregister(crash_shutdown_t handler);
>
> extern void machine_kexec_simple(struct kimage *image);
> extern void crash_kexec_secondary(struct pt_regs *regs);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
^ permalink raw reply
* Re: [PATCH 2/2] kdump shutdown hook support
From: Olof Johansson @ 2007-12-13 5:13 UTC (permalink / raw)
To: Michael Neuling; +Cc: linuxppc-dev, RAISCH, Paul Mackerras, THEMANN
In-Reply-To: <20071213051224.GA22378@lixom.net>
On Wed, Dec 12, 2007 at 11:12:24PM -0600, Olof Johansson wrote:
> Hi,
> > + __delay(SETJMP_MACHINE_CHECK_DELAY);
>
> Where is this defined?
Oops, nevermind. In 1/2, of course. :-)
-Olof
^ permalink raw reply
* [PATCH] Do ioremap and allocation for sleep on 3400 once at boot
From: Paul Mackerras @ 2007-12-13 5:15 UTC (permalink / raw)
To: linuxppc-dev
Currently the sleep code on the old powerbook 3400 does an ioremap and
a kmalloc on each sleep/wakeup cycle. This moves the ioremap and
kmalloc to boot-time code (via_pmu_start) so that they only need to be
done once. This will be more convenient when we change to using the
generic suspend code, since it will avoid the need to do the
ioremap/kmalloc after devices have been suspended.
Signed-off-by: Paul Mackerras <paulus@samba.org>
---
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 35e1f22..0e84cb8 100644
--- a/drivers/macintosh/via-pmu.c
+++ b/drivers/macintosh/via-pmu.c
@@ -203,6 +203,12 @@ static int proc_read_options(char *page, char **start, off_t off,
static int proc_write_options(struct file *file, const char __user *buffer,
unsigned long count, void *data);
+#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32)
+static void powerbook_sleep_init_3400(void);
+#else
+#define powerbook_sleep_init_3400() do { } while (0)
+#endif
+
#ifdef CONFIG_ADB
struct adb_driver via_pmu_driver = {
"PMU",
@@ -450,6 +456,10 @@ static int __init via_pmu_start(void)
pmu_poll();
} while (pmu_state != idle);
+ /* Do allocations and ioremaps that will be needed for sleep */
+ if (pmu_kind == PMU_OHARE_BASED)
+ powerbook_sleep_init_3400();
+
return 0;
}
@@ -2271,26 +2281,30 @@ powerbook_sleep_Core99(void)
#define PB3400_MEM_CTRL 0xf8000000
#define PB3400_MEM_CTRL_SLEEP 0x70
-static int
-powerbook_sleep_3400(void)
+static void __iomem *pb3400_mem_ctrl;
+
+static void powerbook_sleep_init_3400(void)
+{
+ /* map in the memory controller registers */
+ pb3400_mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
+ if (pb3400_mem_ctrl == NULL)
+ printk(KERN_WARNING "ioremap failed: sleep won't be possible");
+
+ /* Allocate room for PCI save */
+ pbook_alloc_pci_save();
+}
+
+static int powerbook_sleep_3400(void)
{
int ret, i, x;
unsigned int hid0;
unsigned long p;
struct adb_request sleep_req;
- void __iomem *mem_ctrl;
unsigned int __iomem *mem_ctrl_sleep;
- /* first map in the memory controller registers */
- mem_ctrl = ioremap(PB3400_MEM_CTRL, 0x100);
- if (mem_ctrl == NULL) {
- printk("powerbook_sleep_3400: ioremap failed\n");
+ if (pb3400_mem_ctrl == NULL)
return -ENOMEM;
- }
- mem_ctrl_sleep = mem_ctrl + PB3400_MEM_CTRL_SLEEP;
-
- /* Allocate room for PCI save */
- pbook_alloc_pci_save();
+ mem_ctrl_sleep = pb3400_mem_ctrl + PB3400_MEM_CTRL_SLEEP;
ret = pmac_suspend_devices();
if (ret) {
@@ -2343,8 +2357,6 @@ powerbook_sleep_3400(void)
mb();
pmac_wakeup_devices();
- pbook_free_pci_save();
- iounmap(mem_ctrl);
return 0;
}
^ permalink raw reply related
* How to Build Rootfile system
From: vinay kumar @ 2007-12-13 6:03 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 291 bytes --]
Hi All,
I have booted linux on PPC440GP with treeimage(zimage+initrd).
Now my next aim is to have a more stable rootfile system.
I wanted to know the procedure of building a root file system for PPC440GP
architecture.
Pls share your knowledge and also some links.
regards to all,
vinay
[-- Attachment #2: Type: text/html, Size: 329 bytes --]
^ permalink raw reply
* Re: [RFC] ehea: kdump support using new shutdown hook
From: Michael Ellerman @ 2007-12-13 6:30 UTC (permalink / raw)
To: Dave Jones
Cc: Michael Neuling, Jan-Bernd Themann, netdev, linux-kernel,
Thomas Klein, linux-ppc, Christoph Raisch, Paul Mackerras,
Marcus Eder, Stefan Roscher
In-Reply-To: <20071212170440.GD2359@redhat.com>
[-- Attachment #1: Type: text/plain, Size: 668 bytes --]
On Wed, 2007-12-12 at 12:04 -0500, Dave Jones wrote:
> On Wed, Dec 12, 2007 at 05:53:43PM +0100, Thomas Klein wrote:
>
> > +static void ehea_update_adapter_handles(struct ehea_adapter *adapter)
> > +{
> > + int i, k;
> > + int j = 0;
> > +
> > + memset(adapter->res_handles, sizeof(adapter->res_handles), 0);
>
> arguments wrong way around.
Remind me why bzero is deprecated again? :)
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [RFC] ehea: kdump support using new shutdown hook
From: Michael Ellerman @ 2007-12-13 6:41 UTC (permalink / raw)
To: Thomas Klein
Cc: Michael Neuling, Jan-Bernd Themann, netdev, linux-kernel,
linux-ppc, Christoph Raisch, Paul Mackerras, Marcus Eder,
Stefan Roscher
In-Reply-To: <200712121753.43543.osstklei@de.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 5607 bytes --]
On Wed, 2007-12-12 at 17:53 +0100, Thomas Klein wrote:
> This patch adds kdump support using the new PPC crash shutdown hook to the
> ehea driver. The driver now keeps a list of firmware handles which have to
> be freed in case of a crash. The crash handler does the minimum required: it
> frees the firmware resource handles plus broadcast/multicast registrations.
>
> Please comment.
Hi Thomas,
Here's a few ..
> ---
> diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea.h patched_kernel/drivers/net/ehea/ehea.h
> --- linux-2.6.24-rc5/drivers/net/ehea/ehea.h 2007-12-11 04:48:43.000000000 +0100
> +++ patched_kernel/drivers/net/ehea/ehea.h 2007-12-12 17:30:53.000000000 +0100
> @@ -386,6 +386,7 @@ struct ehea_port_res {
>
>
> #define EHEA_MAX_PORTS 16
> +#define EHEA_MAX_RES_HANDLES (100 * EHEA_MAX_PORTS + 10)
> struct ehea_adapter {
> u64 handle;
> struct of_device *ofdev;
> @@ -397,6 +398,7 @@ struct ehea_adapter {
> u64 max_mc_mac; /* max number of multicast mac addresses */
> int active_ports;
> struct list_head list;
> + u64 res_handles[EHEA_MAX_RES_HANDLES];
> };
I don't like this ..
> diff -Nurp -X dontdiff linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c patched_kernel/drivers/net/ehea/ehea_main.c
> --- linux-2.6.24-rc5/drivers/net/ehea/ehea_main.c 2007-12-11 04:48:43.000000000 +0100
> +++ patched_kernel/drivers/net/ehea/ehea_main.c 2007-12-12 17:30:53.000000000 +0100
> @@ -35,6 +35,7 @@
> #include <linux/if_ether.h>
> #include <linux/notifier.h>
> #include <linux/reboot.h>
> +#include <asm-powerpc/kexec.h>
Just <asm/kexec.h>
> @@ -3302,6 +3333,71 @@ static int __devexit ehea_remove(struct
> return 0;
> }
>
> +void ehea_crash_deregister(void)
> +{
> + struct ehea_adapter *adapter;
> + int i;
> + u64 hret;
> + u8 reg_type;
> +
> + list_for_each_entry(adapter, &adapter_list, list) {
> + for (i = 0; i < EHEA_MAX_PORTS; i++) {
> + struct ehea_port *port = adapter->port[i];
> + if (port->state == EHEA_PORT_UP) {
> + struct ehea_mc_list *mc_entry = port->mc_list;
> + struct list_head *pos;
> + struct list_head *temp;
> +
> + /* Undo multicast registrations */
> + list_for_each_safe(pos, temp,
> + &(port->mc_list->list)) {
> + mc_entry = list_entry(pos,
> + struct ehea_mc_list,
> + list);
> + ehea_multicast_reg_helper(port,
> + mc_entry->macaddr,
> + H_DEREG_BCMC);
> + }
> +
> + /* Undo broad registration */
> + reg_type = EHEA_BCMC_BROADCAST |
> + EHEA_BCMC_UNTAGGED;
> + ehea_h_reg_dereg_bcmc(port->adapter->handle,
> + port->logical_port_id,
> + reg_type, port->mac_addr,
> + 0, H_DEREG_BCMC);
> +
> + reg_type = EHEA_BCMC_BROADCAST |
> + EHEA_BCMC_VLANID_ALL;
> + ehea_h_reg_dereg_bcmc(port->adapter->handle,
> + port->logical_port_id,
> + reg_type, port->mac_addr,
> + 0, H_DEREG_BCMC);
> + }
> + }
> + for (i = 0; i < EHEA_MAX_RES_HANDLES; i++) {
> + u64 handle = adapter->res_handles[i];
> + if (handle) {
> + hret = ehea_h_free_resource(adapter->handle,
> + handle,
> + FORCE_FREE);
> + }
> + }
> +
> + if (adapter->neq) {
> + hret = ehea_h_free_resource(adapter->handle,
> + adapter->neq->fw_handle,
> + FORCE_FREE);
> + }
> +
> + if (adapter->mr.handle) {
> + hret = ehea_h_free_resource(adapter->handle,
> + adapter->mr.handle,
> + FORCE_FREE);
> + }
> + }
> +}
This is sort of on the right track, I like that the ehea_h_.. routines
are basically just hypercalls, but there's a few things wrong. You're
walking a linked list, which is asking for trouble, if a single pointer
is corrupted you'll walk off into lala land. Then you're pulling fields
out of structs via pointers, again hoping that they're all valid. Then
you walk another linked list .. And then you're pulling bits out of the
adapter again.
Ideally it would look like this:
static u64 things_to_free[];
void ehea_crash_deregister(void)
{
for (i = 0; i < num_things_to_free; i++)
h_call_free_a_thing(things_to_free[i]);
}
> static int ehea_reboot_notifier(struct notifier_block *nb,
> unsigned long action, void *unused)
> {
> @@ -3373,6 +3469,9 @@ int __init ehea_module_init(void)
> goto out;
>
> register_reboot_notifier(&ehea_reboot_nb);
> + ret = crash_shutdown_register(&ehea_crash_deregister);
> + if (ret)
> + ehea_info("failed registering crash handler");
Your naming is a little confusing here, you're registering the
deregister function. I think I get it, you're unregistering the fw
handles, but perhaps ehea_crash_shutdown() would be clearer.
> @@ -3396,10 +3496,15 @@ out:
>
> static void __exit ehea_module_exit(void)
> {
> + int ret;
> +
> flush_scheduled_work();
> driver_remove_file(&ehea_driver.driver, &driver_attr_capabilities);
> ibmebus_unregister_driver(&ehea_driver);
> unregister_reboot_notifier(&ehea_reboot_nb);
> + ret = crash_shutdown_unregister(&ehea_crash_deregister);
> + if (ret)
> + ehea_info("failed unregistering crash handler");
You don't need ret if that's all you're going to do with it.
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] Introduce driver_create/remove_dir
From: Greg KH @ 2007-12-13 7:10 UTC (permalink / raw)
To: Stephen Rothwell
Cc: linux-kernel, David Gibson, linuxppc-dev, Kyle A. Lucke, paulus
In-Reply-To: <20071212105633.725496cb.sfr@canb.auug.org.au>
On Wed, Dec 12, 2007 at 10:56:33AM +1100, Stephen Rothwell wrote:
>
> Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
> ---
> drivers/base/driver.c | 24 ++++++++++++++++++++++++
> drivers/net/iseries_veth.c | 15 +++++++--------
> include/linux/device.h | 3 +++
> 3 files changed, 34 insertions(+), 8 deletions(-)
>
> Greg, does this look like a reasonable solution to iseries_veth accessing
> the "private" kobject in struct device_driver? This version is against
> maimline, but the stuff you have in mm would just need to update
> driver_create_dir ...
Hm, we just want to be able to get to the kobject somehow here. Not
create a new api that doesn't match up. I'll think about it and figure
something that matches the other portions of the api.
> Also something along the lines of device_add_dir() might be good if you
> want to hide the kobject in struct device as well.
As devices _should_ always be dynamic, hopefully I'll not have to do
that. But knowing some of the platform devices, I'm afraid I'll have to
do that split :)
thanks,
greg k-h
^ permalink raw reply
* Re: drivers/net/iseries_veth.c dubious sysfs usage
From: Greg KH @ 2007-12-13 7:08 UTC (permalink / raw)
To: Michael Ellerman
Cc: linuxppc-dev, Kyle A. Lucke, paulus, linux-kernel, David Gibson
In-Reply-To: <1196912898.14754.13.camel@concordia>
On Thu, Dec 06, 2007 at 02:48:18PM +1100, Michael Ellerman wrote:
> igoeast:~# cd /sys/class/net/eth1/
> igoeast:/sys/class/net/eth1# ls -la
> total 0
> drwxr-xr-x 4 root root 0 Dec 6 10:22 .
> drwxr-xr-x 6 root root 0 Dec 6 10:21 ..
> -r--r--r-- 1 root root 4096 Dec 6 10:30 addr_len
> -r--r--r-- 1 root root 4096 Dec 6 10:30 address
> -r--r--r-- 1 root root 4096 Dec 6 10:30 broadcast
> -r--r--r-- 1 root root 4096 Dec 6 10:30 carrier
> lrwxrwxrwx 1 root root 0 Dec 6 10:22 device -> ../../../devices/vio/3
> -r--r--r-- 1 root root 4096 Dec 6 10:30 dormant
> -r--r--r-- 1 root root 4096 Dec 6 10:30 features
> -rw-r--r-- 1 root root 4096 Dec 6 10:30 flags
> -r--r--r-- 1 root root 4096 Dec 6 10:30 ifindex
> -r--r--r-- 1 root root 4096 Dec 6 10:30 iflink
> -r--r--r-- 1 root root 4096 Dec 6 10:30 link_mode
> -rw-r--r-- 1 root root 4096 Dec 6 10:30 mtu
> -r--r--r-- 1 root root 4096 Dec 6 10:30 operstate
> drwxr-xr-x 2 root root 0 Dec 6 10:30 statistics
> lrwxrwxrwx 1 root root 0 Dec 6 10:30 subsystem -> ../../../class/net
> -rw-r--r-- 1 root root 4096 Dec 6 10:30 tx_queue_len
> -r--r--r-- 1 root root 4096 Dec 6 10:30 type
> -rw-r--r-- 1 root root 4096 Dec 6 10:30 uevent
> drwxr-xr-x 2 root root 0 Dec 6 10:30 veth_port
>
> Each net device has a port structure associated with it, the fields
> should be fairly self explanatory, they're all read only I think.
>
> igoeast:/sys/class/net/eth1# find veth_port/
> veth_port/
> veth_port/mac_addr
> veth_port/lpar_map
> veth_port/stopped_map
> veth_port/promiscuous
> veth_port/num_mcast
That's fine, I'll let you fight with the network people over that :)
> igoeast:/sys/class/net/eth1# cd device/driver
>
> igoeast:/sys/class/net/eth1/device/driver# ls -l
> total 0
> lrwxrwxrwx 1 root root 0 Dec 6 10:21 2 -> ../../../../devices/vio/2
> lrwxrwxrwx 1 root root 0 Dec 6 10:21 3 -> ../../../../devices/vio/3
> --w------- 1 root root 4096 Dec 6 10:21 bind
> drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx00
> drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx02
> drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx03
> drwxr-xr-x 2 root root 0 Dec 6 10:21 cnx04
> lrwxrwxrwx 1 root root 0 Dec 6 10:21 module -> ../../../../module/iseries_veth
> --w------- 1 root root 4096 Dec 6 10:21 uevent
> --w------- 1 root root 4096 Dec 6 10:21 unbind
>
> The driver has a connection to all the other lpars, this is entirely
> independent of the net devices.
>
> igoeast:/sys/class/net/eth1/device/driver# find cnx00/
> cnx00/
> cnx00/outstanding_tx
> cnx00/remote_lp
> cnx00/num_events
> cnx00/reset_timeout
> cnx00/last_contact
> cnx00/state
> cnx00/src_inst
> cnx00/dst_inst
> cnx00/num_pending_acks
> cnx00/num_ack_events
> cnx00/ack_timeout
Hm, ok, it's odd as you are the only driver in the whole tree doing
something like this, but it seems semi-resonable, so I can't complain :)
I'll fix the core up to allow you to do this, thanks for the
explanation.
greg k-h
^ permalink raw reply
* [PATCH 1/20] [POWERPC] Reworking machine check handling and Fix 440/440A
From: Benjamin Herrenschmidt @ 2007-12-13 7:38 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
This adds a cputable function pointer for the CPU-side machine
check handling. The semantic is still the same as the old one,
the one in ppc_md. overrides the one in cputable, though
ultimately we'll want to change that so the CPU gets first.
This removes CONFIG_440A which was a problem for multiplatform
kernels and instead fixes up the IVOR at runtime from a setup_cpu
function. The "A" version of the machine check also tweaks the
regs->trap value to differenciate the 2 versions at the C level.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
arch/powerpc/kernel/cpu_setup_44x.S | 9 +++
arch/powerpc/kernel/cputable.c | 105 ++++++++++++++++++++++++++++++++++++
arch/powerpc/kernel/head_44x.S | 14 +++-
arch/powerpc/kernel/head_booke.h | 2
arch/powerpc/kernel/traps.c | 62 ++++++++++++++++-----
arch/powerpc/platforms/44x/Kconfig | 5 -
arch/ppc/kernel/traps.c | 98 ++++++++++++++++++++++-----------
include/asm-powerpc/cputable.h | 13 ++++
include/asm-powerpc/ptrace.h | 3 -
include/asm-powerpc/reg_booke.h | 3 -
include/asm-ppc/reg_booke.h | 2
11 files changed, 258 insertions(+), 58 deletions(-)
--- linux-merge.orig/arch/powerpc/kernel/cpu_setup_44x.S 2007-10-15 11:19:35.000000000 +1000
+++ linux-merge/arch/powerpc/kernel/cpu_setup_44x.S 2007-12-11 16:11:27.000000000 +1100
@@ -23,11 +23,20 @@ _GLOBAL(__setup_cpu_440epx)
mflr r4
bl __init_fpu_44x
bl __plb_disable_wrp
+ bl __fixup_440A_mcheck
mtlr r4
blr
_GLOBAL(__setup_cpu_440grx)
b __plb_disable_wrp
+_GLOBAL(__setup_cpu_440gx)
+_GLOBAL(__setup_cpu_440spe)
+ b __fixup_440A_mcheck
+ /* Temporary fixup for arch/ppc until we kill the whole thing */
+#ifndef CONFIG_PPC_MERGE
+_GLOBAL(__fixup_440A_mcheck)
+ blr
+#endif
/* enable APU between CPU and FPU */
_GLOBAL(__init_fpu_44x)
Index: linux-merge/arch/powerpc/kernel/cputable.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/cputable.c 2007-11-13 11:39:44.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/cputable.c 2007-12-11 16:11:27.000000000 +1100
@@ -33,7 +33,9 @@ EXPORT_SYMBOL(cur_cpu_spec);
#ifdef CONFIG_PPC32
extern void __setup_cpu_440ep(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440epx(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_440gx(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_440grx(unsigned long offset, struct cpu_spec* spec);
+extern void __setup_cpu_440spe(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_603(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_604(unsigned long offset, struct cpu_spec* spec);
extern void __setup_cpu_750(unsigned long offset, struct cpu_spec* spec);
@@ -85,6 +87,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/power3",
.oprofile_type = PPC_OPROFILE_RS64,
+ .machine_check = machine_check_generic,
.platform = "power3",
},
{ /* Power3+ */
@@ -99,6 +102,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/power3",
.oprofile_type = PPC_OPROFILE_RS64,
+ .machine_check = machine_check_generic,
.platform = "power3",
},
{ /* Northstar */
@@ -113,6 +117,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
+ .machine_check = machine_check_generic,
.platform = "rs64",
},
{ /* Pulsar */
@@ -127,6 +132,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
+ .machine_check = machine_check_generic,
.platform = "rs64",
},
{ /* I-star */
@@ -141,6 +147,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
+ .machine_check = machine_check_generic,
.platform = "rs64",
},
{ /* S-star */
@@ -155,6 +162,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/rs64",
.oprofile_type = PPC_OPROFILE_RS64,
+ .machine_check = machine_check_generic,
.platform = "rs64",
},
{ /* Power4 */
@@ -169,6 +177,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/power4",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "power4",
},
{ /* Power4+ */
@@ -183,6 +192,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/power4",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "power4",
},
{ /* PPC970 */
@@ -200,6 +210,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_restore = __restore_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "ppc970",
},
{ /* PPC970FX */
@@ -217,6 +228,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_restore = __restore_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "ppc970",
},
{ /* PPC970MP DD1.0 - no DEEPNAP, use regular 970 init */
@@ -234,6 +246,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_restore = __restore_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970MP",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "ppc970",
},
{ /* PPC970MP */
@@ -251,6 +264,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_restore = __restore_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970MP",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "ppc970",
},
{ /* PPC970GX */
@@ -267,6 +281,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_ppc970,
.oprofile_cpu_type = "ppc64/970",
.oprofile_type = PPC_OPROFILE_POWER4,
+ .machine_check = machine_check_generic,
.platform = "ppc970",
},
{ /* Power5 GR */
@@ -286,6 +301,7 @@ static struct cpu_spec __initdata cpu_sp
*/
.oprofile_mmcra_sihv = MMCRA_SIHV,
.oprofile_mmcra_sipr = MMCRA_SIPR,
+ .machine_check = machine_check_generic,
.platform = "power5",
},
{ /* Power5++ */
@@ -301,6 +317,7 @@ static struct cpu_spec __initdata cpu_sp
.oprofile_type = PPC_OPROFILE_POWER4,
.oprofile_mmcra_sihv = MMCRA_SIHV,
.oprofile_mmcra_sipr = MMCRA_SIPR,
+ .machine_check = machine_check_generic,
.platform = "power5+",
},
{ /* Power5 GS */
@@ -317,6 +334,7 @@ static struct cpu_spec __initdata cpu_sp
.oprofile_type = PPC_OPROFILE_POWER4,
.oprofile_mmcra_sihv = MMCRA_SIHV,
.oprofile_mmcra_sipr = MMCRA_SIPR,
+ .machine_check = machine_check_generic,
.platform = "power5+",
},
{ /* POWER6 in P5+ mode; 2.04-compliant processor */
@@ -327,6 +345,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_POWER5_PLUS,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .machine_check = machine_check_generic,
.platform = "power5+",
},
{ /* Power6 */
@@ -346,6 +365,7 @@ static struct cpu_spec __initdata cpu_sp
.oprofile_mmcra_sipr = POWER6_MMCRA_SIPR,
.oprofile_mmcra_clear = POWER6_MMCRA_THRM |
POWER6_MMCRA_OTHER,
+ .machine_check = machine_check_generic,
.platform = "power6x",
},
{ /* 2.05-compliant processor, i.e. Power6 "architected" mode */
@@ -356,6 +376,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_POWER6,
.icache_bsize = 128,
.dcache_bsize = 128,
+ .machine_check = machine_check_generic,
.platform = "power6",
},
{ /* Cell Broadband Engine */
@@ -372,6 +393,7 @@ static struct cpu_spec __initdata cpu_sp
.pmc_type = PPC_PMC_IBM,
.oprofile_cpu_type = "ppc64/cell-be",
.oprofile_type = PPC_OPROFILE_CELL,
+ .machine_check = machine_check_generic,
.platform = "ppc-cell-be",
},
{ /* PA Semi PA6T */
@@ -388,6 +410,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_restore = __restore_cpu_pa6t,
.oprofile_cpu_type = "ppc64/pa6t",
.oprofile_type = PPC_OPROFILE_PA6T,
+ .machine_check = machine_check_generic,
.platform = "pa6t",
},
{ /* default match */
@@ -400,6 +423,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 128,
.num_pmcs = 6,
.pmc_type = PPC_PMC_IBM,
+ .machine_check = machine_check_generic,
.platform = "power4",
}
#endif /* CONFIG_PPC64 */
@@ -414,6 +438,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_UNIFIED_CACHE | PPC_FEATURE_NO_TB,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_generic,
.platform = "ppc601",
},
{ /* 603 */
@@ -425,6 +450,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* 603e */
@@ -436,6 +462,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* 603ev */
@@ -447,6 +474,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* 604 */
@@ -459,6 +487,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 2,
.cpu_setup = __setup_cpu_604,
+ .machine_check = machine_check_generic,
.platform = "ppc604",
},
{ /* 604e */
@@ -471,6 +500,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_604,
+ .machine_check = machine_check_generic,
.platform = "ppc604",
},
{ /* 604r */
@@ -483,6 +513,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_604,
+ .machine_check = machine_check_generic,
.platform = "ppc604",
},
{ /* 604ev */
@@ -495,6 +526,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_604,
+ .machine_check = machine_check_generic,
.platform = "ppc604",
},
{ /* 740/750 (0x4202, don't support TAU ?) */
@@ -507,6 +539,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750CX (80100 and 8010x?) */
@@ -519,6 +552,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750CX (82201 and 82202) */
@@ -531,6 +565,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750CXe (82214) */
@@ -543,6 +578,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750CXe "Gekko" (83214) */
@@ -555,6 +591,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750cx,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750CL */
@@ -567,6 +604,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 745/755 */
@@ -579,6 +617,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750FX rev 1.x */
@@ -591,6 +630,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750FX rev 2.0 must disable HID0[DPM] */
@@ -603,6 +643,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750FX (All revs except 2.0) */
@@ -615,6 +656,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750fx,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 750GX */
@@ -627,6 +669,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750fx,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 740/750 (L2CR bit need fixup for 740) */
@@ -639,6 +682,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_750,
+ .machine_check = machine_check_generic,
.platform = "ppc750",
},
{ /* 7400 rev 1.1 ? (no TAU) */
@@ -652,6 +696,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_7400,
+ .machine_check = machine_check_generic,
.platform = "ppc7400",
},
{ /* 7400 */
@@ -665,6 +710,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_7400,
+ .machine_check = machine_check_generic,
.platform = "ppc7400",
},
{ /* 7410 */
@@ -678,6 +724,7 @@ static struct cpu_spec __initdata cpu_sp
.dcache_bsize = 32,
.num_pmcs = 4,
.cpu_setup = __setup_cpu_7410,
+ .machine_check = machine_check_generic,
.platform = "ppc7400",
},
{ /* 7450 2.0 - no doze/nap */
@@ -693,6 +740,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7450 2.1 */
@@ -708,6 +756,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7450 2.3 and newer */
@@ -723,6 +772,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7455 rev 1.x */
@@ -738,6 +788,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7455 rev 2.0 */
@@ -753,6 +804,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7455 others */
@@ -768,6 +820,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7447/7457 Rev 1.0 */
@@ -783,6 +836,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7447/7457 Rev 1.1 */
@@ -798,6 +852,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7447/7457 Rev 1.2 and later */
@@ -812,6 +867,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7447A */
@@ -827,6 +883,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 7448 */
@@ -842,6 +899,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_setup = __setup_cpu_745x,
.oprofile_cpu_type = "ppc/7450",
.oprofile_type = PPC_OPROFILE_G4,
+ .machine_check = machine_check_generic,
.platform = "ppc7450",
},
{ /* 82xx (8240, 8245, 8260 are all 603e cores) */
@@ -853,6 +911,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* All G2_LE (603e core, plus some) have the same pvr */
@@ -864,6 +923,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* e300c1 (a 603e core, plus some) on 83xx */
@@ -875,6 +935,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* e300c2 (an e300c1 core, plus some, minus FPU) on 83xx */
@@ -886,6 +947,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* e300c3 on 83xx */
@@ -897,6 +959,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_603,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
{ /* default match, we assume split I/D cache & TB (non-601)... */
@@ -907,6 +970,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_generic,
.platform = "ppc603",
},
#endif /* CLASSIC_PPC */
@@ -933,6 +997,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .machine_check = machine_check_4xx,
.platform = "ppc403",
},
{ /* 403GCX */
@@ -944,6 +1009,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_NO_TB,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .machine_check = machine_check_4xx,
.platform = "ppc403",
},
{ /* 403G ?? */
@@ -954,6 +1020,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 16,
.dcache_bsize = 16,
+ .machine_check = machine_check_4xx,
.platform = "ppc403",
},
{ /* 405GP */
@@ -965,6 +1032,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* STB 03xxx */
@@ -976,6 +1044,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* STB 04xxx */
@@ -987,6 +1056,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* NP405L */
@@ -998,6 +1068,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* NP4GS3 */
@@ -1009,6 +1080,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* NP405H */
@@ -1020,6 +1092,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* 405GPr */
@@ -1031,6 +1104,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* STBx25xx */
@@ -1042,6 +1116,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* 405LP */
@@ -1052,6 +1127,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = PPC_FEATURE_32 | PPC_FEATURE_HAS_MMU,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* Xilinx Virtex-II Pro */
@@ -1063,6 +1139,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* Xilinx Virtex-4 FX */
@@ -1074,6 +1151,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* 405EP */
@@ -1085,6 +1163,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
{ /* 405EX */
@@ -1096,6 +1175,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_MMU | PPC_FEATURE_HAS_4xxMAC,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc405",
},
@@ -1109,6 +1189,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc440",
},
{ /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
@@ -1120,6 +1201,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_440ep,
+ .machine_check = machine_check_4xx,
.platform = "ppc440",
},
{
@@ -1130,6 +1212,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE | PPC_FEATURE_HAS_FPU,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc440",
},
{ /* Use logical PVR for 440EP (logical pvr = pvr | 0x8) */
@@ -1141,6 +1224,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_440ep,
+ .machine_check = machine_check_4xx,
.platform = "ppc440",
},
{ /* 440GRX */
@@ -1152,6 +1236,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_440grx,
+ .machine_check = machine_check_4xx,
.platform = "ppc440",
},
{ /* Use logical PVR for 440EPx (logical pvr = pvr | 0x8) */
@@ -1163,6 +1248,7 @@ static struct cpu_spec __initdata cpu_sp
.icache_bsize = 32,
.dcache_bsize = 32,
.cpu_setup = __setup_cpu_440epx,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 440GP Rev. B */
@@ -1173,6 +1259,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc440gp",
},
{ /* 440GP Rev. C */
@@ -1183,6 +1270,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc440gp",
},
{ /* 440GX Rev. A */
@@ -1193,6 +1281,8 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 440GX Rev. B */
@@ -1203,6 +1293,8 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 440GX Rev. C */
@@ -1213,6 +1305,8 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 440GX Rev. F */
@@ -1223,6 +1317,8 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440gx,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 440SP Rev. A */
@@ -1233,6 +1329,7 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .machine_check = machine_check_4xx,
.platform = "ppc440",
},
{ /* 440SPe Rev. A */
@@ -1243,6 +1340,8 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440spe,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
{ /* 440SPe Rev. B */
@@ -1253,6 +1352,8 @@ static struct cpu_spec __initdata cpu_sp
.cpu_user_features = COMMON_USER_BOOKE,
.icache_bsize = 32,
.dcache_bsize = 32,
+ .cpu_setup = __setup_cpu_440spe,
+ .machine_check = machine_check_440A,
.platform = "ppc440",
},
#endif /* CONFIG_44x */
@@ -1267,6 +1368,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_EFP_SINGLE |
PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32,
+ .machine_check = machine_check_e200,
.platform = "ppc5554",
},
{ /* e200z6 */
@@ -1280,6 +1382,7 @@ static struct cpu_spec __initdata cpu_sp
PPC_FEATURE_HAS_EFP_SINGLE_COMP |
PPC_FEATURE_UNIFIED_CACHE,
.dcache_bsize = 32,
+ .machine_check = machine_check_e200,
.platform = "ppc5554",
},
{ /* e500 */
@@ -1296,6 +1399,7 @@ static struct cpu_spec __initdata cpu_sp
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
.oprofile_type = PPC_OPROFILE_BOOKE,
+ .machine_check = machine_check_e500,
.platform = "ppc8540",
},
{ /* e500v2 */
@@ -1313,6 +1417,7 @@ static struct cpu_spec __initdata cpu_sp
.num_pmcs = 4,
.oprofile_cpu_type = "ppc/e500",
.oprofile_type = PPC_OPROFILE_BOOKE,
+ .machine_check = machine_check_e500,
.platform = "ppc8548",
},
#endif
Index: linux-merge/arch/powerpc/kernel/head_44x.S
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/head_44x.S 2007-12-11 15:07:22.000000000 +1100
+++ linux-merge/arch/powerpc/kernel/head_44x.S 2007-12-11 16:11:27.000000000 +1100
@@ -289,11 +289,8 @@ interrupt_base:
CRITICAL_EXCEPTION(0x0100, CriticalInput, unknown_exception)
/* Machine Check Interrupt */
-#ifdef CONFIG_440A
- MCHECK_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#else
CRITICAL_EXCEPTION(0x0200, MachineCheck, machine_check_exception)
-#endif
+ MCHECK_EXCEPTION(0x0210, MachineCheckA, machine_check_exception)
/* Data Storage Interrupt */
START_EXCEPTION(DataStorage)
@@ -674,6 +671,15 @@ finish_tlb_load:
*/
/*
+ * Adjust the machine check IVOR on 440A cores
+ */
+_GLOBAL(__fixup_440A_mcheck)
+ li r3,MachineCheckA@l
+ mtspr SPRN_IVOR1,r3
+ sync
+ blr
+
+/*
* extern void giveup_altivec(struct task_struct *prev)
*
* The 44x core does not have an AltiVec unit.
Index: linux-merge/arch/powerpc/kernel/traps.c
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/traps.c 2007-10-25 13:15:47.000000000 +1000
+++ linux-merge/arch/powerpc/kernel/traps.c 2007-12-11 16:11:27.000000000 +1100
@@ -334,18 +334,25 @@ static inline int check_io_access(struct
#define clear_single_step(regs) ((regs)->msr &= ~MSR_SE)
#endif
-static int generic_machine_check_exception(struct pt_regs *regs)
+#if defined(CONFIG_4xx)
+int machine_check_4xx(struct pt_regs *regs)
{
unsigned long reason = get_mc_reason(regs);
-#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
if (reason & ESR_IMCP) {
printk("Instruction");
mtspr(SPRN_ESR, reason & ~ESR_IMCP);
} else
printk("Data");
printk(" machine check in kernel mode.\n");
-#elif defined(CONFIG_440A)
+
+ return 0;
+}
+
+int machine_check_440A(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
if (reason & ESR_IMCP){
printk("Instruction Synchronous Machine Check exception\n");
@@ -375,7 +382,13 @@ static int generic_machine_check_excepti
/* Clear MCSR */
mtspr(SPRN_MCSR, mcsr);
}
-#elif defined (CONFIG_E500)
+ return 0;
+}
+#elif defined(CONFIG_E500)
+int machine_check_e500(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
@@ -403,7 +416,14 @@ static int generic_machine_check_excepti
printk("Bus - Instruction Parity Error\n");
if (reason & MCSR_BUS_RPERR)
printk("Bus - Read Parity Error\n");
-#elif defined (CONFIG_E200)
+
+ return 0;
+}
+#elif defined(CONFIG_E200)
+int machine_check_e200(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
@@ -421,7 +441,14 @@ static int generic_machine_check_excepti
printk("Bus - Read Bus Error on data load\n");
if (reason & MCSR_BUS_WRERR)
printk("Bus - Write Bus Error on buffered store or cache line push\n");
-#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
+
+ return 0;
+}
+#else
+int machine_check_generic(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from SRR1=%lx): ", reason);
switch (reason & 0x601F0000) {
@@ -451,22 +478,26 @@ static int generic_machine_check_excepti
default:
printk("Unknown values in msr\n");
}
-#endif /* CONFIG_4xx */
-
return 0;
}
+#endif /* everything else */
void machine_check_exception(struct pt_regs *regs)
{
int recover = 0;
- /* See if any machine dependent calls */
+ /* See if any machine dependent calls. In theory, we would want
+ * to call the CPU first, and call the ppc_md. one if the CPU
+ * one returns a positive number. However there is existing code
+ * that assumes the board gets a first chance, so let's keep it
+ * that way for now and fix things later. --BenH.
+ */
if (ppc_md.machine_check_exception)
recover = ppc_md.machine_check_exception(regs);
- else
- recover = generic_machine_check_exception(regs);
+ else if (cur_cpu_spec->machine_check)
+ recover = cur_cpu_spec->machine_check(regs);
- if (recover)
+ if (recover > 0)
return;
if (user_mode(regs)) {
@@ -476,7 +507,12 @@ void machine_check_exception(struct pt_r
}
#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
- /* the qspan pci read routines can cause machine checks -- Cort */
+ /* the qspan pci read routines can cause machine checks -- Cort
+ *
+ * yuck !!! that totally needs to go away ! There are better ways
+ * to deal with that than having a wart in the mcheck handler.
+ * -- BenH
+ */
bad_page_fault(regs, regs->dar, SIGBUS);
return;
#endif
Index: linux-merge/arch/powerpc/platforms/44x/Kconfig
===================================================================
--- linux-merge.orig/arch/powerpc/platforms/44x/Kconfig 2007-10-25 13:15:47.000000000 +1000
+++ linux-merge/arch/powerpc/platforms/44x/Kconfig 2007-12-11 16:11:27.000000000 +1100
@@ -62,11 +62,6 @@ config 440GX
config 440SP
bool
-config 440A
- bool
- depends on 440GX || 440EPX
- default y
-
# 44x errata/workaround config symbols, selected by the CPU models above
config IBM440EP_ERR42
bool
Index: linux-merge/arch/powerpc/kernel/head_booke.h
===================================================================
--- linux-merge.orig/arch/powerpc/kernel/head_booke.h 2007-07-27 13:44:42.000000000 +1000
+++ linux-merge/arch/powerpc/kernel/head_booke.h 2007-12-11 16:11:27.000000000 +1100
@@ -166,7 +166,7 @@ label:
mfspr r5,SPRN_ESR; \
stw r5,_ESR(r11); \
addi r3,r1,STACK_FRAME_OVERHEAD; \
- EXC_XFER_TEMPLATE(hdlr, n+2, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
+ EXC_XFER_TEMPLATE(hdlr, n+4, (MSR_KERNEL & ~(MSR_ME|MSR_DE|MSR_CE)), \
NOCOPY, mcheck_transfer_to_handler, \
ret_from_mcheck_exc)
Index: linux-merge/include/asm-powerpc/ptrace.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/ptrace.h 2007-09-28 11:42:10.000000000 +1000
+++ linux-merge/include/asm-powerpc/ptrace.h 2007-12-11 16:11:27.000000000 +1100
@@ -106,7 +106,8 @@ extern int ptrace_put_reg(struct task_st
*/
#define FULL_REGS(regs) (((regs)->trap & 1) == 0)
#ifndef __powerpc64__
-#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) == 0)
+#define IS_CRITICAL_EXC(regs) (((regs)->trap & 2) != 0)
+#define IS_MCHECK_EXC(regs) (((regs)->trap & 4) != 0)
#endif /* ! __powerpc64__ */
#define TRAP(regs) ((regs)->trap & ~0xF)
#ifdef __powerpc64__
Index: linux-merge/include/asm-powerpc/reg_booke.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/reg_booke.h 2007-09-28 11:42:10.000000000 +1000
+++ linux-merge/include/asm-powerpc/reg_booke.h 2007-12-11 16:11:27.000000000 +1100
@@ -207,7 +207,6 @@
#define CCR1_TCS 0x00000080 /* Timer Clock Select */
/* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
#define MCSR_MCS 0x80000000 /* Machine Check Summary */
#define MCSR_IB 0x40000000 /* Instruction PLB Error */
#define MCSR_DRB 0x20000000 /* Data Read PLB Error */
@@ -217,7 +216,7 @@
#define MCSR_DCSP 0x02000000 /* D-Cache Search Parity Error */
#define MCSR_DCFP 0x01000000 /* D-Cache Flush Parity Error */
#define MCSR_IMPE 0x00800000 /* Imprecise Machine Check Exception */
-#endif
+
#ifdef CONFIG_E500
#define MCSR_MCP 0x80000000UL /* Machine Check Input Pin */
#define MCSR_ICPERR 0x40000000UL /* I-Cache Parity Error */
Index: linux-merge/include/asm-powerpc/cputable.h
===================================================================
--- linux-merge.orig/include/asm-powerpc/cputable.h 2007-11-27 18:25:29.000000000 +1100
+++ linux-merge/include/asm-powerpc/cputable.h 2007-12-11 16:11:27.000000000 +1100
@@ -57,6 +57,14 @@ enum powerpc_pmc_type {
PPC_PMC_PA6T = 2,
};
+struct pt_regs;
+
+extern int machine_check_generic(struct pt_regs *regs);
+extern int machine_check_4xx(struct pt_regs *regs);
+extern int machine_check_440A(struct pt_regs *regs);
+extern int machine_check_e500(struct pt_regs *regs);
+extern int machine_check_e200(struct pt_regs *regs);
+
/* NOTE WELL: Update identify_cpu() if fields are added or removed! */
struct cpu_spec {
/* CPU is matched via (PVR & pvr_mask) == pvr_value */
@@ -97,6 +105,11 @@ struct cpu_spec {
/* Name of processor class, for the ELF AT_PLATFORM entry */
char *platform;
+
+ /* Processor specific machine check handling. Return negative
+ * if the error is fatal, 1 if it was fully recovered and 0 to
+ * pass up (not CPU originated) */
+ int (*machine_check)(struct pt_regs *regs);
};
extern struct cpu_spec *cur_cpu_spec;
Index: linux-merge/arch/ppc/kernel/traps.c
===================================================================
--- linux-merge.orig/arch/ppc/kernel/traps.c 2007-12-11 16:11:45.000000000 +1100
+++ linux-merge/arch/ppc/kernel/traps.c 2007-12-11 16:23:35.000000000 +1100
@@ -231,39 +231,25 @@ platform_machine_check(struct pt_regs *r
{
}
-void machine_check_exception(struct pt_regs *regs)
+#if defined(CONFIG_4xx)
+int machine_check_4xx(struct pt_regs *regs)
{
unsigned long reason = get_mc_reason(regs);
- if (user_mode(regs)) {
- regs->msr |= MSR_RI;
- _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
- return;
- }
-
-#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
- /* the qspan pci read routines can cause machine checks -- Cort */
- bad_page_fault(regs, regs->dar, SIGBUS);
- return;
-#endif
-
- if (debugger_fault_handler) {
- debugger_fault_handler(regs);
- regs->msr |= MSR_RI;
- return;
- }
-
- if (check_io_access(regs))
- return;
-
-#if defined(CONFIG_4xx) && !defined(CONFIG_440A)
if (reason & ESR_IMCP) {
printk("Instruction");
mtspr(SPRN_ESR, reason & ~ESR_IMCP);
} else
printk("Data");
printk(" machine check in kernel mode.\n");
-#elif defined(CONFIG_440A)
+
+ return 0;
+}
+
+int machine_check_440A(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
if (reason & ESR_IMCP){
printk("Instruction Synchronous Machine Check exception\n");
@@ -293,7 +279,13 @@ void machine_check_exception(struct pt_r
/* Clear MCSR */
mtspr(SPRN_MCSR, mcsr);
}
-#elif defined (CONFIG_E500)
+ return 0;
+}
+#elif defined(CONFIG_E500)
+int machine_check_e500(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
@@ -305,8 +297,6 @@ void machine_check_exception(struct pt_r
printk("Data Cache Push Parity Error\n");
if (reason & MCSR_DCPERR)
printk("Data Cache Parity Error\n");
- if (reason & MCSR_GL_CI)
- printk("Guarded Load or Cache-Inhibited stwcx.\n");
if (reason & MCSR_BUS_IAERR)
printk("Bus - Instruction Address Error\n");
if (reason & MCSR_BUS_RAERR)
@@ -318,12 +308,19 @@ void machine_check_exception(struct pt_r
if (reason & MCSR_BUS_RBERR)
printk("Bus - Read Data Bus Error\n");
if (reason & MCSR_BUS_WBERR)
- printk("Bus - Write Data Bus Error\n");
+ printk("Bus - Read Data Bus Error\n");
if (reason & MCSR_BUS_IPERR)
printk("Bus - Instruction Parity Error\n");
if (reason & MCSR_BUS_RPERR)
printk("Bus - Read Parity Error\n");
-#elif defined (CONFIG_E200)
+
+ return 0;
+}
+#elif defined(CONFIG_E200)
+int machine_check_e200(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from MCSR=%lx): ", reason);
@@ -341,7 +338,14 @@ void machine_check_exception(struct pt_r
printk("Bus - Read Bus Error on data load\n");
if (reason & MCSR_BUS_WRERR)
printk("Bus - Write Bus Error on buffered store or cache line push\n");
-#else /* !CONFIG_4xx && !CONFIG_E500 && !CONFIG_E200 */
+
+ return 0;
+}
+#else
+int machine_check_generic(struct pt_regs *regs)
+{
+ unsigned long reason = get_mc_reason(regs);
+
printk("Machine check in kernel mode.\n");
printk("Caused by (from SRR1=%lx): ", reason);
switch (reason & 0x601F0000) {
@@ -371,7 +375,39 @@ void machine_check_exception(struct pt_r
default:
printk("Unknown values in msr\n");
}
-#endif /* CONFIG_4xx */
+ return 0;
+}
+#endif /* everything else */
+
+void machine_check_exception(struct pt_regs *regs)
+{
+ int recover = 0;
+
+ if (cur_cpu_spec->machine_check)
+ recover = cur_cpu_spec->machine_check(regs);
+ if (recover > 0)
+ return;
+
+ if (user_mode(regs)) {
+ regs->msr |= MSR_RI;
+ _exception(SIGBUS, regs, BUS_ADRERR, regs->nip);
+ return;
+ }
+
+#if defined(CONFIG_8xx) && defined(CONFIG_PCI)
+ /* the qspan pci read routines can cause machine checks -- Cort */
+ bad_page_fault(regs, regs->dar, SIGBUS);
+ return;
+#endif
+
+ if (debugger_fault_handler) {
+ debugger_fault_handler(regs);
+ regs->msr |= MSR_RI;
+ return;
+ }
+
+ if (check_io_access(regs))
+ return;
/*
* Optional platform-provided routine to print out
Index: linux-merge/include/asm-ppc/reg_booke.h
===================================================================
--- linux-merge.orig/include/asm-ppc/reg_booke.h 2007-12-11 16:21:38.000000000 +1100
+++ linux-merge/include/asm-ppc/reg_booke.h 2007-12-11 16:23:21.000000000 +1100
@@ -207,7 +207,7 @@
#define CCR1_TCS 0x00000080 /* Timer Clock Select */
/* Bit definitions for the MCSR. */
-#ifdef CONFIG_440A
+#ifdef CONFIG_44x
#define MCSR_MCS 0x80000000 /* Machine Check Summary */
#define MCSR_IB 0x40000000 /* Instruction PLB Error */
#define MCSR_DRB 0x20000000 /* Data Read PLB Error */
^ permalink raw reply
* [PATCH 2/20] [POWERPC] Improve support for 4xx indirect DCRs
From: Benjamin Herrenschmidt @ 2007-12-13 7:38 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
Accessing indirect DCRs is done via a pair of address/data DCRs.
Such accesses are thus inherently racy, vs. interrupts, preemption
and possibly SMP if 4xx SMP cores are ever used.
This updates the mfdcri/mtdcri macros in dcr-native.h (which were
so far unused) to use a spinlock.
In addition, add some common definitions to a new dcr-regs.h file.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
include/asm-powerpc/dcr-native.h | 30 ++++++++++------
include/asm-powerpc/dcr-regs.h | 71 +++++++++++++++++++++++++++++++++++++++
2 files changed, 91 insertions(+), 10 deletions(-)
--- linux-work.orig/include/asm-powerpc/dcr-native.h 2007-12-10 15:52:26.000000000 +1100
+++ linux-work/include/asm-powerpc/dcr-native.h 2007-12-10 15:53:36.000000000 +1100
@@ -22,6 +22,8 @@
#ifdef __KERNEL__
#ifndef __ASSEMBLY__
+#include <linux/spinlock.h>
+
typedef struct {
unsigned int base;
} dcr_host_t;
@@ -55,20 +57,28 @@ do { \
} while (0)
/* R/W of indirect DCRs make use of standard naming conventions for DCRs */
-#define mfdcri(base, reg) \
-({ \
- mtdcr(base ## _CFGADDR, base ## _ ## reg); \
- mfdcr(base ## _CFGDATA); \
+extern spinlock_t dcr_ind_lock;
+
+#define mfdcri(base, reg) \
+({ \
+ unsigned long flags; \
+ unsigned int val; \
+ spin_lock_irqsave(&dcr_ind_lock, flags); \
+ mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \
+ val = mfdcr(DCRN_ ## base ## _CONFIG_DATA); \
+ spin_unlock_irqrestore(&dcr_ind_lock, flags); \
+ val; \
})
-#define mtdcri(base, reg, data) \
-do { \
- mtdcr(base ## _CFGADDR, base ## _ ## reg); \
- mtdcr(base ## _CFGDATA, data); \
+#define mtdcri(base, reg, data) \
+do { \
+ unsigned long flags; \
+ spin_lock_irqsave(&dcr_ind_lock, flags); \
+ mtdcr(DCRN_ ## base ## _CONFIG_ADDR, reg); \
+ mtdcr(DCRN_ ## base ## _CONFIG_DATA, data); \
+ spin_unlock_irqrestore(&dcr_ind_lock, flags); \
} while (0)
#endif /* __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_DCR_NATIVE_H */
-
-
Index: linux-work/include/asm-powerpc/dcr-regs.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-work/include/asm-powerpc/dcr-regs.h 2007-12-10 15:53:33.000000000 +1100
@@ -0,0 +1,71 @@
+/*
+ * Common DCR / SDR / CPR register definitions used on various IBM/AMCC
+ * 4xx processors
+ *
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp
+ * <benh@kernel.crashing.org>
+ *
+ * Mostly lifted from asm-ppc/ibm4xx.h by
+ *
+ * Copyright (c) 1999 Grant Erickson <grant@lcse.umn.edu>
+ *
+ */
+
+#ifndef __DCR_REGS_H__
+#define __DCR_REGS_H__
+
+/*
+ * Most DCRs used for controlling devices such as the MAL, DMA engine,
+ * etc... are obtained for the device tree.
+ *
+ * The definitions in this files are fixed DCRs and indirect DCRs that
+ * are commonly used outside of specific drivers or refer to core
+ * common registers that may occasionally have to be tweaked outside
+ * of the driver main register set
+ */
+
+/* CPRs (440GX and 440SP/440SPe) */
+#define DCRN_CPR0_CONFIG_ADDR 0xc
+#define DCRN_CPR0_CONFIG_DATA 0xd
+
+/* SDRs (440GX and 440SP/440SPe) */
+#define DCRN_SDR0_CONFIG_ADDR 0xe
+#define DCRN_SDR0_CONFIG_DATA 0xf
+
+#define SDR0_PFC0 0x4100
+#define SDR0_PFC1 0x4101
+#define SDR0_PFC1_EPS 0x1c00000
+#define SDR0_PFC1_EPS_SHIFT 22
+#define SDR0_PFC1_RMII 0x02000000
+#define SDR0_MFR 0x4300
+#define SDR0_MFR_TAH0 0x80000000 /* TAHOE0 Enable */
+#define SDR0_MFR_TAH1 0x40000000 /* TAHOE1 Enable */
+#define SDR0_MFR_PCM 0x10000000 /* PPC440GP irq compat mode */
+#define SDR0_MFR_ECS 0x08000000 /* EMAC int clk */
+#define SDR0_MFR_T0TXFL 0x00080000
+#define SDR0_MFR_T0TXFH 0x00040000
+#define SDR0_MFR_T1TXFL 0x00020000
+#define SDR0_MFR_T1TXFH 0x00010000
+#define SDR0_MFR_E0TXFL 0x00008000
+#define SDR0_MFR_E0TXFH 0x00004000
+#define SDR0_MFR_E0RXFL 0x00002000
+#define SDR0_MFR_E0RXFH 0x00001000
+#define SDR0_MFR_E1TXFL 0x00000800
+#define SDR0_MFR_E1TXFH 0x00000400
+#define SDR0_MFR_E1RXFL 0x00000200
+#define SDR0_MFR_E1RXFH 0x00000100
+#define SDR0_MFR_E2TXFL 0x00000080
+#define SDR0_MFR_E2TXFH 0x00000040
+#define SDR0_MFR_E2RXFL 0x00000020
+#define SDR0_MFR_E2RXFH 0x00000010
+#define SDR0_MFR_E3TXFL 0x00000008
+#define SDR0_MFR_E3TXFH 0x00000004
+#define SDR0_MFR_E3RXFL 0x00000002
+#define SDR0_MFR_E3RXFH 0x00000001
+#define SDR0_UART0 0x0120
+#define SDR0_UART1 0x0121
+#define SDR0_UART2 0x0122
+#define SDR0_UART3 0x0123
+#define SDR0_CUST0 0x4000
+
+#endif /* __DCR_REGS_H__ */
^ permalink raw reply
* [PATCH 3/20] [POWERPC] 4xx PLB to PCI-X support
From: Benjamin Herrenschmidt @ 2007-12-13 7:38 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
This adds base support code for the 4xx PCI-X bridge. It also provides
placeholders for the PCI and PCI-E version but they aren't supported
with this patch.
The bridges are configured based on device-tree properties.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
Tested on 440GP only so far.
arch/powerpc/sysdev/Makefile | 3
arch/powerpc/sysdev/ppc4xx_pci.c | 339 +++++++++++++++++++++++++++++++++++++++
arch/powerpc/sysdev/ppc4xx_pci.h | 106 ++++++++++++
3 files changed, 448 insertions(+)
--- linux-merge.orig/arch/powerpc/sysdev/Makefile 2007-10-25 13:15:47.000000000 +1000
+++ linux-merge/arch/powerpc/sysdev/Makefile 2007-12-11 16:32:58.000000000 +1100
@@ -27,6 +27,9 @@ obj-$(CONFIG_PPC_I8259) += i8259.o
obj-$(CONFIG_PPC_83xx) += ipic.o
obj-$(CONFIG_4xx) += uic.o
obj-$(CONFIG_XILINX_VIRTEX) += xilinx_intc.o
+ifeq ($(CONFIG_PCI),y)
+obj-$(CONFIG_4xx) += ppc4xx_pci.o
+endif
endif
# Temporary hack until we have migrated to asm-powerpc
Index: linux-merge/arch/powerpc/sysdev/ppc4xx_pci.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-merge/arch/powerpc/sysdev/ppc4xx_pci.c 2007-12-11 16:52:29.000000000 +1100
@@ -0,0 +1,339 @@
+/*
+ * PCI / PCI-X / PCI-Express support for 4xx parts
+ *
+ * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/of.h>
+
+#include <asm/io.h>
+#include <asm/pci-bridge.h>
+#include <asm/machdep.h>
+
+#include "ppc4xx_pci.h"
+
+static int dma_offset_set;
+
+/* Move that to a useable header */
+extern unsigned long total_memory;
+
+static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
+ void __iomem *reg,
+ struct resource *res)
+{
+ u64 size;
+ const u32 *ranges;
+ int rlen;
+ int pna = of_n_addr_cells(hose->dn);
+ int np = pna + 5;
+
+ /* Default */
+ res->start = 0;
+ res->end = size = 0x80000000;
+ res->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH;
+
+ /* Get dma-ranges property */
+ ranges = of_get_property(hose->dn, "dma-ranges", &rlen);
+ if (ranges == NULL)
+ goto out;
+
+ /* Walk it */
+ while ((rlen -= np * 4) >= 0) {
+ u32 pci_space = ranges[0];
+ u64 pci_addr = of_read_number(ranges + 1, 2);
+ u64 cpu_addr = of_translate_dma_address(hose->dn, ranges + 3);
+ size = of_read_number(ranges + pna + 3, 2);
+ ranges += np;
+ if (cpu_addr == OF_BAD_ADDR || size == 0)
+ continue;
+
+ /* We only care about memory */
+ if ((pci_space & 0x03000000) != 0x02000000)
+ continue;
+
+ /* We currently only support memory at 0, and pci_addr
+ * within 32 bits space
+ */
+ if (cpu_addr != 0 || pci_addr > 0xffffffff) {
+ printk(KERN_WARNING "%s: Ignored unsupported dma range"
+ " 0x%016llx...0x%016llx -> 0x%016llx\n",
+ hose->dn->full_name,
+ pci_addr, pci_addr + size - 1, cpu_addr);
+ continue;
+ }
+
+ /* Check if not prefetchable */
+ if (!(pci_space & 0x40000000))
+ res->flags &= ~IORESOURCE_PREFETCH;
+
+
+ /* Use that */
+ res->start = pci_addr;
+#ifndef CONFIG_RESOURCES_64BIT
+ /* Beware of 32 bits resources */
+ if ((pci_addr + size) > 0x100000000ull)
+ res->end = 0xffffffff;
+ else
+#endif
+ res->end = res->start + size - 1;
+ break;
+ }
+
+ /* We only support one global DMA offset */
+ if (dma_offset_set && pci_dram_offset != res->start) {
+ printk(KERN_ERR "%s: dma-ranges(s) mismatch\n",
+ hose->dn->full_name);
+ return -ENXIO;
+ }
+
+ /* Check that we can fit all of memory as we don't support
+ * DMA bounce buffers
+ */
+ if (size < total_memory) {
+ printk(KERN_ERR "%s: dma-ranges too small "
+ "(size=%llx total_memory=%lx)\n",
+ hose->dn->full_name, size, total_memory);
+ return -ENXIO;
+ }
+
+ /* Check we are a power of 2 size and that base is a multiple of size*/
+ if (!is_power_of_2(size) ||
+ (res->start & (size - 1)) != 0) {
+ printk(KERN_ERR "%s: dma-ranges unaligned\n",
+ hose->dn->full_name);
+ return -ENXIO;
+ }
+
+ /* Check that we are fully contained within 32 bits space */
+ if (res->end > 0xffffffff) {
+ printk(KERN_ERR "%s: dma-ranges outside of 32 bits space\n",
+ hose->dn->full_name);
+ return -ENXIO;
+ }
+ out:
+ dma_offset_set = 1;
+ pci_dram_offset = res->start;
+
+ printk(KERN_INFO "4xx PCI DMA offset set to 0x%08lx\n",
+ pci_dram_offset);
+ return 0;
+}
+
+/*
+ * 4xx PCI 2.x part
+ */
+static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
+{
+ /* NYI */
+}
+
+/*
+ * 4xx PCI-X part
+ */
+
+static void __init ppc4xx_configure_pcix_POMs(struct pci_controller *hose,
+ void __iomem *reg)
+{
+ u32 lah, lal, pciah, pcial, sa;
+ int i, j;
+
+ /* Setup outbound memory windows */
+ for (i = j = 0; i < 3; i++) {
+ struct resource *res = &hose->mem_resources[i];
+
+ /* we only care about memory windows */
+ if (!(res->flags & IORESOURCE_MEM))
+ continue;
+ if (j > 1) {
+ printk(KERN_WARNING "%s: Too many ranges\n",
+ hose->dn->full_name);
+ break;
+ }
+
+ /* Calculate register values */
+#ifdef CONFIG_PTE_64BIT
+ lah = res->start >> 32;
+ lal = res->start & 0xffffffffu;
+ pciah = (res->start - hose->pci_mem_offset) >> 32;
+ pcial = (res->start - hose->pci_mem_offset) & 0xffffffffu;
+#else
+ lah = pciah = 0;
+ lal = res->start;
+ pcial = res->start - hose->pci_mem_offset;
+#endif
+ sa = res->end + 1 - res->start;
+ if (!is_power_of_2(sa) || sa < 0x100000 ||
+ sa > 0xffffffffu) {
+ printk(KERN_WARNING "%s: Resource out of range\n",
+ hose->dn->full_name);
+ continue;
+ }
+ sa = (0xffffffffu << ilog2(sa)) | 0x1;
+
+ /* Program register values */
+ if (j == 0) {
+ writel(lah, reg + PCIX0_POM0LAH);
+ writel(lal, reg + PCIX0_POM0LAL);
+ writel(pciah, reg + PCIX0_POM0PCIAH);
+ writel(pcial, reg + PCIX0_POM0PCIAL);
+ writel(sa, reg + PCIX0_POM0SA);
+ } else {
+ writel(lah, reg + PCIX0_POM1LAH);
+ writel(lal, reg + PCIX0_POM1LAL);
+ writel(pciah, reg + PCIX0_POM1PCIAH);
+ writel(pcial, reg + PCIX0_POM1PCIAL);
+ writel(sa, reg + PCIX0_POM1SA);
+ }
+ j++;
+ }
+}
+
+static void __init ppc4xx_configure_pcix_PIMs(struct pci_controller *hose,
+ void __iomem *reg,
+ const struct resource *res,
+ int big_pim,
+ int enable_msi_hole)
+{
+ resource_size_t size = res->end - res->start + 1;
+ u32 sa;
+
+ /* RAM is always at 0 */
+ writel(0x00000000, reg + PCIX0_PIM0LAH);
+ writel(0x00000000, reg + PCIX0_PIM0LAL);
+
+ /* Calculate window size */
+ sa = (0xffffffffu << ilog2(size)) | 1;
+ sa |= 0x1;
+ if (res->flags & IORESOURCE_PREFETCH)
+ sa |= 0x2;
+ if (enable_msi_hole)
+ sa |= 0x4;
+ writel(sa, reg + PCIX0_PIM0SA);
+ if (big_pim)
+ writel(0xffffffff, reg + PCIX0_PIM0SAH);
+
+ /* Map on PCI side */
+ writel(0x00000000, reg + PCIX0_BAR0H);
+ writel(res->start, reg + PCIX0_BAR0L);
+ writew(0x0006, reg + PCIX0_COMMAND);
+}
+
+static void __init ppc4xx_probe_pcix_bridge(struct device_node *np)
+{
+ struct resource rsrc_cfg;
+ struct resource rsrc_reg;
+ struct resource dma_window;
+ struct pci_controller *hose = NULL;
+ void __iomem *reg = NULL;
+ const int *bus_range;
+ int big_pim = 0, msi = 0, primary = 0;
+
+ /* Fetch config space registers address */
+ if (of_address_to_resource(np, 0, &rsrc_cfg)) {
+ printk(KERN_ERR "%s:Can't get PCI-X config register base !",
+ np->full_name);
+ return;
+ }
+ /* Fetch host bridge internal registers address */
+ if (of_address_to_resource(np, 3, &rsrc_reg)) {
+ printk(KERN_ERR "%s: Can't get PCI-X internal register base !",
+ np->full_name);
+ return;
+ }
+
+ /* Check if it supports large PIMs (440GX) */
+ if (of_get_property(np, "large-inbound-windows", NULL))
+ big_pim = 1;
+
+ /* Check if we should enable MSIs inbound hole */
+ if (of_get_property(np, "enable-msi-hole", NULL))
+ msi = 1;
+
+ /* Check if primary bridge */
+ if (of_get_property(np, "primary", NULL))
+ primary = 1;
+
+ /* Get bus range if any */
+ bus_range = of_get_property(np, "bus-range", NULL);
+
+ /* Map registers */
+ reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
+ if (reg == NULL) {
+ printk(KERN_ERR "%s: Can't map registers !", np->full_name);
+ goto fail;
+ }
+
+ /* Allocate the host controller data structure */
+ hose = pcibios_alloc_controller(np);
+ if (!hose)
+ goto fail;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0x0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ /* Setup config space */
+ setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0);
+
+ /* Disable all windows */
+ writel(0, reg + PCIX0_POM0SA);
+ writel(0, reg + PCIX0_POM1SA);
+ writel(0, reg + PCIX0_POM2SA);
+ writel(0, reg + PCIX0_PIM0SA);
+ writel(0, reg + PCIX0_PIM1SA);
+ writel(0, reg + PCIX0_PIM2SA);
+ if (big_pim) {
+ writel(0, reg + PCIX0_PIM0SAH);
+ writel(0, reg + PCIX0_PIM2SAH);
+ }
+
+ /* Parse outbound mapping resources */
+ pci_process_bridge_OF_ranges(hose, np, primary);
+
+ /* Parse inbound mapping resources */
+ if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
+ goto fail;
+
+ /* Configure outbound ranges POMs */
+ ppc4xx_configure_pcix_POMs(hose, reg);
+
+ /* Configure inbound ranges PIMs */
+ ppc4xx_configure_pcix_PIMs(hose, reg, &dma_window, big_pim, msi);
+
+ /* We don't need the registers anymore */
+ iounmap(reg);
+ return;
+
+ fail:
+ if (hose)
+ pcibios_free_controller(hose);
+ if (reg)
+ iounmap(reg);
+}
+
+/*
+ * 4xx PCI-Express part
+ */
+static void __init ppc4xx_probe_pciex_bridge(struct device_node *np)
+{
+ /* NYI */
+}
+
+static int __init ppc4xx_pci_find_bridges(void)
+{
+ struct device_node *np;
+
+ for_each_compatible_node(np, NULL, "ibm,plb-pciex")
+ ppc4xx_probe_pciex_bridge(np);
+ for_each_compatible_node(np, NULL, "ibm,plb-pcix")
+ ppc4xx_probe_pcix_bridge(np);
+ for_each_compatible_node(np, NULL, "ibm,plb-pci")
+ ppc4xx_probe_pci_bridge(np);
+
+ return 0;
+}
+arch_initcall(ppc4xx_pci_find_bridges);
+
Index: linux-merge/arch/powerpc/sysdev/ppc4xx_pci.h
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-merge/arch/powerpc/sysdev/ppc4xx_pci.h 2007-12-11 16:52:19.000000000 +1100
@@ -0,0 +1,106 @@
+/*
+ * PCI / PCI-X / PCI-Express support for 4xx parts
+ *
+ * Copyright 2007 Ben. Herrenschmidt <benh@kernel.crashing.org>, IBM Corp.
+ *
+ * Bits and pieces extracted from arch/ppc support by
+ *
+ * Matt Porter <mporter@kernel.crashing.org>
+ *
+ * Copyright 2002-2005 MontaVista Software Inc.
+ */
+#ifndef __PPC4XX_PCI_H__
+#define __PPC4XX_PCI_H__
+
+/*
+ * 4xx PCI-X bridge register definitions
+ */
+#define PCIX0_VENDID 0x000
+#define PCIX0_DEVID 0x002
+#define PCIX0_COMMAND 0x004
+#define PCIX0_STATUS 0x006
+#define PCIX0_REVID 0x008
+#define PCIX0_CLS 0x009
+#define PCIX0_CACHELS 0x00c
+#define PCIX0_LATTIM 0x00d
+#define PCIX0_HDTYPE 0x00e
+#define PCIX0_BIST 0x00f
+#define PCIX0_BAR0L 0x010
+#define PCIX0_BAR0H 0x014
+#define PCIX0_BAR1 0x018
+#define PCIX0_BAR2L 0x01c
+#define PCIX0_BAR2H 0x020
+#define PCIX0_BAR3 0x024
+#define PCIX0_CISPTR 0x028
+#define PCIX0_SBSYSVID 0x02c
+#define PCIX0_SBSYSID 0x02e
+#define PCIX0_EROMBA 0x030
+#define PCIX0_CAP 0x034
+#define PCIX0_RES0 0x035
+#define PCIX0_RES1 0x036
+#define PCIX0_RES2 0x038
+#define PCIX0_INTLN 0x03c
+#define PCIX0_INTPN 0x03d
+#define PCIX0_MINGNT 0x03e
+#define PCIX0_MAXLTNCY 0x03f
+#define PCIX0_BRDGOPT1 0x040
+#define PCIX0_BRDGOPT2 0x044
+#define PCIX0_ERREN 0x050
+#define PCIX0_ERRSTS 0x054
+#define PCIX0_PLBBESR 0x058
+#define PCIX0_PLBBEARL 0x05c
+#define PCIX0_PLBBEARH 0x060
+#define PCIX0_POM0LAL 0x068
+#define PCIX0_POM0LAH 0x06c
+#define PCIX0_POM0SA 0x070
+#define PCIX0_POM0PCIAL 0x074
+#define PCIX0_POM0PCIAH 0x078
+#define PCIX0_POM1LAL 0x07c
+#define PCIX0_POM1LAH 0x080
+#define PCIX0_POM1SA 0x084
+#define PCIX0_POM1PCIAL 0x088
+#define PCIX0_POM1PCIAH 0x08c
+#define PCIX0_POM2SA 0x090
+#define PCIX0_PIM0SAL 0x098
+#define PCIX0_PIM0SA PCIX0_PIM0SAL
+#define PCIX0_PIM0LAL 0x09c
+#define PCIX0_PIM0LAH 0x0a0
+#define PCIX0_PIM1SA 0x0a4
+#define PCIX0_PIM1LAL 0x0a8
+#define PCIX0_PIM1LAH 0x0ac
+#define PCIX0_PIM2SAL 0x0b0
+#define PCIX0_PIM2SA PCIX0_PIM2SAL
+#define PCIX0_PIM2LAL 0x0b4
+#define PCIX0_PIM2LAH 0x0b8
+#define PCIX0_OMCAPID 0x0c0
+#define PCIX0_OMNIPTR 0x0c1
+#define PCIX0_OMMC 0x0c2
+#define PCIX0_OMMA 0x0c4
+#define PCIX0_OMMUA 0x0c8
+#define PCIX0_OMMDATA 0x0cc
+#define PCIX0_OMMEOI 0x0ce
+#define PCIX0_PMCAPID 0x0d0
+#define PCIX0_PMNIPTR 0x0d1
+#define PCIX0_PMC 0x0d2
+#define PCIX0_PMCSR 0x0d4
+#define PCIX0_PMCSRBSE 0x0d6
+#define PCIX0_PMDATA 0x0d7
+#define PCIX0_PMSCRR 0x0d8
+#define PCIX0_CAPID 0x0dc
+#define PCIX0_NIPTR 0x0dd
+#define PCIX0_CMD 0x0de
+#define PCIX0_STS 0x0e0
+#define PCIX0_IDR 0x0e4
+#define PCIX0_CID 0x0e8
+#define PCIX0_RID 0x0ec
+#define PCIX0_PIM0SAH 0x0f8
+#define PCIX0_PIM2SAH 0x0fc
+#define PCIX0_MSGIL 0x100
+#define PCIX0_MSGIH 0x104
+#define PCIX0_MSGOL 0x108
+#define PCIX0_MSGOH 0x10c
+#define PCIX0_IM 0x1f8
+
+
+
+#endif /* __PPC4XX_PCI_H__ */
^ permalink raw reply
* [PATCH 4/20] [POWERPC] 4xx PLB to PCI 2.x support
From: Benjamin Herrenschmidt @ 2007-12-13 7:38 UTC (permalink / raw)
To: Josh Boyer; +Cc: linuxppc-dev
This adds to the previous patch the support for the 4xx PCI 2.x
bridges.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
This version implement the basic support for the 405GP bridge,
I haven't yet looked at differences that other implementations
may have for the PCI 2.x part.
arch/powerpc/sysdev/ppc4xx_pci.c | 180 ++++++++++++++++++++++++++++++++++++++-
arch/powerpc/sysdev/ppc4xx_pci.h | 19 ++++
2 files changed, 198 insertions(+), 1 deletion(-)
--- linux-merge.orig/arch/powerpc/sysdev/ppc4xx_pci.c 2007-12-11 16:50:32.000000000 +1100
+++ linux-merge/arch/powerpc/sysdev/ppc4xx_pci.c 2007-12-11 16:50:46.000000000 +1100
@@ -21,6 +21,36 @@ static int dma_offset_set;
/* Move that to a useable header */
extern unsigned long total_memory;
+static void fixup_ppc4xx_pci_bridge(struct pci_dev *dev)
+{
+ struct pci_controller *hose;
+ int i;
+
+ if (dev->devfn != 0 || dev->bus->self != NULL)
+ return;
+
+ hose = pci_bus_to_host(dev->bus);
+ if (hose == NULL)
+ return;
+
+ if (!of_device_is_compatible(hose->dn, "ibm,plb-pciex") &&
+ !of_device_is_compatible(hose->dn, "ibm,plb-pcix") &&
+ !of_device_is_compatible(hose->dn, "ibm,plb-pci"))
+ return;
+
+ /* Hide the PCI host BARs from the kernel as their content doesn't
+ * fit well in the resource management
+ */
+ for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
+ dev->resource[i].start = dev->resource[i].end = 0;
+ dev->resource[i].flags = 0;
+ }
+
+ printk(KERN_INFO "PCI: Hiding 4xx host bridge resources %s\n",
+ pci_name(dev));
+}
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, fixup_ppc4xx_pci_bridge);
+
static int __init ppc4xx_parse_dma_ranges(struct pci_controller *hose,
void __iomem *reg,
struct resource *res)
@@ -126,9 +156,157 @@ static int __init ppc4xx_parse_dma_range
/*
* 4xx PCI 2.x part
*/
+
+static void __init ppc4xx_configure_pci_PMMs(struct pci_controller *hose,
+ void __iomem *reg)
+{
+ u32 la, ma, pcila, pciha;
+ int i, j;
+
+ /* Setup outbound memory windows */
+ for (i = j = 0; i < 3; i++) {
+ struct resource *res = &hose->mem_resources[i];
+
+ /* we only care about memory windows */
+ if (!(res->flags & IORESOURCE_MEM))
+ continue;
+ if (j > 2) {
+ printk(KERN_WARNING "%s: Too many ranges\n",
+ hose->dn->full_name);
+ break;
+ }
+
+ /* Calculate register values */
+ la = res->start;
+#ifdef CONFIG_RESOURCES_64BIT
+ pciha = (res->start - hose->pci_mem_offset) >> 32;
+ pcila = (res->start - hose->pci_mem_offset) & 0xffffffffu;
+#else
+ pciha = 0;
+ pcila = res->start - hose->pci_mem_offset;
+#endif
+
+ ma = res->end + 1 - res->start;
+ if (!is_power_of_2(ma) || ma < 0x1000 || ma > 0xffffffffu) {
+ printk(KERN_WARNING "%s: Resource out of range\n",
+ hose->dn->full_name);
+ continue;
+ }
+ ma = (0xffffffffu << ilog2(ma)) | 0x1;
+ if (res->flags & IORESOURCE_PREFETCH)
+ ma |= 0x2;
+
+ /* Program register values */
+ writel(la, reg + PCIL0_PMM0LA + (0x10 * j));
+ writel(pcila, reg + PCIL0_PMM0PCILA + (0x10 * j));
+ writel(pciha, reg + PCIL0_PMM0PCIHA + (0x10 * j));
+ writel(ma, reg + PCIL0_PMM0MA + (0x10 * j));
+ j++;
+ }
+}
+
+static void __init ppc4xx_configure_pci_PTMs(struct pci_controller *hose,
+ void __iomem *reg,
+ const struct resource *res)
+{
+ resource_size_t size = res->end - res->start + 1;
+ u32 sa;
+
+ /* Calculate window size */
+ sa = (0xffffffffu << ilog2(size)) | 1;
+ sa |= 0x1;
+
+ /* RAM is always at 0 local for now */
+ writel(0, reg + PCIL0_PTM1LA);
+ writel(sa, reg + PCIL0_PTM1MS);
+
+ /* Map on PCI side */
+ early_write_config_dword(hose, hose->first_busno, 0,
+ PCI_BASE_ADDRESS_1, res->start);
+ early_write_config_dword(hose, hose->first_busno, 0,
+ PCI_BASE_ADDRESS_2, 0x00000000);
+ early_write_config_word(hose, hose->first_busno, 0,
+ PCI_COMMAND, 0x0006);
+}
+
static void __init ppc4xx_probe_pci_bridge(struct device_node *np)
{
/* NYI */
+ struct resource rsrc_cfg;
+ struct resource rsrc_reg;
+ struct resource dma_window;
+ struct pci_controller *hose = NULL;
+ void __iomem *reg = NULL;
+ const int *bus_range;
+ int primary = 0;
+
+ /* Fetch config space registers address */
+ if (of_address_to_resource(np, 0, &rsrc_cfg)) {
+ printk(KERN_ERR "%s:Can't get PCI config register base !",
+ np->full_name);
+ return;
+ }
+ /* Fetch host bridge internal registers address */
+ if (of_address_to_resource(np, 3, &rsrc_reg)) {
+ printk(KERN_ERR "%s: Can't get PCI internal register base !",
+ np->full_name);
+ return;
+ }
+
+ /* Check if primary bridge */
+ if (of_get_property(np, "primary", NULL))
+ primary = 1;
+
+ /* Get bus range if any */
+ bus_range = of_get_property(np, "bus-range", NULL);
+
+ /* Map registers */
+ reg = ioremap(rsrc_reg.start, rsrc_reg.end + 1 - rsrc_reg.start);
+ if (reg == NULL) {
+ printk(KERN_ERR "%s: Can't map registers !", np->full_name);
+ goto fail;
+ }
+
+ /* Allocate the host controller data structure */
+ hose = pcibios_alloc_controller(np);
+ if (!hose)
+ goto fail;
+
+ hose->first_busno = bus_range ? bus_range[0] : 0x0;
+ hose->last_busno = bus_range ? bus_range[1] : 0xff;
+
+ /* Setup config space */
+ setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 0x4, 0);
+
+ /* Disable all windows */
+ writel(0, reg + PCIL0_PMM0MA);
+ writel(0, reg + PCIL0_PMM1MA);
+ writel(0, reg + PCIL0_PMM2MA);
+ writel(0, reg + PCIL0_PTM1MS);
+ writel(0, reg + PCIL0_PTM2MS);
+
+ /* Parse outbound mapping resources */
+ pci_process_bridge_OF_ranges(hose, np, primary);
+
+ /* Parse inbound mapping resources */
+ if (ppc4xx_parse_dma_ranges(hose, reg, &dma_window) != 0)
+ goto fail;
+
+ /* Configure outbound ranges POMs */
+ ppc4xx_configure_pci_PMMs(hose, reg);
+
+ /* Configure inbound ranges PIMs */
+ ppc4xx_configure_pci_PTMs(hose, reg, &dma_window);
+
+ /* We don't need the registers anymore */
+ iounmap(reg);
+ return;
+
+ fail:
+ if (hose)
+ pcibios_free_controller(hose);
+ if (reg)
+ iounmap(reg);
}
/*
@@ -155,7 +333,7 @@ static void __init ppc4xx_configure_pcix
}
/* Calculate register values */
-#ifdef CONFIG_PTE_64BIT
+#ifdef CONFIG_RESOURCES_64BIT
lah = res->start >> 32;
lal = res->start & 0xffffffffu;
pciah = (res->start - hose->pci_mem_offset) >> 32;
Index: linux-merge/arch/powerpc/sysdev/ppc4xx_pci.h
===================================================================
--- linux-merge.orig/arch/powerpc/sysdev/ppc4xx_pci.h 2007-12-11 16:50:02.000000000 +1100
+++ linux-merge/arch/powerpc/sysdev/ppc4xx_pci.h 2007-12-11 16:50:46.000000000 +1100
@@ -101,6 +101,25 @@
#define PCIX0_MSGOH 0x10c
#define PCIX0_IM 0x1f8
+/*
+ * 4xx PCI bridge register definitions
+ */
+#define PCIL0_PMM0LA 0x00
+#define PCIL0_PMM0MA 0x04
+#define PCIL0_PMM0PCILA 0x08
+#define PCIL0_PMM0PCIHA 0x0c
+#define PCIL0_PMM1LA 0x10
+#define PCIL0_PMM1MA 0x14
+#define PCIL0_PMM1PCILA 0x18
+#define PCIL0_PMM1PCIHA 0x1c
+#define PCIL0_PMM2LA 0x20
+#define PCIL0_PMM2MA 0x24
+#define PCIL0_PMM2PCILA 0x28
+#define PCIL0_PMM2PCIHA 0x2c
+#define PCIL0_PTM1MS 0x30
+#define PCIL0_PTM1LA 0x34
+#define PCIL0_PTM2MS 0x38
+#define PCIL0_PTM2LA 0x3c
#endif /* __PPC4XX_PCI_H__ */
^ 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