* Re: Unable to boot a kernel on a MPC8560
From: Wolfgang Denk @ 2006-05-16 20:26 UTC (permalink / raw)
To: pito50; +Cc: linuxppc-embedded
In-Reply-To: <BAY105-F10857BC9DB3B958AC19C8D8EA00@phx.gbl>
In message <BAY105-F10857BC9DB3B958AC19C8D8EA00@phx.gbl> you wrote:
>
> first of all, I am a newbie in embedded linux systems.
Seems you are also a newbie when it comes to posting to mailing lists
in general. Posting the same question several times to several
mailing lists is not a good idea. Please read
http://www.catb.org/%7eesr/faqs/smart-questions.html
> The boot loader is U-Boot.
...
> Here is the result of one of my tests :
> -> niot 0
...
> -> nbo 0
These are definitely no U-Boot commands.
Best regards,
Wolfgang Denk
--
Software Engineering: Embedded and Realtime Systems, Embedded Linux
Phone: (+49)-8142-66989-10 Fax: (+49)-8142-66989-80 Email: wd@denx.de
He's dead, Jim
-- McCoy, "The Devil in the Dark", stardate 3196.1
^ permalink raw reply
* Re: [PATCH] yaboot: enable boot from iscsi target via ethernet devices on js20.
From: Doug Maxey @ 2006-05-16 20:40 UTC (permalink / raw)
To: Paul Nasrat; +Cc: yaboot-devel, Linux PowerPC List
In-Reply-To: <1147810848.4115.33.camel@enki.eridu>
On Tue, 16 May 2006 16:20:47 EDT, Paul Nasrat wrote:
>On Fri, 2006-04-28 at 01:05 -0500, Doug Maxey wrote:
>> Certain levels of JS20 firmware will allow the system to boot from an
>> iscsi target. System OFW accomplishes this by setting up a virtual
>> disk device with parameters. These parameters, when passed back to
>> OFW by yaboot, directs the FW to use virtual device over the ethernet
>> port that will then access iscsi target as a block device. This patch
>> extracts those parameters from the property of the virtual device and
>> passes them back to OFW to indicate the kernel is to be retrieved via
>> the iscsi protocol.
>>
>> Signed-off-by: Doug Maxey <dwm@austin.ibm.com>
>
>Sorry for the delay in getting back to you - a few initial questions:
np. been on vacation the last 10 days. Switzerland is nice, and Milan
is cool. :)
>
>> diff --git a/second/file.c b/second/file.c
>
>> @@ -185,16 +188,45 @@ parse_device_path(char *imagepath, char
>>
>> if (!imagepath)
>> return 0;
>> +
>> + /*
>> + * Do preliminary checking for an iscsi device; it may appear as
>> + * pure a network device (device_type == "network") if this is
>> + * ISWI. This is the case on IBM systems doing an iscsi OFW
>> + * boot.
>> + */
>> + if (strstr(imagepath, ",iscsi"))
>
>Is the , always guaranteed to be there - eg if I have boot
>eth1:iscsi,ISCSIARGS won't this check fail.
Yes, with the above command line this would fail.
My point of reference are the bindings that we cannot yet talk about
here, yet. The device args would always be followed by a comma. I suppose
that we could just reference the string "iscsi", but then some wag
would want to create some other property that included "iscsi" as a
substring. Maybe append a comma?
>
>> diff --git a/second/prom.c b/second/prom.c
>> index 5ec06b8..9bc5415 100644
>> --- a/second/prom.c
>> +++ b/second/prom.c
>> @@ -174,6 +174,9 @@ prom_get_devtype (char *device)
>> int result;
>> char tmp[64];
>>
>> + if (strstr(device, ",iscsi"))
>> + device = strcpy(tmp, "/vdevice/gscsi/disk");
>> +
>
>Ditto here.
likewise. Maybe make it a #define so it would be common.
>
>Paul
>
^ permalink raw reply
* Re: [RFC] alsa integer control ranges
From: Benjamin Herrenschmidt @ 2006-05-16 22:00 UTC (permalink / raw)
To: Johannes Berg; +Cc: linuxppc-dev list, ALSA development, Benjamin Berg
In-Reply-To: <1147780945.29795.110.camel@johannes>
On Tue, 2006-05-16 at 14:02 +0200, Johannes Berg wrote:
> Apparently all alsa userspace programs including alsamixer suck. Hence,
> this patch is required to make them work properly. Why is it so hard to
> do these additions/subtractions in the program or maybe even in the alsa
> library? The alsa libraries already think they know better and mess up
> all kinds of things.
alsamixer works for me with negative ranges... but all other apps don't
and there are various bugs, I blame apps converted from OSS....
> What are your opinions on this? Should this be required? And if so, why
> do we even have the value.integer.min when we can't use it anyway?
>
> The code this patch applies against is in
> http://johannes.sipsolutions.net/snd-aoa.git/ but that isn't all too
> relevant, the patch serves just as an illustration of what is wrong
> here.
>
> Thanks,
> johannes
>
> --- snd-aoa.orig/aoa/codecs/onyx/snd-aoa-codec-onyx.c 2006-05-16 12:13:39.663950213 +0200
> +++ snd-aoa/aoa/codecs/onyx/snd-aoa-codec-onyx.c 2006-05-16 12:14:13.698643898 +0200
> @@ -102,8 +102,8 @@ static int onyx_snd_vol_info(struct snd_
> {
> uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> uinfo->count = 2;
> - uinfo->value.integer.min = -128;
> - uinfo->value.integer.max = -1;
> + uinfo->value.integer.min = -128+128;
> + uinfo->value.integer.max = -1+128;
> return 0;
> }
>
> @@ -115,8 +115,8 @@ static int onyx_snd_vol_get(struct snd_k
>
> onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, &l);
> onyx_read_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, &r);
> - ucontrol->value.integer.value[0] = l;
> - ucontrol->value.integer.value[1] = r;
> + ucontrol->value.integer.value[0] = l+128;
> + ucontrol->value.integer.value[1] = r+128;
> return 0;
> }
>
> @@ -125,8 +125,8 @@ static int onyx_snd_vol_put(struct snd_k
> {
> struct onyx *onyx = snd_kcontrol_chip(kcontrol);
>
> - onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, ucontrol->value.integer.value[0]);
> - onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, ucontrol->value.integer.value[1]);
> + onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_LEFT, ucontrol->value.integer.value[0]-128);
> + onyx_write_register(onyx, ONYX_REG_DAC_ATTEN_RIGHT, ucontrol->value.integer.value[1]-128);
> /* FIXME: we could be checking if anything changed */
> return 1;
> }
> @@ -145,8 +145,8 @@ static int onyx_snd_inputgain_info(struc
> {
> uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
> uinfo->count = 1;
> - uinfo->value.integer.min = 3;
> - uinfo->value.integer.max = 28;
> + uinfo->value.integer.min = 3-3;
> + uinfo->value.integer.max = 28-3;
> return 0;
> }
>
> @@ -157,7 +157,7 @@ static int onyx_snd_inputgain_get(struct
> u8 ig;
>
> onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &ig);
> - ucontrol->value.integer.value[0] = ig & ONYX_ADC_PGA_GAIN_MASK;
> + ucontrol->value.integer.value[0] = (ig & ONYX_ADC_PGA_GAIN_MASK)-3;
> return 0;
> }
>
> @@ -169,7 +169,7 @@ static int onyx_snd_inputgain_put(struct
>
> onyx_read_register(onyx, ONYX_REG_ADC_CONTROL, &val);
> val &= ~ONYX_ADC_PGA_GAIN_MASK;
> - val |= ucontrol->value.integer.value[0] & ONYX_ADC_PGA_GAIN_MASK;
> + val |= (ucontrol->value.integer.value[0]+3) & ONYX_ADC_PGA_GAIN_MASK;
> onyx_write_register(onyx, ONYX_REG_ADC_CONTROL, val);
> return 1;
> }
>
^ permalink raw reply
* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Benjamin Herrenschmidt @ 2006-05-16 22:03 UTC (permalink / raw)
To: Takashi Iwai
Cc: linuxppc-dev list, Johannes Berg, ALSA development, Benjamin Berg
In-Reply-To: <s5h7j4m40kf.wl%tiwai@suse.de>
On Tue, 2006-05-16 at 14:27 +0200, Takashi Iwai wrote:
> At Tue, 16 May 2006 14:02:20 +0200,
> Johannes Berg wrote:
> >
> > Apparently all alsa userspace programs including alsamixer suck. Hence,
> > this patch is required to make them work properly. Why is it so hard to
> > do these additions/subtractions in the program or maybe even in the alsa
> > library? The alsa libraries already think they know better and mess up
> > all kinds of things.
>
> It's a pretty stupid question to ask why you are stupid :)
>
> I don't think it's alsa-lib that prevents the negative or non-zero
> integer range. The fact amixer works implies that it's an
> app-specific bug. But I'm not 100% sure and need more
> inside-looking.
Well, the problem I think is that pretty much all apps but amixer (and
alsamixer whch works too for me at least) are bogus. It would have been
good if Alsa had a more explicit specification that those values are not
to be interpreted in the old OSS range :) In fact, best would have been
to have the control structure carry a "unit" which a set of known units,
one being dB, since the natural way of specifying an attenuation on any
serious audio HW is dB and is negative...
> > What are your opinions on this? Should this be required? And if so, why
> > do we even have the value.integer.min when we can't use it anyway?
>
> Right now, the range 0-max would make your life easier, I guess.
>
> The min value is an API definition, and implemented and worked once.
> But no drivers used yet. So, there might be a breakage. It's of
> course to be fixed.
There is a lack of serious/professional audio drivers in the linux world
unfortunately...
Ben.
^ permalink raw reply
* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Benjamin Herrenschmidt @ 2006-05-16 22:04 UTC (permalink / raw)
To: Jaroslav Kysela
Cc: linuxppc-dev list, Johannes Berg, ALSA development, Benjamin Berg
In-Reply-To: <Pine.LNX.4.61.0605161430220.9330@tm8103.perex-int.cz>
On Tue, 2006-05-16 at 14:31 +0200, Jaroslav Kysela wrote:
> On Tue, 16 May 2006, Johannes Berg wrote:
>
> > Apparently all alsa userspace programs including alsamixer suck. Hence,
> > this patch is required to make them work properly. Why is it so hard to
> > do these additions/subtractions in the program or maybe even in the alsa
> > library? The alsa libraries already think they know better and mess up
> > all kinds of things.
>
> It's better to fix apps, if they are broken.
Problem is, they are currently all broken (pretty much) and thus unless
we want to release a driver that won't work with any current distros,
we'll have to whack the ranges :(
Ben.
^ permalink raw reply
* Re: [Alsa-devel] Re: [RFC] alsa integer control ranges
From: Lee Revell @ 2006-05-16 22:04 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev list, Johannes Berg, ALSA development, Benjamin Berg
In-Reply-To: <1147816857.6753.1.camel@localhost.localdomain>
On Wed, 2006-05-17 at 08:00 +1000, Benjamin Herrenschmidt wrote:
> On Tue, 2006-05-16 at 14:02 +0200, Johannes Berg wrote:
> > Apparently all alsa userspace programs including alsamixer suck. Hence,
> > this patch is required to make them work properly. Why is it so hard to
> > do these additions/subtractions in the program or maybe even in the alsa
> > library? The alsa libraries already think they know better and mess up
> > all kinds of things.
>
> alsamixer works for me with negative ranges... but all other apps don't
> and there are various bugs, I blame apps converted from OSS....
kmix is the worst by far, someone really needs to fix it. It has so
many bugs that it's unusable for debugging ALSA, we have to tell people
to use alsamixer.
Lee
^ permalink raw reply
* Re: ppc32 kernel boot problem (pmu related?)
From: Benjamin Herrenschmidt @ 2006-05-16 22:07 UTC (permalink / raw)
To: Nathan Pilatzke; +Cc: linuxppc-dev
In-Reply-To: <98889dd30605160804i78fc6a31w5147aba1dc5562b@mail.gmail.com>
On Tue, 2006-05-16 at 11:04 -0400, Nathan Pilatzke wrote:
> On 5/16/06, Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:
> >
> > Can you try editing arch/powerpc/platforms/powermac/low_i2c.c, in
> > function pmac_i2c_init(), comment out the call to pmac_i2c_devscan() and
> > tell me if that makes a difference.
> >
> > Thanks,
> > Ben.
> >
> >
> Commenting out the call to pmac_i2c_devscan() in function
> pmac_i2c_init() allowed the kernel to boot. I am typing this email
> booted under it. The kernel messages were printed a bit strangely
> though. There was no scrolling or clearing of the screen. The kernel
> messages would start at the top and overwrite old messages, with the
> cursor jumping back to the top of the screen every so often.
That's because of the change you did to udbg.c for debugging :)
> The /proc/device-tree is attached for the booting 2.6.17-rc3 kernel with
> pmu enabled, as is the new dmesg output. If you need the
> /proc/device-tree from a 2.6.15 working kernel with pmu enabled
> instead, let me know.
No, it should be the same regardless of the kernel
> Is this kernel fairly safe/stable to use? What can be done next?
Well, I need to figure out what's going on with the i2c stuff... there
is a chip that hangs off the PMU and that says something like "do that
at boot"... but when I do it, it causes the crash you are seeing. So
either I'm not doing what it tells me to do properly or I should just
blacklist this machine (Apple doesn't execute the platform functions
from the device-tree on older machines I think).
I'm investigating, will come back to you.
Ben.
^ permalink raw reply
* Common Flash Interface v1.4(P30) and MTD support in Linux-2.4.16 kernel
From: Jayasri Sangu @ 2006-05-16 23:18 UTC (permalink / raw)
To: linuxppc-embedded
Hi,
Does linux-2.4.16 kernel MTD support the Intel P30 flash ?
If not what are the solutions ?
Thanks
Jayasri=20
Come see us at CommunicAsia 2006 http://www.communicasia.com/
June 20-23, 2006 in Singapore at the US International Pavilion booth =
6F1-03
^ permalink raw reply
* Re: Common Flash Interface v1.4(P30) and MTD support in Linux-2.4.16 kernel
From: Josh Boyer @ 2006-05-17 1:37 UTC (permalink / raw)
To: Jayasri Sangu; +Cc: linuxppc-embedded
In-Reply-To: <E76D631A87C2874E895D1639A1CEDB962AF95D@aae-exchange.aaesys.com>
On Tue, 2006-05-16 at 16:18 -0700, Jayasri Sangu wrote:
> Hi,
>
> Does linux-2.4.16 kernel MTD support the Intel P30 flash ?
No. That's almost 4.5 years old now. Intel P30 was released within the
last year.
>
> If not what are the solutions ?
Use 2.6.15 or 2.6.16
josh
^ permalink raw reply
* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Jaroslav Kysela @ 2006-05-17 6:41 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev list, Johannes Berg, ALSA development, Benjamin Berg
In-Reply-To: <1147817058.6753.7.camel@localhost.localdomain>
On Wed, 17 May 2006, Benjamin Herrenschmidt wrote:
> On Tue, 2006-05-16 at 14:31 +0200, Jaroslav Kysela wrote:
> > On Tue, 16 May 2006, Johannes Berg wrote:
> >
> > > Apparently all alsa userspace programs including alsamixer suck. Hence,
> > > this patch is required to make them work properly. Why is it so hard to
> > > do these additions/subtractions in the program or maybe even in the alsa
> > > library? The alsa libraries already think they know better and mess up
> > > all kinds of things.
> >
> > It's better to fix apps, if they are broken.
>
> Problem is, they are currently all broken (pretty much) and thus unless
> we want to release a driver that won't work with any current distros,
> we'll have to whack the ranges :(
It's better to have problematic values by default and define a module
(driver) option to enable the "compatible" behaviour. Otherwise the apps
will be never fixed. Also, ideally, you can fix apps and send patches to
authors and/or create problematic controls in the dummy driver
(drivers/dummy.c) and send a notice to app developers that they have
broken apps and ask to fix them refering to the dummy driver test case.
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply
* [PATCH 1/5] powerpc: Make early xmon logic immune to location of early parsing
From: Michael Ellerman @ 2006-05-17 8:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Kumar Gala
Currently early_xmon() calls directly into debugger() if xmon=early is passed.
This ties the invocation of early xmon to the location of parse_early_param(),
which might change.
Tested on P5 LPAR and F50.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/setup-common.c | 3 ++-
arch/powerpc/kernel/setup.h | 1 +
arch/powerpc/kernel/setup_32.c | 3 +++
arch/powerpc/kernel/setup_64.c | 3 +++
4 files changed, 9 insertions(+), 1 deletion(-)
Index: to-merge/arch/powerpc/kernel/setup-common.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup-common.c
+++ to-merge/arch/powerpc/kernel/setup-common.c
@@ -443,6 +443,7 @@ void __init smp_setup_cpu_maps(void)
}
#endif /* CONFIG_SMP */
+int __initdata do_early_xmon;
#ifdef CONFIG_XMON
static int __init early_xmon(char *p)
{
@@ -456,7 +457,7 @@ static int __init early_xmon(char *p)
return 0;
}
xmon_init(1);
- debugger(NULL);
+ do_early_xmon = 1;
return 0;
}
Index: to-merge/arch/powerpc/kernel/setup.h
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup.h
+++ to-merge/arch/powerpc/kernel/setup.h
@@ -2,5 +2,6 @@
#define _POWERPC_KERNEL_SETUP_H
void check_for_initrd(void);
+extern int do_early_xmon;
#endif /* _POWERPC_KERNEL_SETUP_H */
Index: to-merge/arch/powerpc/kernel/setup_32.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_32.c
+++ to-merge/arch/powerpc/kernel/setup_32.c
@@ -296,6 +296,9 @@ void __init setup_arch(char **cmdline_p)
parse_early_param();
+ if (do_early_xmon)
+ debugger(NULL);
+
/* set up the bootmem stuff with available memory */
do_init_bootmem();
if ( ppc_md.progress ) ppc_md.progress("setup_arch: bootmem", 0x3eab);
Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -425,6 +425,9 @@ void __init setup_system(void)
parse_early_param();
+ if (do_early_xmon)
+ debugger(NULL);
+
check_smt_enabled();
smp_setup_cpu_maps();
^ permalink raw reply
* [PATCH 2/5] powerpc: Parse early parameters early, rather than sorta early
From: Michael Ellerman @ 2006-05-17 8:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Kumar Gala
In-Reply-To: <1147852841.148164.91320074069.qpush@concordia>
Currently we have call parse_early_param() earliyish, but not really very
early. In particular, it's not early enough to do things like mem=x or
crashkernel=blah, which is annoying.
So do it earlier. I've checked all the early param handlers, and none of them
look like they should have any trouble with this. I haven't tested the
booke_wdt ones though.
On 32-bit we were doing the CONFIG_CMDLINE logic twice, so don't.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/prom.c | 5 +++++
arch/powerpc/kernel/setup_32.c | 14 ++------------
arch/powerpc/kernel/setup_64.c | 5 -----
3 files changed, 7 insertions(+), 17 deletions(-)
Index: to-merge/arch/powerpc/kernel/prom.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom.c
+++ to-merge/arch/powerpc/kernel/prom.c
@@ -1292,6 +1292,11 @@ void __init early_init_devtree(void *par
lmb_init();
of_scan_flat_dt(early_init_dt_scan_root, NULL);
of_scan_flat_dt(early_init_dt_scan_memory, NULL);
+
+ /* Save command line for /proc/cmdline and then parse parameters */
+ strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
+ parse_early_param();
+
lmb_enforce_memory_limit(memory_limit);
lmb_analyze();
Index: to-merge/arch/powerpc/kernel/setup_32.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_32.c
+++ to-merge/arch/powerpc/kernel/setup_32.c
@@ -131,12 +131,6 @@ void __init machine_init(unsigned long d
/* Do some early initialization based on the flat device tree */
early_init_devtree(__va(dt_ptr));
- /* Check default command line */
-#ifdef CONFIG_CMDLINE
- if (cmd_line[0] == 0)
- strlcpy(cmd_line, CONFIG_CMDLINE, sizeof(cmd_line));
-#endif /* CONFIG_CMDLINE */
-
probe_machine();
#ifdef CONFIG_6xx
@@ -237,6 +231,8 @@ void __init setup_arch(char **cmdline_p)
{
extern void do_init_bootmem(void);
+ *cmdline_p = cmd_line;
+
/* so udelay does something sensible, assume <= 1000 bogomips */
loops_per_jiffy = 500000000 / HZ;
@@ -290,12 +286,6 @@ void __init setup_arch(char **cmdline_p)
init_mm.end_data = (unsigned long) _edata;
init_mm.brk = klimit;
- /* Save unparsed command line copy for /proc/cmdline */
- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
- *cmdline_p = cmd_line;
-
- parse_early_param();
-
if (do_early_xmon)
debugger(NULL);
Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -420,11 +420,6 @@ void __init setup_system(void)
*/
register_early_udbg_console();
- /* Save unparsed command line copy for /proc/cmdline */
- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
- parse_early_param();
-
if (do_early_xmon)
debugger(NULL);
^ permalink raw reply
* [PATCH 3/5] powerpc: Unify mem= handling
From: Michael Ellerman @ 2006-05-17 8:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Kumar Gala
In-Reply-To: <1147852841.148164.91320074069.qpush@concordia>
We currently do mem= handling in three seperate places. And as benh pointed out
I wrote two of them. Now that we parse command line parameters earlier we can
clean this mess up.
Moving the parsing out of prom_init means the device tree might be allocated
above the memory limit. If that happens we'd have to move it. As it happens
we already have logic to do that for kdump, so just genericise it.
This also means we might have reserved regions above the memory limit, if we
do the bootmem allocator will blow up, so we have to modify
lmb_enforce_memory_limit() to truncate the reserves as well.
Tested on P5 LPAR, iSeries, F50, 44p. Tested moving device tree on P5 and
44p and F50.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/machine_kexec_64.c | 5 +
arch/powerpc/kernel/prom.c | 89 +++++++++++++++++----------------
arch/powerpc/kernel/prom_init.c | 55 +-------------------
arch/powerpc/kernel/setup_64.c | 3 -
arch/powerpc/mm/lmb.c | 43 +++++++++++----
arch/powerpc/platforms/iseries/setup.c | 22 --------
include/asm-powerpc/kexec.h | 13 ++++
7 files changed, 100 insertions(+), 130 deletions(-)
Index: to-merge/arch/powerpc/kernel/machine_kexec_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/machine_kexec_64.c
+++ to-merge/arch/powerpc/kernel/machine_kexec_64.c
@@ -339,3 +339,8 @@ void __init kexec_setup(void)
{
export_htab_values();
}
+
+int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+ return (start + size) > crashk_res.start && start <= crashk_res.end;
+}
Index: to-merge/arch/powerpc/kernel/prom.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom.c
+++ to-merge/arch/powerpc/kernel/prom.c
@@ -50,6 +50,7 @@
#include <asm/machdep.h>
#include <asm/pSeries_reconfig.h>
#include <asm/pci-bridge.h>
+#include <asm/kexec.h>
#ifdef DEBUG
#define DBG(fmt...) printk(KERN_ERR fmt)
@@ -836,6 +837,42 @@ static unsigned long __init unflatten_dt
return mem;
}
+static int __init early_parse_mem(char *p)
+{
+ if (!p)
+ return 1;
+
+ memory_limit = PAGE_ALIGN(memparse(p, &p));
+ DBG("memory limit = 0x%lx\n", memory_limit);
+
+ return 0;
+}
+early_param("mem", early_parse_mem);
+
+/*
+ * The device tree may be allocated below our memory limit, or inside the
+ * crash kernel region for kdump. If so, move it out now.
+ */
+static void move_device_tree(void)
+{
+ unsigned long start, size;
+ void *p;
+
+ DBG("-> move_device_tree\n");
+
+ start = __pa(initial_boot_params);
+ size = initial_boot_params->totalsize;
+
+ if ((memory_limit && (start + size) > memory_limit) ||
+ overlaps_crashkernel(start, size)) {
+ p = __va(lmb_alloc_base(size, PAGE_SIZE, lmb.rmo_size));
+ memcpy(p, initial_boot_params, size);
+ initial_boot_params = (struct boot_param_header *)p;
+ DBG("Moved device tree to 0x%p\n", p);
+ }
+
+ DBG("<- move_device_tree\n");
+}
/**
* unflattens the device-tree passed by the firmware, creating the
@@ -1070,6 +1107,7 @@ static int __init early_init_dt_scan_cho
iommu_force_on = 1;
#endif
+ /* mem=x on the command line is the preferred mechanism */
lprop = of_get_flat_dt_prop(node, "linux,memory-limit", NULL);
if (lprop)
memory_limit = *lprop;
@@ -1123,17 +1161,6 @@ static int __init early_init_dt_scan_cho
DBG("Command line is: %s\n", cmd_line);
- if (strstr(cmd_line, "mem=")) {
- char *p, *q;
-
- for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) {
- q = p + 4;
- if (p > cmd_line && p[-1] != ' ')
- continue;
- memory_limit = memparse(q, &q);
- }
- }
-
/* break now */
return 1;
}
@@ -1297,11 +1324,6 @@ void __init early_init_devtree(void *par
strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
parse_early_param();
- lmb_enforce_memory_limit(memory_limit);
- lmb_analyze();
-
- DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
-
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
#ifdef CONFIG_CRASH_DUMP
@@ -1309,6 +1331,15 @@ void __init early_init_devtree(void *par
#endif
early_reserve_mem();
+ lmb_enforce_memory_limit(memory_limit);
+ lmb_analyze();
+
+ DBG("Phys. mem: %lx\n", lmb_phys_mem_size());
+
+ /* We may need to relocate the flat tree, do it now.
+ * FIXME .. and the initrd too? */
+ move_device_tree();
+
DBG("Scanning CPUs ...\n");
/* Retreive CPU related informations from the flat tree
@@ -2058,29 +2089,3 @@ int prom_update_property(struct device_n
return 0;
}
-#ifdef CONFIG_KEXEC
-/* We may have allocated the flat device tree inside the crash kernel region
- * in prom_init. If so we need to move it out into regular memory. */
-void kdump_move_device_tree(void)
-{
- unsigned long start, end;
- struct boot_param_header *new;
-
- start = __pa((unsigned long)initial_boot_params);
- end = start + initial_boot_params->totalsize;
-
- if (end < crashk_res.start || start > crashk_res.end)
- return;
-
- new = (struct boot_param_header*)
- __va(lmb_alloc(initial_boot_params->totalsize, PAGE_SIZE));
-
- memcpy(new, initial_boot_params, initial_boot_params->totalsize);
-
- initial_boot_params = new;
-
- DBG("Flat device tree blob moved to %p\n", initial_boot_params);
-
- /* XXX should we unreserve the old DT? */
-}
-#endif /* CONFIG_KEXEC */
Index: to-merge/arch/powerpc/kernel/prom_init.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom_init.c
+++ to-merge/arch/powerpc/kernel/prom_init.c
@@ -194,8 +194,6 @@ static int __initdata of_platform;
static char __initdata prom_cmd_line[COMMAND_LINE_SIZE];
-static unsigned long __initdata prom_memory_limit;
-
static unsigned long __initdata alloc_top;
static unsigned long __initdata alloc_top_high;
static unsigned long __initdata alloc_bottom;
@@ -594,16 +592,6 @@ static void __init early_cmdline_parse(v
}
#endif
- opt = strstr(RELOC(prom_cmd_line), RELOC("mem="));
- if (opt) {
- opt += 4;
- RELOC(prom_memory_limit) = prom_memparse(opt, (const char **)&opt);
-#ifdef CONFIG_PPC64
- /* Align to 16 MB == size of ppc64 large page */
- RELOC(prom_memory_limit) = ALIGN(RELOC(prom_memory_limit), 0x1000000);
-#endif
- }
-
#ifdef CONFIG_KEXEC
/*
* crashkernel=size@addr specifies the location to reserve for
@@ -1115,29 +1103,6 @@ static void __init prom_init_mem(void)
}
/*
- * If prom_memory_limit is set we reduce the upper limits *except* for
- * alloc_top_high. This must be the real top of RAM so we can put
- * TCE's up there.
- */
-
- RELOC(alloc_top_high) = RELOC(ram_top);
-
- if (RELOC(prom_memory_limit)) {
- if (RELOC(prom_memory_limit) <= RELOC(alloc_bottom)) {
- prom_printf("Ignoring mem=%x <= alloc_bottom.\n",
- RELOC(prom_memory_limit));
- RELOC(prom_memory_limit) = 0;
- } else if (RELOC(prom_memory_limit) >= RELOC(ram_top)) {
- prom_printf("Ignoring mem=%x >= ram_top.\n",
- RELOC(prom_memory_limit));
- RELOC(prom_memory_limit) = 0;
- } else {
- RELOC(ram_top) = RELOC(prom_memory_limit);
- RELOC(rmo_top) = min(RELOC(rmo_top), RELOC(prom_memory_limit));
- }
- }
-
- /*
* Setup our top alloc point, that is top of RMO or top of
* segment 0 when running non-LPAR.
* Some RS64 machines have buggy firmware where claims up at
@@ -1149,9 +1114,9 @@ static void __init prom_init_mem(void)
RELOC(rmo_top) = RELOC(ram_top);
RELOC(rmo_top) = min(0x30000000ul, RELOC(rmo_top));
RELOC(alloc_top) = RELOC(rmo_top);
+ RELOC(alloc_top_high) = RELOC(ram_top);
prom_printf("memory layout at init:\n");
- prom_printf(" memory_limit : %x (16 MB aligned)\n", RELOC(prom_memory_limit));
prom_printf(" alloc_bottom : %x\n", RELOC(alloc_bottom));
prom_printf(" alloc_top : %x\n", RELOC(alloc_top));
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
@@ -1348,16 +1313,10 @@ static void __init prom_initialize_tce_t
reserve_mem(local_alloc_bottom, local_alloc_top - local_alloc_bottom);
- if (RELOC(prom_memory_limit)) {
- /*
- * We align the start to a 16MB boundary so we can map
- * the TCE area using large pages if possible.
- * The end should be the top of RAM so no need to align it.
- */
- RELOC(prom_tce_alloc_start) = _ALIGN_DOWN(local_alloc_bottom,
- 0x1000000);
- RELOC(prom_tce_alloc_end) = local_alloc_top;
- }
+ /* These are only really needed if there is a memory limit in
+ * effect, but we don't know so export them always. */
+ RELOC(prom_tce_alloc_start) = local_alloc_bottom;
+ RELOC(prom_tce_alloc_end) = local_alloc_top;
/* Flag the first invalid entry */
prom_debug("ending prom_initialize_tce_table\n");
@@ -2265,10 +2224,6 @@ unsigned long __init prom_init(unsigned
/*
* Fill in some infos for use by the kernel later on
*/
- if (RELOC(prom_memory_limit))
- prom_setprop(_prom->chosen, "/chosen", "linux,memory-limit",
- &RELOC(prom_memory_limit),
- sizeof(prom_memory_limit));
#ifdef CONFIG_PPC64
if (RELOC(ppc64_iommu_off))
prom_setprop(_prom->chosen, "/chosen", "linux,iommu-off",
Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -353,9 +353,6 @@ void __init setup_system(void)
{
DBG(" -> setup_system()\n");
-#ifdef CONFIG_KEXEC
- kdump_move_device_tree();
-#endif
/*
* Unflatten the device-tree passed by prom_init or kexec
*/
Index: to-merge/arch/powerpc/mm/lmb.c
===================================================================
--- to-merge.orig/arch/powerpc/mm/lmb.c
+++ to-merge/arch/powerpc/mm/lmb.c
@@ -89,20 +89,25 @@ static long __init lmb_regions_adjacent(
return lmb_addrs_adjacent(base1, size1, base2, size2);
}
-/* Assumption: base addr of region 1 < base addr of region 2 */
-static void __init lmb_coalesce_regions(struct lmb_region *rgn,
- unsigned long r1, unsigned long r2)
+static void __init lmb_remove_region(struct lmb_region *rgn, unsigned long r)
{
unsigned long i;
- rgn->region[r1].size += rgn->region[r2].size;
- for (i=r2; i < rgn->cnt-1; i++) {
- rgn->region[i].base = rgn->region[i+1].base;
- rgn->region[i].size = rgn->region[i+1].size;
+ for (i = r; i < rgn->cnt - 1; i++) {
+ rgn->region[i].base = rgn->region[i + 1].base;
+ rgn->region[i].size = rgn->region[i + 1].size;
}
rgn->cnt--;
}
+/* Assumption: base addr of region 1 < base addr of region 2 */
+static void __init lmb_coalesce_regions(struct lmb_region *rgn,
+ unsigned long r1, unsigned long r2)
+{
+ rgn->region[r1].size += rgn->region[r2].size;
+ lmb_remove_region(rgn, r2);
+}
+
/* This routine called with relocation disabled. */
void __init lmb_init(void)
{
@@ -294,17 +299,16 @@ unsigned long __init lmb_end_of_DRAM(voi
return (lmb.memory.region[idx].base + lmb.memory.region[idx].size);
}
-/*
- * Truncate the lmb list to memory_limit if it's set
- * You must call lmb_analyze() after this.
- */
+/* You must call lmb_analyze() after this. */
void __init lmb_enforce_memory_limit(unsigned long memory_limit)
{
unsigned long i, limit;
+ struct lmb_property *p;
if (! memory_limit)
return;
+ /* Truncate the lmb regions to satisfy the memory limit. */
limit = memory_limit;
for (i = 0; i < lmb.memory.cnt; i++) {
if (limit > lmb.memory.region[i].size) {
@@ -316,4 +320,21 @@ void __init lmb_enforce_memory_limit(uns
lmb.memory.cnt = i + 1;
break;
}
+
+ lmb.rmo_size = lmb.memory.region[0].size;
+
+ /* And truncate any reserves above the limit also. */
+ for (i = 0; i < lmb.reserved.cnt; i++) {
+ p = &lmb.reserved.region[i];
+
+ if (p->base > memory_limit)
+ p->size = 0;
+ else if ((p->base + p->size) > memory_limit)
+ p->size = memory_limit - p->base;
+
+ if (p->size == 0) {
+ lmb_remove_region(&lmb.reserved, i);
+ i--;
+ }
+ }
}
Index: to-merge/arch/powerpc/platforms/iseries/setup.c
===================================================================
--- to-merge.orig/arch/powerpc/platforms/iseries/setup.c
+++ to-merge/arch/powerpc/platforms/iseries/setup.c
@@ -90,8 +90,6 @@ extern unsigned long embedded_sysmap_end
extern unsigned long iSeries_recal_tb;
extern unsigned long iSeries_recal_titan;
-static unsigned long cmd_mem_limit;
-
struct MemoryBlock {
unsigned long absStart;
unsigned long absEnd;
@@ -1023,8 +1021,6 @@ void build_flat_dt(struct iseries_flat_d
/* /chosen */
dt_start_node(dt, "chosen");
dt_prop_str(dt, "bootargs", cmd_line);
- if (cmd_mem_limit)
- dt_prop_u64(dt, "linux,memory-limit", cmd_mem_limit);
dt_end_node(dt);
dt_cpus(dt);
@@ -1050,29 +1046,11 @@ void * __init iSeries_early_setup(void)
iSeries_get_cmdline();
- /* Save unparsed command line copy for /proc/cmdline */
- strlcpy(saved_command_line, cmd_line, COMMAND_LINE_SIZE);
-
- /* Parse early parameters, in particular mem=x */
- parse_early_param();
-
build_flat_dt(&iseries_dt, phys_mem_size);
return (void *) __pa(&iseries_dt);
}
-/*
- * On iSeries we just parse the mem=X option from the command line.
- * On pSeries it's a bit more complicated, see prom_init_mem()
- */
-static int __init early_parsemem(char *p)
-{
- if (p)
- cmd_mem_limit = ALIGN(memparse(p, &p), PAGE_SIZE);
- return 0;
-}
-early_param("mem", early_parsemem);
-
static void hvputc(char c)
{
if (c == '\n')
Index: to-merge/include/asm-powerpc/kexec.h
===================================================================
--- to-merge.orig/include/asm-powerpc/kexec.h
+++ to-merge/include/asm-powerpc/kexec.h
@@ -31,9 +31,10 @@
#define KEXEC_ARCH KEXEC_ARCH_PPC
#endif
+#ifndef __ASSEMBLY__
+
#ifdef CONFIG_KEXEC
-#ifndef __ASSEMBLY__
#ifdef __powerpc64__
/*
* This function is responsible for capturing register states if coming
@@ -123,8 +124,16 @@ extern int default_machine_kexec_prepare
extern void default_machine_crash_shutdown(struct pt_regs *regs);
extern void machine_kexec_simple(struct kimage *image);
+extern int overlaps_crashkernel(unsigned long start, unsigned long size);
+
+#else /* !CONFIG_KEXEC */
+
+static inline int overlaps_crashkernel(unsigned long start, unsigned long size)
+{
+ return 0;
+}
-#endif /* ! __ASSEMBLY__ */
#endif /* CONFIG_KEXEC */
+#endif /* ! __ASSEMBLY__ */
#endif /* __KERNEL__ */
#endif /* _ASM_POWERPC_KEXEC_H */
^ permalink raw reply
* [PATCH 4/5] powerpc: Kdump header cleanup
From: Michael Ellerman @ 2006-05-17 8:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Kumar Gala
In-Reply-To: <1147852841.148164.91320074069.qpush@concordia>
We need to know the base address of the kdump kernel even when we're not a
kdump kernel, so add a #define for it. Move the logic that sets the kdump
kernelbase into kdump.h instead of page.h.
Rename kdump_setup() to setup_kdump_trampoline() to make it clearer what it's
doing, and add an empty definition for the !CRASH_DUMP case to avoid a
#define in the C code. Similarly, add reserve_kdump_trampoline().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/crash_dump.c | 11 ++++++++---
arch/powerpc/kernel/prom.c | 4 +---
arch/powerpc/kernel/setup_64.c | 4 +---
include/asm-powerpc/kdump.h | 29 +++++++++++++++++++++++++++--
include/asm-powerpc/page.h | 8 +-------
5 files changed, 38 insertions(+), 18 deletions(-)
Index: to-merge/arch/powerpc/kernel/crash_dump.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/crash_dump.c
+++ to-merge/arch/powerpc/kernel/crash_dump.c
@@ -25,6 +25,11 @@
#define DBG(fmt...)
#endif
+void reserve_kdump_trampoline(void)
+{
+ lmb_reserve(0, KDUMP_RESERVE_LIMIT);
+}
+
static void __init create_trampoline(unsigned long addr)
{
/* The maximum range of a single instruction branch, is the current
@@ -39,11 +44,11 @@ static void __init create_trampoline(uns
create_branch(addr + 4, addr + PHYSICAL_START, 0);
}
-void __init kdump_setup(void)
+void __init setup_kdump_trampoline(void)
{
unsigned long i;
- DBG(" -> kdump_setup()\n");
+ DBG(" -> setup_kdump_trampoline()\n");
for (i = KDUMP_TRAMPOLINE_START; i < KDUMP_TRAMPOLINE_END; i += 8) {
create_trampoline(i);
@@ -52,7 +57,7 @@ void __init kdump_setup(void)
create_trampoline(__pa(system_reset_fwnmi) - PHYSICAL_START);
create_trampoline(__pa(machine_check_fwnmi) - PHYSICAL_START);
- DBG(" <- kdump_setup()\n");
+ DBG(" <- setup_kdump_trampoline()\n");
}
#ifdef CONFIG_PROC_VMCORE
Index: to-merge/arch/powerpc/kernel/prom.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom.c
+++ to-merge/arch/powerpc/kernel/prom.c
@@ -1326,9 +1326,7 @@ void __init early_init_devtree(void *par
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
-#ifdef CONFIG_CRASH_DUMP
- lmb_reserve(0, KDUMP_RESERVE_LIMIT);
-#endif
+ reserve_kdump_trampoline();
early_reserve_mem();
lmb_enforce_memory_limit(memory_limit);
Index: to-merge/arch/powerpc/kernel/setup_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/setup_64.c
+++ to-merge/arch/powerpc/kernel/setup_64.c
@@ -199,9 +199,7 @@ void __init early_setup(unsigned long dt
/* Probe the machine type */
probe_machine();
-#ifdef CONFIG_CRASH_DUMP
- kdump_setup();
-#endif
+ setup_kdump_trampoline();
DBG("Found, Initializing memory management...\n");
Index: to-merge/include/asm-powerpc/kdump.h
===================================================================
--- to-merge.orig/include/asm-powerpc/kdump.h
+++ to-merge/include/asm-powerpc/kdump.h
@@ -1,13 +1,38 @@
#ifndef _PPC64_KDUMP_H
#define _PPC64_KDUMP_H
+/* Kdump kernel runs at 32 MB, change at your peril. */
+#define KDUMP_KERNELBASE 0x2000000
+
/* How many bytes to reserve at zero for kdump. The reserve limit should
- * be greater or equal to the trampoline's end address. */
+ * be greater or equal to the trampoline's end address.
+ * Reserve to the end of the FWNMI area, see head_64.S */
#define KDUMP_RESERVE_LIMIT 0x8000
+#ifdef CONFIG_CRASH_DUMP
+
+#define PHYSICAL_START KDUMP_KERNELBASE
#define KDUMP_TRAMPOLINE_START 0x0100
#define KDUMP_TRAMPOLINE_END 0x3000
-extern void kdump_setup(void);
+#else /* !CONFIG_CRASH_DUMP */
+
+#define PHYSICAL_START 0x0
+
+#endif /* CONFIG_CRASH_DUMP */
+
+#ifndef __ASSEMBLY__
+#ifdef CONFIG_CRASH_DUMP
+
+extern void reserve_kdump_trampoline(void);
+extern void setup_kdump_trampoline(void);
+
+#else /* !CONFIG_CRASH_DUMP */
+
+static inline void reserve_kdump_trampoline(void) { ; }
+static inline void setup_kdump_trampoline(void) { ; }
+
+#endif /* CONFIG_CRASH_DUMP */
+#endif /* __ASSEMBLY__ */
#endif /* __PPC64_KDUMP_H */
Index: to-merge/include/asm-powerpc/page.h
===================================================================
--- to-merge.orig/include/asm-powerpc/page.h
+++ to-merge/include/asm-powerpc/page.h
@@ -13,6 +13,7 @@
#ifdef __KERNEL__
#include <linux/config.h>
#include <asm/asm-compat.h>
+#include <asm/kdump.h>
/*
* On PPC32 page size is 4K. For PPC64 we support either 4K or 64K software
@@ -52,13 +53,6 @@
* If you want to test if something's a kernel address, use is_kernel_addr().
*/
-#ifdef CONFIG_CRASH_DUMP
-/* Kdump kernel runs at 32 MB, change at your peril. */
-#define PHYSICAL_START 0x2000000
-#else
-#define PHYSICAL_START 0x0
-#endif
-
#define PAGE_OFFSET ASM_CONST(CONFIG_KERNEL_START)
#define KERNELBASE (PAGE_OFFSET + PHYSICAL_START)
^ permalink raw reply
* [PATCH 5/5] powerpc: Move crashkernel= handling into the kernel.
From: Michael Ellerman @ 2006-05-17 8:00 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev, Kumar Gala
In-Reply-To: <1147852841.148164.91320074069.qpush@concordia>
Currently we parse crashkernel= in prom_init.c, which means for other boot
loaders to support Kdump they also need to parse the command line and setup
the appropriate crash kernel properties.
With early param parsing done earlier we can do crashkernel= parsing in the
early kernel code and avoid the need for every bootloader to do it for us.
We still support the device tree properties if they're specified by firmware,
however the command line overrides anything we find there.
Tested on P5 LPAR.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/kernel/machine_kexec_64.c | 94 +++++++++++++++++++++++++++++++++
arch/powerpc/kernel/prom.c | 1
arch/powerpc/kernel/prom_init.c | 54 ------------------
include/asm-powerpc/kexec.h | 2
4 files changed, 97 insertions(+), 54 deletions(-)
Index: to-merge/arch/powerpc/kernel/machine_kexec_64.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/machine_kexec_64.c
+++ to-merge/arch/powerpc/kernel/machine_kexec_64.c
@@ -21,6 +21,7 @@
#include <asm/machdep.h>
#include <asm/cacheflush.h>
#include <asm/paca.h>
+#include <asm/lmb.h>
#include <asm/mmu.h>
#include <asm/sections.h> /* _end */
#include <asm/prom.h>
@@ -335,9 +336,102 @@ static void __init export_htab_values(vo
of_node_put(node);
}
+static struct property crashk_base_prop = {
+ .name = "linux,crashkernel-base",
+ .length = sizeof(unsigned long),
+ .value = (unsigned char *)&crashk_res.start,
+};
+
+static unsigned long crashk_size;
+
+static struct property crashk_size_prop = {
+ .name = "linux,crashkernel-size",
+ .length = sizeof(unsigned long),
+ .value = (unsigned char *)&crashk_size,
+};
+
+static void __init export_crashk_values(void)
+{
+ struct device_node *node;
+ struct property *prop;
+
+ node = of_find_node_by_path("/chosen");
+ if (!node)
+ return;
+
+ /* There might be existing crash kernel properties, but we can't
+ * be sure what's in them, so remove them. */
+ prop = of_find_property(node, "linux,crashkernel-base", NULL);
+ if (prop)
+ prom_remove_property(node, prop);
+
+ prop = of_find_property(node, "linux,crashkernel-size", NULL);
+ if (prop)
+ prom_remove_property(node, prop);
+
+ if (crashk_res.start != 0) {
+ prom_add_property(node, &crashk_base_prop);
+ crashk_size = crashk_res.end - crashk_res.start + 1;
+ prom_add_property(node, &crashk_size_prop);
+ }
+
+ of_node_put(node);
+}
+
void __init kexec_setup(void)
{
export_htab_values();
+ export_crashk_values();
+}
+
+static int __init early_parse_crashk(char *p)
+{
+ unsigned long size;
+
+ if (!p)
+ return 1;
+
+ size = memparse(p, &p);
+
+ if (*p == '@')
+ crashk_res.start = memparse(p + 1, &p);
+ else
+ crashk_res.start = KDUMP_KERNELBASE;
+
+ crashk_res.end = crashk_res.start + size - 1;
+
+ return 0;
+}
+early_param("crashkernel", early_parse_crashk);
+
+void __init reserve_crashkernel(void)
+{
+ unsigned long size;
+
+ if (crashk_res.start == 0)
+ return;
+
+ /* We might have got these values via the command line or the
+ * device tree, either way sanitise them now. */
+
+ size = crashk_res.end - crashk_res.start + 1;
+
+ if (crashk_res.start != KDUMP_KERNELBASE)
+ printk("Crash kernel location must be 0x%x\n",
+ KDUMP_KERNELBASE);
+
+ crashk_res.start = KDUMP_KERNELBASE;
+ size = PAGE_ALIGN(size);
+ crashk_res.end = crashk_res.start + size - 1;
+
+ /* Crash kernel trumps memory limit */
+ if (memory_limit && memory_limit <= crashk_res.end) {
+ memory_limit = crashk_res.end + 1;
+ printk("Adjusted memory limit for crashkernel, now 0x%lx\n",
+ memory_limit);
+ }
+
+ lmb_reserve(crashk_res.start, size);
}
int overlaps_crashkernel(unsigned long start, unsigned long size)
Index: to-merge/arch/powerpc/kernel/prom.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom.c
+++ to-merge/arch/powerpc/kernel/prom.c
@@ -1327,6 +1327,7 @@ void __init early_init_devtree(void *par
/* Reserve LMB regions used by kernel, initrd, dt, etc... */
lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);
reserve_kdump_trampoline();
+ reserve_crashkernel();
early_reserve_mem();
lmb_enforce_memory_limit(memory_limit);
Index: to-merge/arch/powerpc/kernel/prom_init.c
===================================================================
--- to-merge.orig/arch/powerpc/kernel/prom_init.c
+++ to-merge/arch/powerpc/kernel/prom_init.c
@@ -200,11 +200,6 @@ static unsigned long __initdata alloc_bo
static unsigned long __initdata rmo_top;
static unsigned long __initdata ram_top;
-#ifdef CONFIG_KEXEC
-static unsigned long __initdata prom_crashk_base;
-static unsigned long __initdata prom_crashk_size;
-#endif
-
static struct mem_map_entry __initdata mem_reserve_map[MEM_RESERVE_MAP_SIZE];
static int __initdata mem_reserve_cnt;
@@ -591,35 +586,6 @@ static void __init early_cmdline_parse(v
RELOC(iommu_force_on) = 1;
}
#endif
-
-#ifdef CONFIG_KEXEC
- /*
- * crashkernel=size@addr specifies the location to reserve for
- * crash kernel.
- */
- opt = strstr(RELOC(prom_cmd_line), RELOC("crashkernel="));
- if (opt) {
- opt += 12;
- RELOC(prom_crashk_size) =
- prom_memparse(opt, (const char **)&opt);
-
- if (ALIGN(RELOC(prom_crashk_size), 0x1000000) !=
- RELOC(prom_crashk_size)) {
- prom_printf("Warning: crashkernel size is not "
- "aligned to 16MB\n");
- }
-
- /*
- * At present, the crash kernel always run at 32MB.
- * Just ignore whatever user passed.
- */
- RELOC(prom_crashk_base) = 0x2000000;
- if (*opt == '@') {
- prom_printf("Warning: PPC64 kdump kernel always runs "
- "at 32 MB\n");
- }
- }
-#endif
}
#ifdef CONFIG_PPC_PSERIES
@@ -1122,12 +1088,6 @@ static void __init prom_init_mem(void)
prom_printf(" alloc_top_hi : %x\n", RELOC(alloc_top_high));
prom_printf(" rmo_top : %x\n", RELOC(rmo_top));
prom_printf(" ram_top : %x\n", RELOC(ram_top));
-#ifdef CONFIG_KEXEC
- if (RELOC(prom_crashk_base)) {
- prom_printf(" crashk_base : %x\n", RELOC(prom_crashk_base));
- prom_printf(" crashk_size : %x\n", RELOC(prom_crashk_size));
- }
-#endif
}
@@ -2187,10 +2147,6 @@ unsigned long __init prom_init(unsigned
*/
prom_init_mem();
-#ifdef CONFIG_KEXEC
- if (RELOC(prom_crashk_base))
- reserve_mem(RELOC(prom_crashk_base), RELOC(prom_crashk_size));
-#endif
/*
* Determine which cpu is actually running right _now_
*/
@@ -2243,16 +2199,6 @@ unsigned long __init prom_init(unsigned
}
#endif
-#ifdef CONFIG_KEXEC
- if (RELOC(prom_crashk_base)) {
- prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-base",
- PTRRELOC(&prom_crashk_base),
- sizeof(RELOC(prom_crashk_base)));
- prom_setprop(_prom->chosen, "/chosen", "linux,crashkernel-size",
- PTRRELOC(&prom_crashk_size),
- sizeof(RELOC(prom_crashk_size)));
- }
-#endif
/*
* Fixup any known bugs in the device-tree
*/
Index: to-merge/include/asm-powerpc/kexec.h
===================================================================
--- to-merge.orig/include/asm-powerpc/kexec.h
+++ to-merge/include/asm-powerpc/kexec.h
@@ -133,6 +133,8 @@ static inline int overlaps_crashkernel(u
return 0;
}
+static inline void reserve_crashkernel(void) { ; }
+
#endif /* CONFIG_KEXEC */
#endif /* ! __ASSEMBLY__ */
#endif /* __KERNEL__ */
^ permalink raw reply
* Re: [SOLVED] MPC8248 goes berserk when printing messages on the SMC console
From: Laurent Pinchart @ 2006-05-17 9:38 UTC (permalink / raw)
To: linuxppc-embedded
In-Reply-To: <200605161709.36387.laurent.pinchart@tbox.biz>
http://www.freescale.com/webapp/sps/utils/SingleFaq.jsp?FAQ-11241.xml
"Question. Board hangs when the 8260 data cache is enabled.
Answer. We have found that in some systems, changing the pipline depth to 0
in the BCR register (BCR[PLDP] = 1) fixes any data cache issues."
I don't know what those "some systems" are, but it seems that on all the
others the pipeline depth must be set to 1 (BCR[PLDP] = 0). I don't know why,
and it seems that Freescale doesn't either.
Laurent Pinchart
^ permalink raw reply
* Does the CPM uart driver need more memory barriers ?
From: Laurent Pinchart @ 2006-05-17 9:43 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 271 bytes --]
Hi everybody,
while trying to debug a serial port issue, I found out some code might seemed
to miss write memory barriers. Does the volatile keyword guarantee that gcc
will no reorder memory writes, or is the attached patched needed ?
Best regards,
Laurent Pinchart
[-- Attachment #2: cpm_wmb.patch --]
[-- Type: text/x-diff, Size: 578 bytes --]
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index b7bf4c6..545f56c 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -1032,6 +1032,7 @@ static void cpm_uart_console_write(struc
*cp = *s;
bdp->cbd_datlen = 1;
+ wmb();
bdp->cbd_sc |= BD_SC_READY;
if (bdp->cbd_sc & BD_SC_WRAP)
@@ -1048,6 +1049,7 @@ static void cpm_uart_console_write(struc
*cp = 13;
bdp->cbd_datlen = 1;
+ wmb();
bdp->cbd_sc |= BD_SC_READY;
if (bdp->cbd_sc & BD_SC_WRAP)
^ permalink raw reply related
* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Takashi Iwai @ 2006-05-17 9:47 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev list, Johannes Berg, ALSA development,
Jaroslav Kysela, Benjamin Berg
In-Reply-To: <1147817058.6753.7.camel@localhost.localdomain>
At Wed, 17 May 2006 08:04:18 +1000,
Benjamin Herrenschmidt wrote:
>
> On Tue, 2006-05-16 at 14:31 +0200, Jaroslav Kysela wrote:
> > On Tue, 16 May 2006, Johannes Berg wrote:
> >
> > > Apparently all alsa userspace programs including alsamixer suck. Hence,
> > > this patch is required to make them work properly. Why is it so hard to
> > > do these additions/subtractions in the program or maybe even in the alsa
> > > library? The alsa libraries already think they know better and mess up
> > > all kinds of things.
> >
> > It's better to fix apps, if they are broken.
>
> Problem is, they are currently all broken (pretty much) and thus unless
> we want to release a driver that won't work with any current distros,
> we'll have to whack the ranges :(
Well that's a big dilemma. Surely you want a stable driver and don't
want to see the flood of bug reports.
The mixer stuff is the weakest point in the current ALSA
implementation, and it has to be sorted out better.
Almost all existing mixer GUI programs are more or less buggy or quite
user-unfriendly.
Takashi
^ permalink raw reply
* [RFC PATCH 00/09] robust VM per_cpu variables
From: Steven Rostedt @ 2006-05-17 9:54 UTC (permalink / raw)
To: LKML
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
Andi Kleen, ralf, Marc Gauthier, lethal, schwidefsky, linux390,
davem, parisc-linux
[-- Attachment #1: Type: TEXT/PLAIN, Size: 3716 bytes --]
(I tried to include all arch maintianers and memory maintainers, if I
missed someone, please let me know).
OK, as promised, I've got a working VM percpu solution.
A little history: please read the thread http://lkml.org/lkml/2006/4/14/137
Preivously I noticed that the per_cpu variables were implemented with
a little hack that Rusty Russell wrote up. I call it a hack because,
for modules an arbitrary number was used to hold all per_cpu variables
that would be used in the kernel or in modules. If this number was too
big, you waste the memory that is allocated for it, and if it were
too small, you wont be able to load all the modules that are required.
My first attempt to fix this introduced another dereference, to allow
for modules to allocate their own memory. This was quickly shot down,
and for good reason, because dereferences kill performance, and don't
play nice with large SMP systems that depend on per_cpu being fast.
But that first attempt had one benefit. It had good responses on how
to actually fix the problem. Without the first try, I would not have
tried this approach.
So what is this solution?
I now place the per_cpu variables into VM, such that the pages are
only allocated when needed. All the architecture needs to do is
supply a VM address range, size for each CPU to use (note this
implementation expects all the VM CPU areas to be together), and
three functions to allow for allocating page tables at bootup.
The bootup page table allocations are needed because the percpu
variables are used before the system initializes the memory. So
bootmem is needed to load the page tables.
But that's it! No more hacks for architectures with lots of CPUS and
NUMA to implement their own percpu algorithms. They just supply the
functions to allocate the variables, and the memory will be loaded
appropriately. So all architectures with VM can use the generic
solution. Does the main-line kernel support any architectures that
doesn't have a VM?
Another benefit is that this approach removes the one redirection that
was already used in the generic solution. Since the virtual memory
of the architecture for the per_cpu is static, the calculation to
find the variable is done with constants. So this is another win
for this solution.
So the three things that this patch gives us are:
1) Robust per_cpu. No more guessing the size of the per_cpu variable
sections. Default VM is 1 Meg per cpu. If you use more than that
I guess you're SOL.
2) Generic solution for all architectures. No more fancy hacks to
get the per cpu offest.
3) Removes the inderection of the current per_cpu generic solution.
The set of patches that I have implement this for the i386 architecture
and lays out the ground work for others. The i386 implementation I did
was mainly a hack. Nick Piggin suggested that before I do too much
work, I should post my stuff and ask for comments. That's what I'm doing
now.
This patch set works for my laptop (P4 HT) and I haven't tested
it with any other configuration. The implementation that I did for
i386 was only to get it to work and is not flexible. It needs much
better implementation, and I ask for help with that.
I basically concentrated to the core stuff. Another nice thing about
this patch set is that it needs both CONFIG_HAS_VM_PERCPU and
__ARCH_HAS_VM_PERCPU to take advantage of the VM percpu implementation.
Without these set, it defaults to the old usage. This way we
can slowly implement each architecture, in an incremental fashion.
OK, let'er rip. Flame me, yell at me, curse me, but please give me
feedback.
Thanks for your time.
-- Steve
PS. The attached module was used to test this patch on my laptop.
[-- Attachment #2: Type: TEXT/x-csrc, Size: 666 bytes --]
#include <linux/module.h>
#include <linux/percpu.h>
#define BIG_SIZE 4200
DEFINE_PER_CPU(int , bigarray[BIG_SIZE]);
static int __init percpu_init(void)
{
int i, x;
for (i=0; cpu_possible(i) ; i++)
for (x=0; x < BIG_SIZE; x++) {
if (!(x%100))
printk("processing %d:%d\n", i, x);
per_cpu(bigarray[x], i) = 10000 + x;
}
return 0;
}
static void __exit percpu_exit(void)
{
int i;
for (i=1; i < BIG_SIZE; i <<= 1)
printk("bigarray[%d] = %d\n", i, per_cpu(bigarray[i],0));
}
module_init(percpu_init);
module_exit(percpu_exit);
MODULE_AUTHOR("My name here");
MODULE_DESCRIPTION("percpu!");
MODULE_LICENSE("GPL");
^ permalink raw reply
* [RFC PATCH 01/09] robust VM per_cpu core
From: Steven Rostedt @ 2006-05-17 9:56 UTC (permalink / raw)
To: LKML
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
Andi Kleen, ralf, Marc Gauthier, lethal, schwidefsky, linux390,
davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170547490.8408@gandalf.stny.rr.com>
This is the VM per_cpu core patch. It includes the mm/per_cpu.c file
that is used to initialize and update per_cpu variables at startup
and module load.
To use this, the arch must define CONFIG_HAS_VM_PERCPU and
__ARCH_HAS_VM_PERCPU.
Also the following must be defined:
PERCPU_START - start of the percpu VM area
PERCPU_SIZE - size of the percpu VM area for each CPU so that the
total size would be PERCPU_SIZE * NR_CPUS
As well as the following three functions:
pud_t *pud_boot_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
int cpu);
pmd_t *pmd_boot_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
int cpu);
pte_t *pte_boot_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long addr,
int cpu);
The above functions are to allocate page tables from bootmem because the
percpu is initialized right after setup_arch in init/main.c
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-2.6.16-test/mm/percpu.c
===================================================================
--- /dev/null 1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.16-test/mm/percpu.c 2006-05-17 04:39:52.000000000 -0400
@@ -0,0 +1,287 @@
+/*
+ * linux/mm/percpu.c
+ *
+ * Copyright (C) 2006 Steven Rostedt <rostedt@goodmis.org>
+ *
+ * Some of this code was influenced by mm/vmalloc.c
+ *
+ * The percpu variables need to always have the same offset from one CPU to
+ * the next no matter if the percpu variable is defined in the kernel or
+ * inside a module. So to guarentee that the offset is the same for both,
+ * they are mapped into virtual memory.
+ *
+ * Since the percpu variables are used before memory is initialized, the
+ * inital setup must be done with bootmem, and thus vmalloc code can not be
+ * used.
+ *
+ * Credits:
+ * -------
+ * This goes to lots of people that inspired me on LKML, and responded to
+ * my first (horrible) implementation of robust per_cpu variables.
+ *
+ * Also many thanks to Rusty Russell in his generic per_cpu implementation.
+ */
+
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+
+#include <linux/bootmem.h>
+
+#include <asm/uaccess.h>
+#include <asm/tlbflush.h>
+
+static int __init percpu_boot_alloc(unsigned long addr, unsigned long size,
+ int node);
+
+/*
+ * percpu_allocated keeps track of the actual allocated memory. It
+ * always points to the page after the last page in VM that was allocated.
+ *
+ * Yes this is also a per_cpu variable :)
+ * It gets updated after the copys are made.
+ */
+static DEFINE_PER_CPU(unsigned long, percpu_allocated);
+
+static char * __init per_cpu_allocate_init(unsigned long size, int cpu)
+{
+ unsigned long addr;
+
+ addr = PERCPU_START+(cpu*PERCPU_SIZE);
+ BUG_ON(percpu_boot_alloc(addr, size, cpu));
+
+ return (char*)addr;
+
+}
+
+/**
+ * setup_per_cpu_areas - initialization of VM per_cpu variables
+ *
+ * Allocate pages in VM for the per_cpu variables
+ * of the kernel.
+ */
+void __init setup_per_cpu_areas(void)
+{
+ unsigned long size, i;
+ char *ptr;
+
+ /* Copy section for each CPU (we discard the original) */
+ size = ALIGN(__per_cpu_end - __per_cpu_start, SMP_CACHE_BYTES);
+
+ for (i = 0; i < NR_CPUS; i++, ptr += size) {
+ ptr = per_cpu_allocate_init(size, i);
+ memcpy(ptr, __per_cpu_start, __per_cpu_end - __per_cpu_start);
+ wmb();
+ per_cpu(percpu_allocated, i) =
+ PAGE_ALIGN((unsigned long)ptr + size);
+ }
+}
+
+static __init int percpu_boot_pte_alloc(pmd_t *pmd, unsigned long addr,
+ unsigned long end, int node)
+{
+ pte_t *pte;
+
+ pte = pte_boot_alloc(&init_mm, pmd, addr, node);
+ if (!pte)
+ return -ENOMEM;
+ do {
+ void *page;
+ WARN_ON(!pte_none(*pte));
+ page = alloc_bootmem_pages(PAGE_SIZE);
+ if (!page)
+ return -ENOMEM;
+ set_pte_at(&init_mm, addr, pte, mk_pte(virt_to_page(page),
+ PAGE_KERNEL));
+ } while (pte++, addr += PAGE_SIZE, addr < end);
+ return 0;
+}
+
+static __init int percpu_boot_pmd_alloc(pud_t *pud, unsigned long addr,
+ unsigned long end, int node)
+{
+ pmd_t *pmd;
+ unsigned long next;
+
+ pmd = pmd_boot_alloc(&init_mm, pud, addr, node);
+ if (!pud)
+ return -ENOMEM;
+ do {
+ next = pmd_addr_end(addr, end);
+ if (percpu_boot_pte_alloc(pmd, addr, next, node))
+ return -ENOMEM;
+ } while (pmd++, addr = next, addr < end);
+ return 0;
+}
+
+static __init int percpu_boot_pud_alloc(pgd_t *pgd, unsigned long addr,
+ unsigned long end, int node)
+{
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_boot_alloc(&init_mm, pgd, addr, node);
+ if (!pud)
+ return -ENOMEM;
+ do {
+ next = pud_addr_end(addr, end);
+ if (percpu_boot_pmd_alloc(pud, addr, next, node))
+ return -ENOMEM;
+ } while (pud++, addr = next, addr < end);
+ return 0;
+}
+
+static int __init percpu_boot_alloc(unsigned long addr, unsigned long size,
+ int node)
+{
+ pgd_t *pgd;
+ unsigned long end = addr + size;
+ unsigned long next;
+ int err;
+
+ pgd = pgd_offset_k(addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ err = percpu_boot_pud_alloc(pgd, addr, next, node);
+ if (err)
+ break;
+ } while (pgd++, addr = next, addr < end);
+ return err;
+}
+
+static __init int percpu_pte_alloc(pmd_t *pmd, unsigned long addr,
+ unsigned long end, int node)
+{
+ pte_t *pte;
+
+ pte = pte_alloc_kernel(pmd, addr);
+ if (!pte)
+ return -ENOMEM;
+ do {
+ void *page;
+ if (unlikely(!pte_none(*pte))) {
+ printk("bad pte: %p->%p\n", pte, (void*)pte_val(*pte));
+ BUG();
+ return -EFAULT;
+ }
+ page = (void*)__get_free_page(GFP_KERNEL);
+ if (!page)
+ return -ENOMEM;
+ set_pte_at(&init_mm, addr, pte, mk_pte(virt_to_page(page),
+ PAGE_KERNEL));
+ } while (pte++, addr += PAGE_SIZE, addr < end);
+ __flush_tlb();
+ return 0;
+}
+
+static __init int percpu_pmd_alloc(pud_t *pud, unsigned long addr,
+ unsigned long end, int node)
+{
+ pmd_t *pmd;
+ unsigned long next;
+
+ pmd = pmd_alloc(&init_mm, pud, addr);
+ if (!pmd)
+ return -ENOMEM;
+ do {
+ next = pmd_addr_end(addr, end);
+ if (percpu_pte_alloc(pmd, addr, next, node))
+ return -ENOMEM;
+ } while (pmd++, addr = next, addr < end);
+ return 0;
+}
+
+static __init int percpu_pud_alloc(pgd_t *pgd, unsigned long addr,
+ unsigned long end, int node)
+{
+ pud_t *pud;
+ unsigned long next;
+
+ pud = pud_alloc(&init_mm, pgd, addr);
+ if (!pud)
+ return -ENOMEM;
+ do {
+ next = pud_addr_end(addr, end);
+ if (percpu_pmd_alloc(pud, addr, next, node))
+ return -ENOMEM;
+ } while (pud++, addr = next, addr < end);
+ return 0;
+}
+
+static int percpu_alloc(unsigned long addr, unsigned long size,
+ int node)
+{
+ pgd_t *pgd;
+ unsigned long end = addr + size;
+ unsigned long next;
+ int err;
+
+ pgd = pgd_offset_k(addr);
+ do {
+ next = pgd_addr_end(addr, end);
+ err = percpu_pud_alloc(pgd, addr, next, node);
+ if (err)
+ break;
+ } while (pgd++, addr = next, addr < end);
+ return err;
+}
+
+static int percpu_module_update(void *pcpudst, unsigned long size, int cpu)
+{
+ int err = 0;
+ /*
+ * These two local variables are only used to keep the code
+ * looking simpler. Since this function is only called on
+ * module load, it's not time critical.
+ */
+ unsigned long needed_address = (unsigned long)
+ ((pcpudst) + __PERCPU_OFFSET_ADDRESS(cpu)+size);
+ unsigned long allocated = per_cpu(percpu_allocated, cpu);
+
+ if (allocated < needed_address) {
+ unsigned long alloc = needed_address - allocated;
+ err = percpu_alloc(allocated, alloc, cpu);
+ if (!err)
+ per_cpu(percpu_allocated, cpu) =
+ PAGE_ALIGN(needed_address);
+ }
+ return err;
+}
+
+/**
+ * per_cpu_modcopy - copy and allocate module VM per_cpu variables
+ *
+ * @pcpudst: Destination of module per_cpu section
+ * @src: Source of module per_cpu data section
+ * @size: Size of module per_cpu data section
+ *
+ * Copy the module's data per_cpu section into each VM per_cpu section
+ * stored in the kernel. If need be, allocate more pages in VM
+ * if they are not yet allocated.
+ *
+ * protected by module_mutex
+ */
+int percpu_modcopy(void *pcpudst, void *src, unsigned long size)
+{
+ unsigned int i;
+ int err = 0;
+
+ for (i = 0; i < NR_CPUS; i++)
+ if (cpu_possible(i)) {
+ err = percpu_module_update(pcpudst, size, i);
+ if (err)
+ break;
+ memcpy((pcpudst)+__PERCPU_OFFSET_ADDRESS(i),
+ (src), (size));
+ }
+ return err;
+}
+
+/*
+ * We use the __per_cpu_start for the indexing of
+ * per_cpu variables, even in modules.
+ */
+EXPORT_SYMBOL(__per_cpu_start);
Index: linux-2.6.16-test/mm/Makefile
===================================================================
--- linux-2.6.16-test.orig/mm/Makefile 2006-05-17 04:32:27.000000000 -0400
+++ linux-2.6.16-test/mm/Makefile 2006-05-17 04:39:52.000000000 -0400
@@ -22,3 +22,4 @@ obj-$(CONFIG_SLOB) += slob.o
obj-$(CONFIG_SLAB) += slab.o
obj-$(CONFIG_MEMORY_HOTPLUG) += memory_hotplug.o
obj-$(CONFIG_FS_XIP) += filemap_xip.o
+obj-$(CONFIG_HAS_VM_PERCPU) += percpu.o
\ No newline at end of file
^ permalink raw reply
* [RFC PATCH 01/09] robust VM per_cpu mm header update
From: Steven Rostedt @ 2006-05-17 9:56 UTC (permalink / raw)
To: LKML
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
Andi Kleen, ralf, Marc Gauthier, lethal, schwidefsky, linux390,
davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170547490.8408@gandalf.stny.rr.com>
This patch declares the three functions needed by the archs to
implement the percpu VM.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-2.6.16-test/include/linux/mm.h
===================================================================
--- linux-2.6.16-test.orig/include/linux/mm.h 2006-05-17 04:32:27.000000000 -0400
+++ linux-2.6.16-test/include/linux/mm.h 2006-05-17 04:56:52.000000000 -0400
@@ -795,6 +795,15 @@ int __pmd_alloc(struct mm_struct *mm, pu
int __pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address);
int __pte_alloc_kernel(pmd_t *pmd, unsigned long address);
+#ifdef CONFIG_HAS_VM_PERCPU
+pud_t *pud_boot_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long addr,
+ int cpu);
+pmd_t *pmd_boot_alloc(struct mm_struct *mm, pud_t *pud, unsigned long addr,
+ int cpu);
+pte_t *pte_boot_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long addr,
+ int cpu);
+#endif
+
/*
* The following ifdef needed to get the 4level-fixup.h header to work.
* Remove it when 4level-fixup.h has been removed.
^ permalink raw reply
* [RFC PATCH 03/09] robust VM per_cpu generic header
From: Steven Rostedt @ 2006-05-17 9:57 UTC (permalink / raw)
To: LKML
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
Andi Kleen, ralf, Marc Gauthier, lethal, schwidefsky, linux390,
davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170547490.8408@gandalf.stny.rr.com>
This patch adds the VM per_cpu to the generic per_cpu.h header.
If __ARCH_HAS_VM_PERCPU is defined, it is expected that the arch
also defined the following:
PERCPU_START - start of VM area that per_cpu variables will be stored.
PERCPU_SIZE - size of the VM area for each CPU. So the total size
would be PERCPU_SIZE * NR_CPU
If __ARCH_HAS_VM_PERCPU is not defined, it falls back to the old
percpu hack.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-2.6.16-test/include/asm-generic/percpu.h
===================================================================
--- linux-2.6.16-test.orig/include/asm-generic/percpu.h 2006-05-17 04:32:27.000000000 -0400
+++ linux-2.6.16-test/include/asm-generic/percpu.h 2006-05-17 04:57:21.000000000 -0400
@@ -5,25 +5,52 @@
#define __GENERIC_PER_CPU
#ifdef CONFIG_SMP
-extern unsigned long __per_cpu_offset[NR_CPUS];
-
/* Separate out the type, so (int[3], foo) works. */
#define DEFINE_PER_CPU(type, name) \
__attribute__((__section__(".data.percpu"))) __typeof__(type) per_cpu__##name
+#ifdef __ARCH_HAS_VM_PERCPU
+
+#include <asm/sections.h>
+
+/*
+ * This is included in linux/percpu.h and if PERCPU_ENOUGH_ROOM is already
+ * defined, it wont overwrite it.
+ * This allows kernel/module.c to be the same for both archs with VM
+ * per_cpu and without.
+ */
+#define PERCPU_ENOUGH_ROOM PERCPU_SIZE
+
+#define __PERCPU_OFFSET_ADDRESS(i) ((PERCPU_START+PERCPU_SIZE*(i)) - \
+ (unsigned long)__per_cpu_start)
+
+extern void setup_per_cpu_areas (void);
+extern int percpu_modcopy(void *pcpudst, void *src, unsigned long size);
+
+#else /* !__ARCH_HAS_VM_PERCPU */
+
+extern unsigned long __per_cpu_offset[NR_CPUS];
+
+#define __PERCPU_OFFSET_ADDRESS(i) __per_cpu_offset[i]
+
+/* A macro to avoid #include hell... */
+#define percpu_modcopy(pcpudst, src, size) \
+({ \
+ unsigned int __i; \
+ for (__i = 0; __i < NR_CPUS; __i++) \
+ if (cpu_possible(__i)) \
+ memcpy((pcpudst)+__PERCPU_OFFSET_ADDRESS(__i), \
+ (src), (size)); \
+ 0; \
+})
+
+#endif /* __ARCH_HAS_VM_PERCPU */
+
/* var is in discarded region: offset to particular copy we want */
-#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, __per_cpu_offset[cpu]))
+#define per_cpu(var, cpu) (*RELOC_HIDE(&per_cpu__##var, \
+ __PERCPU_OFFSET_ADDRESS(cpu)))
#define __get_cpu_var(var) per_cpu(var, smp_processor_id())
-/* A macro to avoid #include hell... */
-#define percpu_modcopy(pcpudst, src, size) \
-do { \
- unsigned int __i; \
- for (__i = 0; __i < NR_CPUS; __i++) \
- if (cpu_possible(__i)) \
- memcpy((pcpudst)+__per_cpu_offset[__i], \
- (src), (size)); \
-} while (0)
#else /* ! SMP */
#define DEFINE_PER_CPU(type, name) \
^ permalink raw reply
* [RFC PATCH 04/09] robust VM per_cpu main startup
From: Steven Rostedt @ 2006-05-17 9:58 UTC (permalink / raw)
To: LKML
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
Andi Kleen, ralf, Marc Gauthier, lethal, schwidefsky, linux390,
davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170547490.8408@gandalf.stny.rr.com>
This patch disables the generic setup if __ARCH_HAS_VM_PERCPU defined.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-2.6.16-test/init/main.c
===================================================================
--- linux-2.6.16-test.orig/init/main.c 2006-05-17 04:32:28.000000000 -0400
+++ linux-2.6.16-test/init/main.c 2006-05-17 04:57:45.000000000 -0400
@@ -324,7 +324,7 @@ static inline void smp_prepare_cpus(unsi
#else
-#ifdef __GENERIC_PER_CPU
+#if defined(__GENERIC_PER_CPU) && !defined(__ARCH_HAS_VM_PERCPU)
unsigned long __per_cpu_offset[NR_CPUS];
EXPORT_SYMBOL(__per_cpu_offset);
^ permalink raw reply
* [RFC PATCH 05/09] robust VM per_cpu module
From: Steven Rostedt @ 2006-05-17 9:59 UTC (permalink / raw)
To: LKML
Cc: Andrew Morton, linux-mips, David Mosberger-Tang, linux-ia64,
Martin Mares, spyro, Joe Taylor, linuxppc-dev, Paul Mackerras,
benedict.gaster, sam, bjornw, kenneth.w.chen, Ingo Molnar, kiran,
clameter, Nick Piggin, grundler, arnd, Rusty Russell, starvik,
Linus Torvalds, Thomas Gleixner, rth, Chris Zankel, tony.luck,
Andi Kleen, ralf, Marc Gauthier, lethal, schwidefsky, linux390,
davem, parisc-linux
In-Reply-To: <Pine.LNX.4.58.0605170547490.8408@gandalf.stny.rr.com>
This patch performs a check on the return value of percpu_modcopy
for the module load.
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Index: linux-2.6.16-test/kernel/module.c
===================================================================
--- linux-2.6.16-test.orig/kernel/module.c 2006-05-17 04:32:28.000000000 -0400
+++ linux-2.6.16-test/kernel/module.c 2006-05-17 04:57:53.000000000 -0400
@@ -1819,8 +1819,11 @@ static struct module *load_module(void _
sort_extable(extable, extable + mod->num_exentries);
/* Finally, copy percpu area over. */
- percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
- sechdrs[pcpuindex].sh_size);
+ err = percpu_modcopy(mod->percpu, (void *)sechdrs[pcpuindex].sh_addr,
+ sechdrs[pcpuindex].sh_size);
+
+ if (err < 0)
+ goto cleanup;
add_kallsyms(mod, sechdrs, symindex, strindex, secstrings);
^ permalink raw reply
* Re: [Alsa-devel] [RFC] alsa integer control ranges
From: Takashi Iwai @ 2006-05-17 9:59 UTC (permalink / raw)
To: Benjamin Herrenschmidt
Cc: linuxppc-dev list, Johannes Berg, ALSA development, Benjamin Berg
In-Reply-To: <1147817023.6753.5.camel@localhost.localdomain>
At Wed, 17 May 2006 08:03:43 +1000,
Benjamin Herrenschmidt wrote:
>
> On Tue, 2006-05-16 at 14:27 +0200, Takashi Iwai wrote:
> > At Tue, 16 May 2006 14:02:20 +0200,
> > Johannes Berg wrote:
> > >
> > > Apparently all alsa userspace programs including alsamixer suck. Hence,
> > > this patch is required to make them work properly. Why is it so hard to
> > > do these additions/subtractions in the program or maybe even in the alsa
> > > library? The alsa libraries already think they know better and mess up
> > > all kinds of things.
> >
> > It's a pretty stupid question to ask why you are stupid :)
> >
> > I don't think it's alsa-lib that prevents the negative or non-zero
> > integer range. The fact amixer works implies that it's an
> > app-specific bug. But I'm not 100% sure and need more
> > inside-looking.
>
> Well, the problem I think is that pretty much all apps but amixer (and
> alsamixer whch works too for me at least) are bogus. It would have been
> good if Alsa had a more explicit specification that those values are not
> to be interpreted in the old OSS range :) In fact, best would have been
> to have the control structure carry a "unit" which a set of known units,
> one being dB, since the natural way of specifying an attenuation on any
> serious audio HW is dB and is negative...
Yes, the dB expression has been discussed sometimes and we all agreed
that we definitely need it. But stuck at the implemenation detail.
We have several issuess regarding the conversion of dB <-> raw volume
values:
- some codecs use linear volume
- some codecs have non-linear dB slopes
- unknown dB information for some controllers and codecs
And, USB and HD-audio devices/codecs provide the dB information. Thus
the dB conversion table has to be evaluated dynamically for them.
So, it's not so easy as expected to create an API covering all
above...
Takashi
^ 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