* Re: [patch 3/3] mpc8349emitx.dts: Add ds1339 RTC
From: David Gibson @ 2007-09-24 5:07 UTC (permalink / raw)
To: Peter Korsgaard; +Cc: linuxppc-dev, Timur Tabi
In-Reply-To: <874pholbdk.fsf@macbook.be.48ers.dk>
On Fri, Sep 21, 2007 at 09:35:03AM +0200, Peter Korsgaard wrote:
> >>>>> "Scott" == Scott Wood <scottwood@freescale.com> writes:
>
> Hi,
>
> Scott> #size-cells is zero on i2c, so it should just be reg = <68>.
>
> Scott> You'll probably need to add #address-cells and #size-cells to the
> Scott> controller node, as well.
Uh.. yes.. i2c interfaces should really always have #a and #s.
> Ahh - Thanks. This should be better.
> ---
>
> [PATCH] mpc8349emitx.dts: Add ds1339 RTC
>
> Add ds1339 I2C RTC chip as child of 2nd I2C controller.
>
> Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
> ---
> arch/powerpc/boot/dts/mpc8349emitx.dts | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> Index: linux/arch/powerpc/boot/dts/mpc8349emitx.dts
> ===================================================================
> --- linux.orig/arch/powerpc/boot/dts/mpc8349emitx.dts
> +++ linux/arch/powerpc/boot/dts/mpc8349emitx.dts
> @@ -62,12 +62,21 @@
> };
>
> i2c@3100 {
> + #address-cells = <1>;
> + #size-cells = <0>;
> device_type = "i2c";
Hrm... we probably want an "i2c" device_type class, but I don't think
we've actually defined one, which is a problem
> compatible = "fsl-i2c";
> reg = <3100 100>;
> interrupts = <f 8>;
> interrupt-parent = < &ipic >;
> dfsrr;
> +
> + rtc@68 {
> + device_type = "rtc";
> + compatible = "dallas,ds1339";
> + reg = <68>;
> + };
I think we want to think a bit more carefully about how to do bindings
for RTC devices. No "rtc" device_type is defined, but again we might
want to.
I did find one real OF binding for a different Dallas RTC (and NVRAM),
see:
http://playground.sun.com/1275/proposals/Closed/Remanded/Accepted/346-it.txt
It's a little different from the example above.
The fact that NVRAM+RTC chips are so common is a bit of an issue from
the point of view of defining a device class binding - a device can't
have type "rtc" and "nvram".
> +
> };
>
> spi@7000 {
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 13/15] bootwrapper: attach an empty vmlinux
From: David Gibson @ 2007-09-24 4:03 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-13.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:06:38PM -0500, Milton Miller wrote:
> Allow the boot wrapper code to be linked without an attached vmlinux.
>
> Rather than invent a new syntax to invoke the wrapper, attach the
> stripped version of empty.o, which produces the same result.
Aiee. Please don't do that. Add a new wrapper option so the vmlinux
is optional instead.
Particularly since...
> Index: kernel/arch/powerpc/boot/wrapper
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/wrapper 2007-09-17 22:11:51.000000000 -0500
> +++ kernel/arch/powerpc/boot/wrapper 2007-09-17 22:12:05.000000000 -0500
> @@ -161,6 +161,13 @@ ps3)
> ;;
> esac
>
> +if [ "$kernel" = $object/empty.o ] ; then
> + ext=bin
> + objflags="-O binary"
> + gzip=
> +fi
Making the vmlinux empty.o *isn't* just a matter of doing that but
also has other side effects as above.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 1/2] qemu platform, v2
From: David Gibson @ 2007-09-24 4:00 UTC (permalink / raw)
To: Christoph Hellwig
Cc: linuxppc-dev, Paul Mackerras, Rob Landley, Milton Miller
In-Reply-To: <20070922095546.GA14185@lst.de>
On Sat, Sep 22, 2007 at 11:55:46AM +0200, Christoph Hellwig wrote:
> On Fri, Sep 21, 2007 at 06:08:31PM -0500, Milton Miller wrote:
> > Here is the second rev of patches to boot a arch powerpc kernel on
> > qemu with the prep architecture.
>
> So if this is supposed to be prep why do you need additional kernel
> support? And if you really needed why isn't it under
> platforms/prep?
Basically because PReP support doesn't work under arch/powerpc.
Getting it working properly is something that should happen, but will
take a while. In the meantime, getting something that's sufficient to
get working under just qemu's version of prep, without using the
abominable openhackware is a quicker path to a usable arch/powerpc
kernel under qemu.
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 9/15] bootwrapper: rtas support
From: David Gibson @ 2007-09-24 3:46 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-09.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:05:30PM -0500, Milton Miller wrote:
> This code provides a console write that calls put-term-char.
>
> To avoid PIC relocation of the absolute rtas addresses, hide the
> actual call to rtas in assembly and declare all variables as int.
>
> An instantiated rtas will be protected by a reserved range in the
> device tree, so no explicit call to add_occupied_range is needed
> here.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> vs 12176
> rtas_put_term_write now takes const char *buf
> rediff ops.h, Makefile
>
> Index: kernel/arch/powerpc/boot/rtas.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/rtas.c 2007-09-21 01:43:08.000000000 -0500
> @@ -0,0 +1,146 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + * Copyright 2007 IBM Corporation.
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + *
> + */
> +
> +#include "ops.h"
> +#include "stdio.h"
> +#include "flatdevtree.h"
> +
> +static int rtas_entry;
> +static int rtas_base;
> +static int rtas_size;
> +
> +static void find_rtas(void)
> +{
> + int rc;
> + void *devp;
> + char *str;
> +
> + devp = finddevice("/rtas");
> + if (! devp)
> + return;
> +
> + str = "linux,rtas-entry";
wtf? Just use the literals in the getprop() calls, this is pure
obfuscation.
> + rc = getprop(devp, str, &rtas_entry, sizeof(rtas_entry));
> + if (rc < 0)
> + return;
> + if (rc != sizeof(rtas_entry))
> + goto fail;
> +
> + str = "rtas-size";
> + rc = getprop(devp, str, &rtas_size, sizeof(rtas_size));
> + if (rc < 0)
> + return;
> + if (rc != sizeof(rtas_size))
> + goto fail;
> +
> + str = "linux,rtas-base";
> + rc = getprop(devp, str, &rtas_base, sizeof(rtas_base));
> + if (rc < 0) {
> + printf("rtas-size but no linux,rtas-base in /rtas. "
> + "disabling wrapper rtas interface\n\r");
> + rtas_entry = 0;
> + return;
> + }
> +
> + if (rc != sizeof(rtas_base))
> + goto fail;
> +
> + return;
> +
> +
> +fail:
> + printf("Unexpected length %d of %s property in /rtas.\n\r"
> + "disabling wrapper rtas interface\n\r", rc, str);
> + rtas_entry = 0;
> + return;
> +}
> +
> +/*
> + * PIC relocation of function pointers happens at call time.
> + * We have an absolute out-of-image address. So tell C they
> + * are just integers, and hide the call as an out-of-file
> + * function.
> + */
I don't get this. If we can call into the kernel using a function
pointer, you should be able to call into rtas without this weirdness.
> +__asm__ (
> + " .globl call_rtas\n"
> + " call_rtas: mtctr 5\n"
> + " bctr\n"
> + );
> +
> +void call_rtas(int args[], int base, int entry);
> +
> +
> +static int put_term_char;
> +
> +static void rtas_put_term_write(const char *buf, int len)
> +{
> + int i, args[5];
> +
> + args[0] = put_term_char;
> + args[1] = 1; /* num inputs */
> + args[2] = 1; /* num outputs */
> +
> + for (i=0; i < len; ) {
> + args[3] = buf[i];
> + args[4] = 0;
> +
> + call_rtas(args, rtas_base, rtas_entry);
> + if (args[4] == 0) /* SUCCESS */
> + i++;
> + else if (args[4] == -1) /* HARDWARE_ERROR */
> + break;
> + /* else retry */
> + }
> +}
> +
> +int rtas_console_init(void)
> +{
> + void *devp;
> + int rc;
> +
> +
> + devp = finddevice("/rtas");
> + if (!devp)
> + return -1;
> +
> + if (!rtas_entry)
> + find_rtas();
> + if (!rtas_entry)
> + return -1;
> +
> + rc = getprop(devp, "put-term-char", &put_term_char,
> + sizeof(put_term_char));
> + if (rc == sizeof(put_term_char))
> + console_ops.write = rtas_put_term_write;
> + else
> + put_term_char = -1;
> +
> + return put_term_char == -1 ? -1 : 0;
> +}
> +
> +/* for debug, hard code */
> +void use_rtas_console(int entry, int base, int tc)
> +{
> + rtas_entry = entry;
> + rtas_base = base;
> + put_term_char = tc;
> + console_ops.write = rtas_put_term_write;
> +}
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h 2007-09-21 01:43:02.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h 2007-09-21 01:43:08.000000000 -0500
> @@ -99,6 +99,8 @@ void send_slaves_to_kernel(void *vmlinux
> void slaves_are_low(void);
> void wait_slaves_moved(void);
> void kexec_platform_init(struct boot_param_header *dt_blob);
> +int rtas_console_init(void);
> +void use_rtas_console(int entry, int base, int tc);
>
> int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
> int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
> Index: kernel/arch/powerpc/boot/kexec.c
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/kexec.c 2007-09-21 01:43:02.000000000 -0500
> +++ kernel/arch/powerpc/boot/kexec.c 2007-09-21 01:43:08.000000000 -0500
> @@ -33,6 +33,9 @@ static void find_console_from_tree(void)
> {
> int rc = -1;
>
> + rc = rtas_console_init();
> + if (!rc)
> + return;
> if (rc) {
> /* no console, oh well */
> }
> Index: kernel/arch/powerpc/boot/Makefile
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/Makefile 2007-09-21 01:43:02.000000000 -0500
> +++ kernel/arch/powerpc/boot/Makefile 2007-09-21 01:43:08.000000000 -0500
> @@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
> $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
>
> src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
> - flatdevtree_conv.c marshal.c memranges.c kexec.c \
> + flatdevtree_conv.c marshal.c memranges.c kexec.c rtas.c \
> ns16550.c serial.c simple_alloc.c div64.S util.S \
> gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
> 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 8/15] bootwrapper: convert flatdevtree to version 16
From: David Gibson @ 2007-09-24 3:36 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-08.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:05:06PM -0500, Milton Miller wrote:
> kexec-tools still produces a version 2 device tree, while the
> libraries in the wrapper only support version 16 and later.
>
> Add a routine to convert a v2 flat device tree to a v16 one inplace
> by inserting OF_DT_NOP and chomping full path. Make space for new
> headers by moving and then chomping the OF_DT_NOPs.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> vs 12175
> Rediffed Makefile, ops, kexec.c
>
> Index: kernel/arch/powerpc/boot/flatdevtree_conv.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/flatdevtree_conv.c 2007-09-20 17:49:04.000000000 -0500
> @@ -0,0 +1,280 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + * Copyright IBM Corporation 2007
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + */
> +#include "flatdevtree.h"
> +#include "stdio.h"
> +#include "ops.h"
> +
> +#define MIN_VERSION 2
> +#define OUT_VERSION 16
Should output version 17. In any case, don't try to be so general -
just convert v123 (all basically the same) to latest (i.e. v17)
without all the #if nonsense.
> +#define OUT_COMPAT 16
> +
> +#ifdef NO_CHECK
> +static int check_v123_tree(u32 *start, u32 *limit)
> +{
> + return 0;
> +}
> +#else
> +/**
> + * check_v123_tree - check integrety of a version 1, 2, or 3 tree
> + * @start: the start of the device tree struct
> + * @limit: the end of the region for the struct
> + * structural checks on device_tree
> + */
> +static int check_v123_tree(u32 *start, u32 *limit)
What is the point of this check? If the device tree is corrupt, we're
stuffed anyway, so why bother?
> +{
> + u32 len;
> + int depth = 0;
> + u32 *dtp = start;
> +
> + while (dtp < limit)
> + switch (*dtp) {
> + case OF_DT_END:
> + if (depth)
> + return -1;
> + return ++dtp - start;
> + case OF_DT_NOP:
> + dtp++;
> + break;
> + case OF_DT_END_NODE:
> + dtp++;
> + depth--;
> + break;
> + case OF_DT_BEGIN_NODE:
> + len = strlen((char *)(++dtp));
> + /* check path is suffix to previous? */
> + dtp += 1 + (len / 4);
> + depth++;
> + break;
> + case OF_DT_PROP:
> + len = dtp[1];
> + dtp += 3;
> + if ((len >= 8) && ((long)dtp & 4))
> + dtp++;
> + dtp += (len + 3) / 4;
> + break;
> + default:
> + return -1;
> + }
> + return -1; /* no OF_DT_END */
> +}
> +#endif
> +
> +/**
> + * nop_to_v16 - add %OF_DT_NOP to hide alignment differences
> + * @dtp: pointer to the beginning of the struct area to modify
> + * insert %OF_DT_NOP into the dt_struct @dtp to make it v16 from v1, 2, or 3.
> + */
> +static int nop_to_v16(u32 *dtp)
> +{
> + int nops = 0;
> + char *p, *s;
> + int len;
> + u32 *next;
> +
> + while (*dtp != OF_DT_END)
> + switch (*dtp) {
> + case OF_DT_BEGIN_NODE:
> + /* v2 & v3 names are full path, v16+ is relative */
> + p = (char *)(++dtp);
> + len = strlen(p);
> + next = dtp + 1 + len / 4;
> +
> + for (s = p + len; *s != '/'; s--)
> + if (s == p)
> + fatal("name %s has no '/'", p);
> +
> + len -= s++ - p; /* not the slash but the nul */
> + memmove(p, s, len);
> + while (len % 4)
> + p[len++] = '\0';
> + dtp += len / 4;
> + while (dtp != next) {
> + *dtp++ = OF_DT_NOP;
> + nops++;
> + }
> + break;
> + case OF_DT_PROP:
> + /* convert from align_8 to align_4 via prefixing nop */
> + len = dtp[1];
> + if ((len >= 8) && !((long)dtp & 4)) {
> + memmove(dtp+1, dtp, 12);
> + *dtp++ = OF_DT_NOP;
> + nops++;
> + }
> + dtp += 3 + (len + 3)/4;
> + break;
> + default:
> + fatal("%s: unrecognised tag %d at %p\n", __FUNCTION__,
> + *dtp, dtp);
> + case OF_DT_NOP:
> + nops ++;
> + /* fall through */
> + case OF_DT_END_NODE:
> + dtp ++;
> + break;
> + }
> + return nops;
> +}
> +
> +#if MIN_VERSION < 3 || OUT_VERSION > 16
> +/**
> + * move_nops_fwd - move nops in a v16 dt_struct to the beginning
> + * @start - device tree starting address
> + * @count - number of %OF_DT_NOP cells to move
> + */
> +static void move_nops_fwd(u32 *start, int count)
What on earth is the point of this. The NOPs are perfectly valid
scattered within the tree, why go to all this trouble to shuffle them
about.
> +{
> + u32 *dtp = start;
> + int len;
> + while (count)
> + switch (*dtp) {
> + case OF_DT_NOP:
> + memmove(start+1,start,(dtp-start) * 4);
> + *start++ = OF_DT_NOP;
> + dtp++;
> + count--;
> + break;
> + case OF_DT_END_NODE:
> + dtp++;
> + break;
> + case OF_DT_BEGIN_NODE:
> + len = strlen((char *)(++dtp));
> + dtp += 1 + len / 4;
> + break;
> + case OF_DT_PROP:
> + len = dtp[1];
> + dtp += 3 + (len + 3) / 4;
> + break;
> + case OF_DT_END:
> + fatal("Not enough nops -- need %d more\n", count);
> + return;
> + default:
> + fatal("%s: unknown tag %d at %p", __FUNCTION__, *dtp, dtp)
> + }
> +}
> +#endif
> +
> +/**
> + * conv_flattree_inplace upgrade the version of a boot_param_header
> + * @tree: pointer to the device tree header to convert
> + *
> + * Converts a v1, 2, 3 device tree (of at least MIN_VERSION)
> + * in place to OUT_VERSION (16) format, usable by flatdevtree.c
> + */
> +void conv_flattree_inplace(struct boot_param_header *tree)
> +{
> + u32 *dtp;
> + u32 need = 0, nops;
> + int slen;
> +
> + if (tree->magic != OF_DT_HEADER)
> + fatal("%s: no magic", __FUNCTION__);
More pointless tests...
> + if (tree->last_comp_version > 3)
> + return; /* don't know what to do */
Rather, don't need to do anything.
> +
> + if (tree->version < MIN_VERSION) {
> + printf("%s: Warning: can't handle version %d tree\n",
> + __FUNCTION__, tree->version);
> + return;
> + }
> +
> + if (tree->version < 2)
> + need++; /* boot_cpu_id */
> +
> + if (tree->version < 3)
> + need++; /* dt_string_size */
> +
> + if (OUT_VERSION > 16)
> + need++; /* dt_struct_size */
> +
> + dtp = (void *)tree + tree->off_dt_struct;
> +
> + slen = check_v123_tree(dtp, (void *)tree + tree->totalsize);
> + if (slen < 0)
> + fatal("device tree check failed\n");
> +
> + nops = nop_to_v16(dtp);
> +
> + if (need & 1) /* keep 8 byte alignment of mem reserve */
> + need++;
> +
> + if (need > nops)
> + fatal("Didn't find enough space to add new header fields\n\r"
> + "(needed %d found %d tree %p)", need, nops, tree);
> +
> + /* ok now compress the dtb struct */
> + move_nops_fwd(dtp, need);
> + dtp += need;
> +
> + /*
> + * move mem_rsvmap and dt_strings if they are before dt_struct
> + * onto our nops . Adjust start addresses for the 3 sections.
> + */
Hrm. Do we really need to worry about this case. You may be
producing v2 trees in kexec-tools, but do they actually have the
blocks out of order? dtc certainly never produced them that way.
> + if ((tree->off_mem_rsvmap < tree->off_dt_struct) ||
> + (tree->off_dt_strings < tree->off_dt_struct)) {
> + int start, end;
> + void *ptr;
> +
> + if (tree->off_mem_rsvmap < tree->off_dt_strings)
> + start = tree->off_mem_rsvmap;
> + else
> + start = tree->off_dt_strings;
> +
> + end = tree->off_dt_struct;
> + ptr = (void *)tree + start;
> +
> + memmove(ptr + 4 * need, ptr, end - start);
> +
> + if (tree->off_mem_rsvmap < tree->off_dt_struct)
> + tree->off_mem_rsvmap += 4 * need;
> + if (tree->off_dt_strings < tree->off_dt_struct)
> + tree->off_dt_strings += 4 * need;
> + }
> + tree->off_dt_struct += 4 * need;
> +
> + /* ok now we have space to extend the header. */
> + if (tree->version < 2 && MIN_VERSION < 2) {
> + tree->boot_cpuid_phys = 0; /* default, caller can fix */
> + }
> +
> + /* calculate size of dt_strings_size */
> + if (tree->version < 3 && MIN_VERSION < 3) {
> + int end = tree->totalsize;
> +
> + if (tree->off_dt_strings < tree->off_mem_rsvmap)
> + end = tree->off_mem_rsvmap;
> +
> + if ((tree->off_dt_strings < tree->off_dt_struct) &&
> + (end > tree->off_dt_struct))
> + end = tree->off_dt_struct;
> +
> + tree->dt_strings_size = end - tree->off_dt_strings;
> + }
> +
> +#if OUT_VERSION > 16
> + tree->dt_struct_size = 4 * slen;
> +#endif
> +
> + tree->version = OUT_VERSION;
> + tree->last_comp_version = OUT_COMPAT;
> +
> + return;
> +}
> Index: kernel/arch/powerpc/boot/Makefile
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/Makefile 2007-09-20 17:42:24.000000000 -0500
> +++ kernel/arch/powerpc/boot/Makefile 2007-09-20 17:49:04.000000000 -0500
> @@ -42,7 +42,7 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
> $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
>
> src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
> - marshal.c memranges.c kexec.c \
> + flatdevtree_conv.c marshal.c memranges.c kexec.c \
> ns16550.c serial.c simple_alloc.c div64.S util.S \
> gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
> 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h 2007-09-20 17:42:24.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h 2007-09-20 17:49:04.000000000 -0500
> @@ -81,7 +81,10 @@ struct loader_info {
> };
> extern struct loader_info loader_info;
>
> +struct boot_param_header;
> +
> void start(void);
> +void conv_flattree_inplace(struct boot_param_header *tree);
> int ft_init(void *dt_blob, unsigned int max_size, unsigned int max_find_device);
> int serial_console_init(void);
> int ns16550_console_init(void *devp, struct serial_console_data *scdp);
> Index: kernel/arch/powerpc/boot/kexec.c
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/kexec.c 2007-09-20 17:42:24.000000000 -0500
> +++ kernel/arch/powerpc/boot/kexec.c 2007-09-20 17:49:04.000000000 -0500
> @@ -99,6 +99,7 @@ void kexec_platform_init(struct boot_par
> move_slaves_up();
>
> setup_initial_heap();
> + conv_flattree_inplace(dt_blob);
> init_flat_tree(dt_blob);
> /*
> * drivers can malloc and read the tree, but not realloc later
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 7/15] bootwrapper: Add kexec callable zImage wrapper
From: David Gibson @ 2007-09-24 3:23 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-07.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:04:58PM -0500, Milton Miller wrote:
>
> This code creates a 32 bit zImage wrapper for a 32 or 64 bit PowerPC
> Linux kernel. This allows you to kexec a zImage with its compressed
> vmlinux instead of the uncompressed vmlinux elf. The code is also
> packaged as a 64 bit elf for use by kexec-tools on 64 bit kernels.
>
> Limitations:
> Note: the device-tree generated by kexec-tools is currently version 2,
> not the version 16 supported by the boot code base.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> find_rmo_end moved to memranges as find_rma_end.
> early_scan_flat_tree replaced with calls to its pieces in
> kexec_platform_init
> rediff wrapper, Makefile, ops.h
>
> Index: kernel/arch/powerpc/boot/kexec.c
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/kexec.c 2007-09-21 04:52:46.000000000 -0500
> @@ -0,0 +1,122 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + * Copyright IBM Corporation 2007
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + */
> +
> +#include "ops.h"
> +#include "stdio.h"
> +#include "flatdevtree.h"
> +#include "page.h"
> +#include "types.h"
> +
> +extern char _start[];
> +extern char _end[];
Don't need these externs any more, they're in the headers.
> +
> +BSS_STACK(16*1024);
> +
> +static void find_console_from_tree(void)
> +{
> + int rc = -1;
> +
> + if (rc) {
> + /* no console, oh well */
> + }
Um... pointless function...?
> +}
> +
> +/**
> + * setup_initial_heap - setup a small heap in the bss
> + * Using a preallocated heap, setup for scanning the device tree.
> + * Intended for the initial read while the tree will remain read-only so
> + * a minimal malloc and search limit can be used. This way we don't have
> + * lots of data or bss to clear.
> + */
> +static void setup_initial_heap(void)
> +{
> + static char initial_heap[8*1024];
> + void *heap_end;
> +
> + heap_end = simple_alloc_init(initial_heap,
> + sizeof(initial_heap) * 7 / 8,
> + sizeof(long), 64);
> +
> + if (heap_end - sizeof(initial_heap) > (void *)&initial_heap[0])
> + fatal("Initial heap too big\n\r");
> +}
> +
> +static void init_flat_tree(struct boot_param_header *dt_blob)
> +{
> + int rc;
> +
> + rc = ft_init(dt_blob, dt_blob->totalsize, /* max_finddevice */ 1024);
> + if (rc)
> + fatal("Unable to initialize device_tree library!\n\r");
> +}
> +
> +static void *saved_vmlinux_addr;
> +
> +static void *kexec_vmlinux_alloc(unsigned long size)
> +{
> + void *addr;
> +
> + addr = ranges_vmlinux_alloc(size);
> +
> + saved_vmlinux_addr = addr;
> + return addr;
> +}
> +
> +static void kexec_fixups(void)
> +{
> + wait_slaves_moved();
> +}
> +
> +static unsigned long (*finalize_chain)(void);
> +
> +static unsigned long kexec_finalize(void)
> +{
> + send_slaves_to_kernel(saved_vmlinux_addr);
Ow, yuck, no. The finalize callback is for finalizing the device
tree, don't abuse it for SMP entry. It's a new thing that needs to be
done, so create a new callback for it.
> +
> + return finalize_chain();
> +}
> +
> +void kexec_platform_init(struct boot_param_header *dt_blob)
> +{
> + slaves_are_low();
> + move_slaves_up();
> +
> + setup_initial_heap();
> + init_flat_tree(dt_blob);
> + /*
> + * drivers can malloc and read the tree, but not realloc later
> + * or modify the tree now.
> + */
> + if (!console_ops.write)
> + find_console_from_tree();
> +
> + find_rma_end();
> + dt_find_initrd();
> + add_known_ranges(dt_blob);
> + ranges_init_malloc();
> +
> + /* now that we have a malloc region, start over from the flat tree */
> + init_flat_tree(dt_blob);
> +
> + platform_ops.vmlinux_alloc = kexec_vmlinux_alloc;
> + platform_ops.fixups = kexec_fixups;
> + finalize_chain = dt_ops.finalize;
> + dt_ops.finalize = kexec_finalize;
> +}
> Index: kernel/arch/powerpc/boot/crt0_kexec.S
> ===================================================================
> --- /dev/null 1970-01-01 00:00:00.000000000 +0000
> +++ kernel/arch/powerpc/boot/crt0_kexec.S 2007-09-21 04:52:46.000000000 -0500
> @@ -0,0 +1,45 @@
> +/*
> + * 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.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program; if not, write to the Free Software
> + * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
> + *
> + * Copyright 2007 IBM Corporation.
> + *
> + * Authors: Milton Miller <miltonm@bga.com>
> + *
> + */
> + /*
> + * The kernel calls out to the first image with
> + * r3 = boot cpu, r4 = entrypoint, r5 = 0
> + *
> + * kexec-tools purgatory calls this as it would a linux kernel:
> + * r3 = boot block, r4 = entrypoint, r5 = 0
> + *
> + * The boot block boot_cpu field has been filled in.
> + *
> + * kexec-tools and its purgatory are suppposed to copy SMP_SLAVE_SIZE
> + * bytes from the from entry point, but aparently instead it copies
> + * from the image start.
> + */
> + .globl _zimage_start
> +_zimage_start:
> +
> +#include "marshal_low.S"
> +
> + .globl _zimage_start_plat
> +_zimage_start_plat:
> + b _zimage_start_lib
> +
> + .globl platform_init
> +platform_init:
> + b kexec_platform_init
> Index: kernel/arch/powerpc/boot/wrapper
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/wrapper 2007-09-21 04:51:31.000000000 -0500
> +++ kernel/arch/powerpc/boot/wrapper 2007-09-21 04:52:46.000000000 -0500
> @@ -133,6 +133,12 @@ coff)
> platformo=$object/of.o
> lds=$object/zImage.coff.lds
> ;;
> +kexec)
> + platformo=$object/crt0_kexec.o
> + ;;
> +kexec64)
> + platformo="-e _zimage_start_64 $object/crt0_kexec.o"
Arg. Again, just because it happens to fit is not a good reason to
abuse platformo - which, obviously enough, s meant to contain the .o
file for the platform - to also contain flags.
> + ;;
> miboot|uboot)
> # miboot and U-boot want just the bare bits, not an ELF binary
> ext=bin
> @@ -190,6 +196,9 @@ uboot)
> fi
> exit 0
> ;;
> +kexec64)
> + ${CROSS}objcopy -O elf64-powerpc $ofile
> + ;;
> esac
>
> addsec() {
> Index: kernel/arch/powerpc/boot/Makefile
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/Makefile 2007-09-21 04:52:44.000000000 -0500
> +++ kernel/arch/powerpc/boot/Makefile 2007-09-21 04:52:46.000000000 -0500
> @@ -42,12 +42,12 @@ $(addprefix $(obj)/,$(zlib) gunzip_util.
> $(addprefix $(obj)/,$(zliblinuxheader)) $(addprefix $(obj)/,$(zlibheader))
>
> src-wlib := string.S crt0.S stdio.c main.c flatdevtree.c flatdevtree_misc.c \
> - marshal.c memranges.c \
> + marshal.c memranges.c kexec.c \
> ns16550.c serial.c simple_alloc.c div64.S util.S \
> gunzip_util.c elf_util.c $(zlib) devtree.c oflib.c ofconsole.c \
> 4xx.c ebony.c mv64x60.c mpsc.c mv64x60_i2c.c cuboot.c bamboo.c \
> cpm-serial.c stdlib.c
> -src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c \
> +src-plat := of.c cuboot-83xx.c cuboot-85xx.c holly.c crt0_kexec.S \
> cuboot-ebony.c treeboot-ebony.c prpmc2800.c \
> ps3-head.S ps3-hvcall.S ps3.c treeboot-bamboo.c cuboot-8xx.c \
> cuboot-pq2.c cuboot-sequoia.c treeboot-walnut.c cuboot-bamboo.c
> @@ -128,6 +128,9 @@ quiet_cmd_wrap = WRAP $@
> cmd_wrap =$(CONFIG_SHELL) $(wrapper) -c -o $@ -p $2 $(CROSSWRAP) \
> $(if $3, -s $3)$(if $4, -d $4)$(if $5, -i $5) vmlinux
>
> +kexec-$(CONFIG_PPC32) += zImage.kexec
> +kexec-$(CONFIG_PPC64) += zImage.kexec64
> +
> image-$(CONFIG_PPC_PSERIES) += zImage.pseries
> image-$(CONFIG_PPC_MAPLE) += zImage.pseries
> image-$(CONFIG_PPC_IBM_CELL_BLADE) += zImage.pseries
> @@ -140,6 +143,7 @@ image-$(CONFIG_PPC_HOLLY) += zImage.hol
> image-$(CONFIG_PPC_PRPMC2800) += zImage.prpmc2800
> image-$(CONFIG_PPC_ISERIES) += zImage.iseries
> image-$(CONFIG_DEFAULT_UIMAGE) += uImage
> +image-$(CONFIG_KEXEC) += $(kexec-y)
>
> ifneq ($(CONFIG_DEVICE_TREE),"")
> image-$(CONFIG_PPC_8xx) += cuImage.8xx
> @@ -158,7 +162,7 @@ ifeq ($(CONFIG_PPC32),y)
> image-$(CONFIG_PPC_PMAC) += zImage.coff zImage.miboot
> endif
>
> -initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-))
> +initrd- := $(patsubst zImage%, zImage.initrd%, $(image-n) $(image-) $(kexec-))
> initrd-y := $(patsubst zImage%, zImage.initrd%, \
> $(patsubst treeImage%, treeImage.initrd%, $(image-y)))
> initrd-y := $(filter-out $(image-y), $(initrd-y))
> @@ -227,7 +231,7 @@ install: $(CONFIGURE) $(addprefix $(obj)
>
> # anything not in $(targets)
> clean-files += $(image-) $(initrd-) zImage zImage.initrd cuImage.* treeImage.* \
> - otheros.bld
> + otheros.bld $(kexec-)
>
> # clean up files cached by wrapper
> clean-kernel := vmlinux.strip vmlinux.bin
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h 2007-09-21 04:52:44.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h 2007-09-21 04:52:46.000000000 -0500
> @@ -95,6 +95,7 @@ void move_slaves_here(void *where);
> void send_slaves_to_kernel(void *vmlinux_addr);
> void slaves_are_low(void);
> void wait_slaves_moved(void);
> +void kexec_platform_init(struct boot_param_header *dt_blob);
This platform specific function should not poluute ops.h.
>
> int dt_xlate_reg(void *node, int res, unsigned long *addr, unsigned long *size);
> int dt_xlate_addr(void *node, u32 *buf, int buflen, unsigned long *xlated_addr);
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 6/15] bootwrapper: help for 64 bit cpus
From: David Gibson @ 2007-09-24 3:14 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-06.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:04:37PM -0500, Milton Miller wrote:
> Add code to check if the processor is in 64 or 32 bit mode using
> only instructions from the 32 bit subset. If the processor is in
> 64 bit mode, switch to 32 bit mode by clearing MSR[SF].
>
> Also add a 64 bit procedure descriptor to use as a elf64 entry
> point.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> vs 12173
> correct comment (equal vs not-equal)
>
> Index: kernel/arch/powerpc/boot/crt0.S
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/crt0.S 2007-07-10 03:33:36.000000000 -0500
> +++ kernel/arch/powerpc/boot/crt0.S 2007-07-10 03:39:08.000000000 -0500
> @@ -17,11 +17,47 @@
> _zimage_start_opd:
> .long _zimage_start, 0, 0, 0
>
> + /* a procedure descriptor used when pretending to be elf64_powerpc */
> + .balign 8
> + .globl _zimage_start_64
> +_zimage_start_64:
Hrm, I'd prefer _zimage_start_opd64 in analogy with the COFF opd entry
above.
> + .long 0, _zimage_start /* big endian, supported reloc ppc32 */
> + .long 0, 0, 0, 0, 0, 0
> +
> +
> .weak _zimage_start
> .globl _zimage_start
> _zimage_start:
> .globl _zimage_start_lib
> _zimage_start_lib:
> + /* Check if the processor is running in 32 bit mode, using
> + * only 32 bit instructions which should be safe on 32 and
> + * 64 bit processors.
> + *
> + * Subtract bottom 32 bits of MSR from full value recording
> + * the result. Since MSR[SF] is in the high word, we will
> + * be equal iff in 32 bit mode (either the processor is
> + * a 32 bit processor or MSR[SF] = 0).
> + */
> + mfmsr r0 /* grab whole msr */
> + rlwinm r8,r0,0,0,31 /* extract bottom word */
> + subf. r8,r8,r0 /* subtract, same? */
> + beq 0f /* yes: we are 32 bit mode */
> +
> + /* We are in 64-bit mode. This program must run in 32 bit
> + * mode. Assume we are actually running somewhere in the
> + * low 32 bits of the address space, so we can just turn
> + * off MSR[SF] which is bit 0.
> + */
> + .machine push
> + .machine "ppc64"
> + rldicl r0,r0,0,1
> + sync
> + mtmsrd r0
> + isync
> + .machine pop
> +0: /* We are now in 32-bit mode */
> +
> /* Work out the offset between the address we were linked at
> and the address where we're running. */
> bl 1f
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 5/15] bootwrapper: occuppied memory ranges
From: David Gibson @ 2007-09-24 3:09 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-05.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:04:18PM -0500, Milton Miller wrote:
> Add a set of library routines to manage gross memory allocations.
>
> This code uses an array in bss to store upto 32 entrys with merging
> representing a range of memory below rma_end (aka end of real mode
> memory at 0).
>
> To use this code, a platform would set rma_end (find_rma_end), mark
> memory ranges occupied (add_known_ranges et al), initialize malloc in
> the spaces between (ranges_init_malloc), and optionally use the supplied
> vmlinux_alloc may be used.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> ---
> vs 12172
> rename rmo_end to rma_end (real mode area, as used in papr)
> removed section labels (now in ops.h)
> rediff ops.h, Makefile
> moved find_rma_end here (from kexec.c in a later patch)
> find_rma_end searches by node type for "memory", checks that
> the parent is the root node, then looks for a reg property
> with the first address/size pair starting at 0.
Urg. It's an awful lot of code for the bootwrapper. Am I right in
understanding that the only reason to use the ranges code is for the
ranges based malloc() and vmlinux_alloc() you get out of it?
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 2/15] boot: record header bytes in gunzip_start
From: David Gibson @ 2007-09-24 2:59 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-02.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:03:34PM -0500, Milton Miller wrote:
>
> Record the number of header bytes skipped in the total bytes read field.
>
> This is needed for the initramfs parsing code to find the end of the
> zip file.
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
Acked-by: David Gibson <david@gibson.dropbear.id.au>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* Re: [PATCH 1/15] boot: find initrd location from device-tree
From: David Gibson @ 2007-09-24 2:58 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev, Paul Mackerras, Rob Landley
In-Reply-To: <boot-8-01.miltonm@bga.com>
On Fri, Sep 21, 2007 at 06:03:24PM -0500, Milton Miller wrote:
> Some platforms have a boot agent that can create or modify properties in
> the device-tree and load images into memory. Provide a helper to set
> loader_info used by prep_initrd().
>
> Signed-off-by: Milton Miller <miltonm@bga.com>
> Acked-by: David Gibson <david@gibson.dropbear.id.au>
Hrm, despite my earlier ack, I'm going to whinge about a few nits
here.
> ---
> re 12168
> rediffed types.h, offset in ops.h
>
> Index: kernel/arch/powerpc/boot/ops.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/ops.h 2007-09-17 22:12:47.000000000 -0500
> +++ kernel/arch/powerpc/boot/ops.h 2007-09-17 22:12:51.000000000 -0500
> @@ -163,6 +163,7 @@ void dt_fixup_clock(const char *path, u3
> void __dt_fixup_mac_addresses(u32 startindex, ...);
> #define dt_fixup_mac_addresses(...) \
> __dt_fixup_mac_addresses(0, __VA_ARGS__, NULL)
> +void dt_find_initrd(void);
>
>
> static inline void *find_node_by_linuxphandle(const u32 linuxphandle)
> Index: kernel/arch/powerpc/boot/types.h
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/types.h 2007-09-17 22:12:47.000000000 -0500
> +++ kernel/arch/powerpc/boot/types.h 2007-09-17 22:12:51.000000000 -0500
> @@ -12,6 +12,8 @@ typedef short s16;
> typedef int s32;
> typedef long long s64;
>
> +#define UINT_MAX 0xFFFFFFFF
I actually don't like this constant - at the point you compare you
care, explicitly, about the value not being over 32-bits, rather than
whether it fits a uint, so the named constant is more misleading than
helpful.
> +
> #define min(x,y) ({ \
> typeof(x) _x = (x); \
> typeof(y) _y = (y); \
> Index: kernel/arch/powerpc/boot/devtree.c
> ===================================================================
> --- kernel.orig/arch/powerpc/boot/devtree.c 2007-09-17 22:12:47.000000000 -0500
> +++ kernel/arch/powerpc/boot/devtree.c 2007-09-17 22:12:51.000000000 -0500
> @@ -1,6 +1,7 @@
> /*
> * devtree.c - convenience functions for device tree manipulation
> * Copyright 2007 David Gibson, IBM Corporation.
> + * Copyright 2007 Milton Miller, IBM Corporation.
> * Copyright (c) 2007 Freescale Semiconductor, Inc.
> *
> * Authors: David Gibson <david@gibson.dropbear.id.au>
> @@ -333,3 +334,68 @@ int dt_is_compatible(void *node, const c
>
> return 0;
> }
> +
> +/**
> + * dt_find_initrd - set loader initrd location based on existing properties
> + *
> + * finds the linux,initrd-start and linux,initrd-end properties in
> + * the /chosen node and sets the loader initrd fields accordingly.
> + *
> + * Use this if your loader sets the properties to allow other code to
> + * relocate the tree and/or cause r3 and r4 to be set on true OF
> + * platforms.
I am unable to make sense of the paragraph above.
> + */
> +void dt_find_initrd(void)
> +{
> + int rc;
> + unsigned long long initrd_start, initrd_end;
> + void *devp;
> + static const char start_prop[] = "linux,initrd-start";
> + static const char end_prop[] = "linux,initrd-end";
I think these constants are more obscuring than useful.
> +
> + devp = finddevice("/chosen");
> + if (! devp) {
> + return;
> + }
CodingStyle would not put { } here.
> +
> + rc = getprop(devp, start_prop, &initrd_start, sizeof(initrd_start));
> + if (rc < 0)
> + return; /* not found */
> + /* The properties had to be 8 bytes until 2.6.22 */
> + if (rc == sizeof(unsigned long)) {
> + unsigned long tmp;
> + memcpy(&tmp, &initrd_start, rc);
> + initrd_start = tmp;
> + } else if (rc != sizeof(initrd_start)) { /* now they
> can be 4 */
Right. 8 bytes and 4 bytes, so you should be using explicit length
types instead of long and long long.
> + printf("unexpected length of %s in /chosen!\n\r", start_prop);
> + return;
All these printf() / return stanzas add a lot of verbosity to this
function. Any way they can be consolidated a bit, maybe a single
error path that just prints the property values, so the user can
figure out what was wrong with them.
> + }
> +
> + rc = getprop(devp, end_prop, &initrd_end, sizeof(initrd_end));
> + if (rc < 0) {
> + printf("chosen has %s but no %s!\n\r", start_prop, end_prop);
> + return;
> + }
> + if (rc == sizeof(unsigned long)) {
> + unsigned long tmp;
> + memcpy(&tmp, &initrd_end, rc);
> + initrd_end = tmp;
> + } else if (rc != sizeof(initrd_end)) {
> + printf("unexpected length of %s in /chosen!\n\r", end_prop);
> + return;
> + }
> +
> + /* Check for presence, ignore if (partially) loaded above 32 bits */
> + if (initrd_start == initrd_end) {
> + printf("ignoring empty device-tree supplied initrd\n");
> + } else if (initrd_start > initrd_end) {
> + printf("ignoring device-tree supplied initrd: start 0x%llx"
> + " > end 0x%llx \n", initrd_start, initrd_end);
> + } else if (initrd_end > UINT_MAX) {
> + printf("ignoring device-tree supplied initrd:"
> + " end 0x%llx > 32 bits\n", initrd_end);
> + } else {
> + loader_info.initrd_addr = initrd_start;
> + loader_info.initrd_size = initrd_end - initrd_start;
> + }
> +}
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
David Gibson | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au | minimalist, thank you. NOT _the_ _other_
| _way_ _around_!
http://www.ozlabs.org/~dgibson
^ permalink raw reply
* [PATCH 11/11] [POWERPC] iSeries: move viodasd probing
From: Stephen Rothwell @ 2007-09-23 16:54 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, Christoph Hellwig
In-Reply-To: <20070921144051.fe554f57.sfr@canb.auug.org.au>
This way we only have entries in the device tree for disks that actually
exist. A slight complication is that disks may be attached to LPARs
at runtime.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/dt.c | 6 -
arch/powerpc/platforms/iseries/vio.c | 301 +++++++++++++++++++++++----------
drivers/block/viodasd.c | 77 +++------
include/asm-powerpc/iseries/vio.h | 47 ++++++
4 files changed, 282 insertions(+), 149 deletions(-)
This version creates the device tree entries unconditionally.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 2e4ad6b..4543c4b 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -72,7 +72,6 @@ static char __initdata device_type_cpu[] = "cpu";
static char __initdata device_type_memory[] = "memory";
static char __initdata device_type_serial[] = "serial";
static char __initdata device_type_network[] = "network";
-static char __initdata device_type_block[] = "block";
static char __initdata device_type_pci[] = "pci";
static char __initdata device_type_vdevice[] = "vdevice";
static char __initdata device_type_vscsi[] = "vscsi";
@@ -374,11 +373,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
dt_end_node(dt);
}
- reg += HVMAXARCHITECTEDVIRTUALLANS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
- dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
- "IBM,iSeries-viodasd", 1);
dt_end_node(dt);
}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index b4f7433..d6435b0 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -25,8 +25,10 @@
#include <linux/gfp.h>
#include <linux/completion.h>
#include <linux/proc_fs.h>
+#include <linux/module.h>
#include <asm/firmware.h>
+#include <asm/vio.h>
#include <asm/iseries/vio.h>
#include <asm/iseries/iommu.h>
#include <asm/iseries/hv_types.h>
@@ -57,7 +59,7 @@ struct vio_resource {
char model[3];
};
-static struct property * __init new_property(const char *name, int length,
+static struct property *new_property(const char *name, int length,
const void *value)
{
struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
@@ -78,7 +80,7 @@ static void __init free_property(struct property *np)
kfree(np);
}
-static struct device_node * __init new_node(const char *path,
+static struct device_node *new_node(const char *path,
struct device_node *parent)
{
struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
@@ -97,7 +99,7 @@ static struct device_node * __init new_node(const char *path,
return np;
}
-static void __init free_node(struct device_node *np)
+static void free_node(struct device_node *np)
{
struct property *next;
struct property *prop;
@@ -113,7 +115,7 @@ static void __init free_node(struct device_node *np)
kfree(np);
}
-static int __init add_string_property(struct device_node *np, const char *name,
+static int add_string_property(struct device_node *np, const char *name,
const char *value)
{
struct property *nprop = new_property(name, strlen(value) + 1, value);
@@ -124,7 +126,7 @@ static int __init add_string_property(struct device_node *np, const char *name,
return 1;
}
-static int __init add_raw_property(struct device_node *np, const char *name,
+static int add_raw_property(struct device_node *np, const char *name,
int length, const void *value)
{
struct property *nprop = new_property(name, length, value);
@@ -135,6 +137,201 @@ static int __init add_raw_property(struct device_node *np, const char *name,
return 1;
}
+static struct device_node *do_device_node(struct device_node *parent,
+ const char *name, u32 reg, u32 unit, const char *type,
+ const char *compat, struct vio_resource *res)
+{
+ struct device_node *np;
+ char path[32];
+
+ snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
+ np = new_node(path, parent);
+ if (!np)
+ return NULL;
+ if (!add_string_property(np, "name", name) ||
+ !add_string_property(np, "device_type", type) ||
+ !add_string_property(np, "compatible", compat) ||
+ !add_raw_property(np, "reg", sizeof(reg), ®) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit)) {
+ goto node_free;
+ }
+ if (res) {
+ if (!add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(res->rsrcname), res->rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(res->type), res->type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(res->model), res->model))
+ goto node_free;
+ }
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (parent->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ return np;
+
+ node_free:
+ free_node(np);
+ return NULL;
+}
+
+/*
+ * This is here so that we can dynamically add viodasd
+ * devices without exposing all the above infrastructure.
+ */
+struct vio_dev *vio_create_viodasd(u32 unit)
+{
+ struct device_node *vio_root;
+ struct device_node *np;
+ struct vio_dev *vdev = NULL;
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return NULL;
+ np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+ "block", "IBM,iSeries-viodasd", NULL);
+ of_node_put(vio_root);
+ if (np) {
+ vdev = vio_register_device_node(np);
+ if (!vdev)
+ free_node(np);
+ }
+ return vdev;
+}
+EXPORT_SYMBOL_GPL(vio_create_viodasd);
+
+static void __init handle_block_event(struct HvLpEvent *event)
+{
+ struct vioblocklpevent *bevent = (struct vioblocklpevent *)event;
+ struct vio_waitevent *pwe;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_viod_request: "
+ "Yikes! got an int in viodasd event handler!\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case vioblockopen:
+ /*
+ * Handle a response to an open request. We get all the
+ * disk information in the response, so update it. The
+ * correlation token contains a pointer to a waitevent
+ * structure that has a completion in it. update the
+ * return code in the waitevent structure and post the
+ * completion to wake up the guy who sent the request
+ */
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+ case vioblockclose:
+ break;
+ default:
+ printk(KERN_WARNING "handle_viod_request: unexpected subtype!");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init probe_disk(struct device_node *vio_root, u32 unit)
+{
+ HvLpEvent_Rc hvrc;
+ struct vio_waitevent we;
+ u16 flags = 0;
+
+retry:
+ init_completion(&we.com);
+
+ /* Send the open event to OS/400 */
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_blockio | vioblockopen,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ ((u64)unit << 48) | ((u64)flags<< 32),
+ 0, 0, 0);
+ if (hvrc != 0) {
+ printk(KERN_WARNING "probe_disk: bad rc on HV open %d\n",
+ (int)hvrc);
+ return;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc != 0) {
+ if (flags != 0)
+ return;
+ /* try again with read only flag set */
+ flags = vioblockflags_ro;
+ goto retry;
+ }
+
+ /* Send the close event to OS/400. We DON'T expect a response */
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_blockio | vioblockclose,
+ HvLpEvent_AckInd_NoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ 0, VIOVERSION << 16,
+ ((u64)unit << 48) | ((u64)flags << 32),
+ 0, 0, 0);
+ if (hvrc != 0) {
+ printk(KERN_WARNING "probe_disk: "
+ "bad rc sending event to OS/400 %d\n", (int)hvrc);
+ return;
+ }
+
+ do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+ "block", "IBM,iSeries-viodasd", NULL);
+}
+
+static void __init get_viodasd_info(struct device_node *vio_root)
+{
+ int rc;
+ u32 unit;
+
+ rc = viopath_open(viopath_hostLp, viomajorsubtype_blockio, 2);
+ if (rc) {
+ printk(KERN_WARNING "get_viodasd_info: "
+ "error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_blockio, handle_block_event);
+
+ for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
+ probe_disk(vio_root, unit);
+
+ vio_clearHandler(viomajorsubtype_blockio);
+ viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
+}
+
static void __init handle_cd_event(struct HvLpEvent *event)
{
struct viocdlpevent *bevent;
@@ -233,49 +430,9 @@ static void __init get_viocd_info(struct device_node *vio_root)
for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
unitinfo[unit].rsrcname[0]; unit++) {
- struct device_node *np;
- char name[64];
- u32 reg = FIRST_VIOCD + unit;
-
- snprintf(name, sizeof(name), "/vdevice/viocd@%08x", reg);
- np = new_node(name, vio_root);
- if (!np)
- goto hv_free;
- if (!add_string_property(np, "name", "viocd") ||
- !add_string_property(np, "device_type", "block") ||
- !add_string_property(np, "compatible",
- "IBM,iSeries-viocd") ||
- !add_raw_property(np, "reg", sizeof(reg), ®) ||
- !add_raw_property(np, "linux,unit_address",
- sizeof(unit), &unit) ||
- !add_raw_property(np, "linux,vio_rsrcname",
- sizeof(unitinfo[unit].rsrcname),
- unitinfo[unit].rsrcname) ||
- !add_raw_property(np, "linux,vio_type",
- sizeof(unitinfo[unit].type),
- unitinfo[unit].type) ||
- !add_raw_property(np, "linux,vio_model",
- sizeof(unitinfo[unit].model),
- unitinfo[unit].model))
- goto node_free;
- np->name = of_get_property(np, "name", NULL);
- np->type = of_get_property(np, "device_type", NULL);
- of_attach_node(np);
-#ifdef CONFIG_PROC_DEVICETREE
- if (vio_root->pde) {
- struct proc_dir_entry *ent;
-
- ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
- vio_root->pde);
- if (ent)
- proc_device_tree_add_node(np, ent);
- }
-#endif
- continue;
-
- node_free:
- free_node(np);
- break;
+ if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
+ "block", "IBM,iSeries-viocd", &unitinfo[unit]))
+ break;
}
hv_free:
@@ -350,49 +507,10 @@ static void __init get_viotape_info(struct device_node *vio_root)
for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
unitinfo[unit].rsrcname[0]; unit++) {
- struct device_node *np;
- char name[64];
- u32 reg = FIRST_VIOTAPE + unit;
-
- snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
- np = new_node(name, vio_root);
- if (!np)
- goto hv_free;
- if (!add_string_property(np, "name", "viotape") ||
- !add_string_property(np, "device_type", "byte") ||
- !add_string_property(np, "compatible",
- "IBM,iSeries-viotape") ||
- !add_raw_property(np, "reg", sizeof(reg), ®) ||
- !add_raw_property(np, "linux,unit_address",
- sizeof(unit), &unit) ||
- !add_raw_property(np, "linux,vio_rsrcname",
- sizeof(unitinfo[unit].rsrcname),
- unitinfo[unit].rsrcname) ||
- !add_raw_property(np, "linux,vio_type",
- sizeof(unitinfo[unit].type),
- unitinfo[unit].type) ||
- !add_raw_property(np, "linux,vio_model",
- sizeof(unitinfo[unit].model),
- unitinfo[unit].model))
- goto node_free;
- np->name = of_get_property(np, "name", NULL);
- np->type = of_get_property(np, "device_type", NULL);
- of_attach_node(np);
-#ifdef CONFIG_PROC_DEVICETREE
- if (vio_root->pde) {
- struct proc_dir_entry *ent;
-
- ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
- vio_root->pde);
- if (ent)
- proc_device_tree_add_node(np, ent);
- }
-#endif
- continue;
-
- node_free:
- free_node(np);
- break;
+ if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
+ unit, "byte", "IBM,iSeries-viotape",
+ &unitinfo[unit]))
+ break;
}
hv_free:
@@ -422,6 +540,7 @@ static int __init iseries_vio_init(void)
goto put_node;
}
+ get_viodasd_info(vio_root);
get_viocd_info(vio_root);
get_viotape_info(vio_root);
diff --git a/drivers/block/viodasd.c b/drivers/block/viodasd.c
index af3969a..e824b67 100644
--- a/drivers/block/viodasd.c
+++ b/drivers/block/viodasd.c
@@ -74,53 +74,9 @@ enum {
static DEFINE_SPINLOCK(viodasd_spinlock);
#define VIOMAXREQ 16
-#define VIOMAXBLOCKDMA 12
#define DEVICE_NO(cell) ((struct viodasd_device *)(cell) - &viodasd_devices[0])
-struct open_data {
- u64 disk_size;
- u16 max_disk;
- u16 cylinders;
- u16 tracks;
- u16 sectors;
- u16 bytes_per_sector;
-};
-
-struct rw_data {
- u64 offset;
- struct {
- u32 token;
- u32 reserved;
- u64 len;
- } dma_info[VIOMAXBLOCKDMA];
-};
-
-struct vioblocklpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_result;
- u16 disk;
- u16 flags;
- union {
- struct open_data open_data;
- struct rw_data rw_data;
- u64 changed;
- } u;
-};
-
-#define vioblockflags_ro 0x0001
-
-enum vioblocksubtype {
- vioblockopen = 0x0001,
- vioblockclose = 0x0002,
- vioblockread = 0x0003,
- vioblockwrite = 0x0004,
- vioblockflush = 0x0005,
- vioblockcheck = 0x0007
-};
-
struct viodasd_waitevent {
struct completion com;
int rc;
@@ -429,7 +385,7 @@ static void do_viodasd_request(struct request_queue *q)
* Probe a single disk and fill in the viodasd_device structure
* for it.
*/
-static void probe_disk(struct viodasd_device *d)
+static int probe_disk(struct viodasd_device *d)
{
HvLpEvent_Rc hvrc;
struct viodasd_waitevent we;
@@ -453,14 +409,14 @@ retry:
0, 0, 0);
if (hvrc != 0) {
printk(VIOD_KERN_WARNING "bad rc on HV open %d\n", (int)hvrc);
- return;
+ return 0;
}
wait_for_completion(&we.com);
if (we.rc != 0) {
if (flags != 0)
- return;
+ return 0;
/* try again with read only flag set */
flags = vioblockflags_ro;
goto retry;
@@ -490,15 +446,32 @@ retry:
if (hvrc != 0) {
printk(VIOD_KERN_WARNING
"bad rc sending event to OS/400 %d\n", (int)hvrc);
- return;
+ return 0;
}
+
+ if (d->dev == NULL) {
+ /* this is when we reprobe for new disks */
+ if (vio_create_viodasd(dev_no) == NULL) {
+ printk(VIOD_KERN_WARNING
+ "cannot allocate virtual device for disk %d\n",
+ dev_no);
+ return 0;
+ }
+ /*
+ * The vio_create_viodasd will have recursed into this
+ * routine with d->dev set to the new vio device and
+ * will finish the setup of the disk below.
+ */
+ return 1;
+ }
+
/* create the request queue for the disk */
spin_lock_init(&d->q_lock);
q = blk_init_queue(do_viodasd_request, &d->q_lock);
if (q == NULL) {
printk(VIOD_KERN_WARNING "cannot allocate queue for disk %d\n",
dev_no);
- return;
+ return 0;
}
g = alloc_disk(1 << PARTITION_SHIFT);
if (g == NULL) {
@@ -506,7 +479,7 @@ retry:
"cannot allocate disk structure for disk %d\n",
dev_no);
blk_cleanup_queue(q);
- return;
+ return 0;
}
d->disk = g;
@@ -538,6 +511,7 @@ retry:
/* register us in the global list */
add_disk(g);
+ return 1;
}
/* returns the total number of scatterlist elements converted */
@@ -718,8 +692,7 @@ static int viodasd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
struct viodasd_device *d = &viodasd_devices[vdev->unit_address];
d->dev = &vdev->dev;
- probe_disk(d);
- if (d->disk == NULL)
+ if (!probe_disk(d))
return -ENODEV;
return 0;
}
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index 2555dfd..f9ac0d0 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -51,6 +51,51 @@
*/
#define VIO_MAX_SUBTYPES 8
+#define VIOMAXBLOCKDMA 12
+
+struct open_data {
+ u64 disk_size;
+ u16 max_disk;
+ u16 cylinders;
+ u16 tracks;
+ u16 sectors;
+ u16 bytes_per_sector;
+};
+
+struct rw_data {
+ u64 offset;
+ struct {
+ u32 token;
+ u32 reserved;
+ u64 len;
+ } dma_info[VIOMAXBLOCKDMA];
+};
+
+struct vioblocklpevent {
+ struct HvLpEvent event;
+ u32 reserved;
+ u16 version;
+ u16 sub_result;
+ u16 disk;
+ u16 flags;
+ union {
+ struct open_data open_data;
+ struct rw_data rw_data;
+ u64 changed;
+ } u;
+};
+
+#define vioblockflags_ro 0x0001
+
+enum vioblocksubtype {
+ vioblockopen = 0x0001,
+ vioblockclose = 0x0002,
+ vioblockread = 0x0003,
+ vioblockwrite = 0x0004,
+ vioblockflush = 0x0005,
+ vioblockcheck = 0x0007
+};
+
struct viocdlpevent {
struct HvLpEvent event;
u32 reserved;
@@ -133,6 +178,8 @@ extern void vio_set_hostlp(void);
extern void *vio_get_event_buffer(int subtype);
extern void vio_free_event_buffer(int subtype, void *buffer);
+extern struct vio_dev *vio_create_viodasd(u32 unit);
+
extern HvLpIndex viopath_hostLp;
extern HvLpIndex viopath_ourLp;
--
1.5.3.2
^ permalink raw reply related
* [PATCH 09/11] [POWERPC] iSeries: move detection of virtual tapes
From: Stephen Rothwell @ 2007-09-23 16:52 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, Christoph Hellwig
In-Reply-To: <20070921143841.37ad2a2f.sfr@canb.auug.org.au>
Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties). This way viotape.c gets
all the information about the devices from the device tree.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/platforms/iseries/dt.c | 7 --
arch/powerpc/platforms/iseries/vio.c | 149 ++++++++++++++++++++++++++++++----
drivers/char/viotape.c | 124 ++++------------------------
include/asm-powerpc/iseries/vio.h | 41 +++++++++
4 files changed, 192 insertions(+), 129 deletions(-)
This version creates the device tree entries unconditionally.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 84fcee1..2e4ad6b 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -73,7 +73,6 @@ static char __initdata device_type_memory[] = "memory";
static char __initdata device_type_serial[] = "serial";
static char __initdata device_type_network[] = "network";
static char __initdata device_type_block[] = "block";
-static char __initdata device_type_byte[] = "byte";
static char __initdata device_type_pci[] = "pci";
static char __initdata device_type_vdevice[] = "vdevice";
static char __initdata device_type_vscsi[] = "vscsi";
@@ -380,12 +379,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
for (i = 0; i < HVMAXARCHITECTEDVIRTUALDISKS; i++)
dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
"IBM,iSeries-viodasd", 1);
- reg += HVMAXARCHITECTEDVIRTUALDISKS;
- reg += HVMAXARCHITECTEDVIRTUALCDROMS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
- dt_do_vdevice(dt, "viotape", reg, i, device_type_byte,
- "IBM,iSeries-viotape", 1);
dt_end_node(dt);
}
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
index 08f6884..b4f7433 100644
--- a/arch/powerpc/platforms/iseries/vio.c
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -45,6 +45,18 @@
#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
+struct vio_waitevent {
+ struct completion com;
+ int rc;
+ u16 sub_result;
+};
+
+struct vio_resource {
+ char rsrcname[10];
+ char type[4];
+ char model[3];
+};
+
static struct property * __init new_property(const char *name, int length,
const void *value)
{
@@ -123,22 +135,10 @@ static int __init add_raw_property(struct device_node *np, const char *name,
return 1;
}
-struct viocd_waitevent {
- struct completion com;
- int rc;
- u16 sub_result;
-};
-
-struct cdrom_info {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
static void __init handle_cd_event(struct HvLpEvent *event)
{
struct viocdlpevent *bevent;
- struct viocd_waitevent *pwe;
+ struct vio_waitevent *pwe;
if (!event)
/* Notification that a partition went away! */
@@ -158,7 +158,7 @@ static void __init handle_cd_event(struct HvLpEvent *event)
switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
case viocdgetinfo:
- pwe = (struct viocd_waitevent *)event->xCorrelationToken;
+ pwe = (struct vio_waitevent *)event->xCorrelationToken;
pwe->rc = event->xRc;
pwe->sub_result = bevent->sub_result;
complete(&pwe->com);
@@ -179,8 +179,8 @@ static void __init get_viocd_info(struct device_node *vio_root)
{
HvLpEvent_Rc hvrc;
u32 unit;
- struct viocd_waitevent we;
- struct cdrom_info *unitinfo;
+ struct vio_waitevent we;
+ struct vio_resource *unitinfo;
dma_addr_t unitinfo_dmaaddr;
int ret;
@@ -286,6 +286,122 @@ static void __init get_viocd_info(struct device_node *vio_root)
viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
}
+/* Handle interrupt events for tape */
+static void __init handle_tape_event(struct HvLpEvent *event)
+{
+ struct vio_waitevent *we;
+ struct viotapelpevent *tevent = (struct viotapelpevent *)event;
+
+ if (event == NULL)
+ /* Notification that a partition went away! */
+ return;
+
+ we = (struct vio_waitevent *)event->xCorrelationToken;
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viotapegetinfo:
+ we->rc = tevent->sub_type_result;
+ complete(&we->com);
+ break;
+ default:
+ printk(KERN_WARNING "handle_tape_event: weird ack\n");
+ }
+}
+
+static void __init get_viotape_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct vio_resource *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ size_t len = sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALTAPES;
+ struct vio_waitevent we;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_tape, 2);
+ if (ret) {
+ printk(KERN_WARNING "get_viotape_info: "
+ "error on viopath_open to hostlp %d\n", ret);
+ return;
+ }
+
+ vio_setHandler(viomajorsubtype_tape, handle_tape_event);
+
+ unitinfo = iseries_hv_alloc(len, &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo)
+ goto clear_handler;
+
+ memset(unitinfo, 0, len);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_tape | viotapegetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)(unsigned long)&we, VIOVERSION << 16,
+ unitinfo_dmaaddr, len, 0, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING "get_viotape_info: hv error on op %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ struct device_node *np;
+ char name[64];
+ u32 reg = FIRST_VIOTAPE + unit;
+
+ snprintf(name, sizeof(name), "/vdevice/viotape@%08x", reg);
+ np = new_node(name, vio_root);
+ if (!np)
+ goto hv_free;
+ if (!add_string_property(np, "name", "viotape") ||
+ !add_string_property(np, "device_type", "byte") ||
+ !add_string_property(np, "compatible",
+ "IBM,iSeries-viotape") ||
+ !add_raw_property(np, "reg", sizeof(reg), ®) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit) ||
+ !add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(unitinfo[unit].rsrcname),
+ unitinfo[unit].rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(unitinfo[unit].type),
+ unitinfo[unit].type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(unitinfo[unit].model),
+ unitinfo[unit].model))
+ goto node_free;
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (vio_root->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
+ vio_root->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ continue;
+
+ node_free:
+ free_node(np);
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(len, unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_tape);
+ viopath_close(viopath_hostLp, viomajorsubtype_tape, 2);
+}
+
static int __init iseries_vio_init(void)
{
struct device_node *vio_root;
@@ -307,6 +423,7 @@ static int __init iseries_vio_init(void)
}
get_viocd_info(vio_root);
+ get_viotape_info(vio_root);
return 0;
diff --git a/drivers/char/viotape.c b/drivers/char/viotape.c
index 064c091..f1d60f0 100644
--- a/drivers/char/viotape.c
+++ b/drivers/char/viotape.c
@@ -92,47 +92,6 @@ struct viot_devinfo_struct {
#define VIOTAPOP_SETPART 14
#define VIOTAPOP_UNLOAD 15
-struct viotapelpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_type_result;
- u16 tape;
- u16 flags;
- u32 token;
- u64 len;
- union {
- struct {
- u32 tape_op;
- u32 count;
- } op;
- struct {
- u32 type;
- u32 resid;
- u32 dsreg;
- u32 gstat;
- u32 erreg;
- u32 file_no;
- u32 block_no;
- } get_status;
- struct {
- u32 block_no;
- } get_pos;
- } u;
-};
-
-enum viotapesubtype {
- viotapeopen = 0x0001,
- viotapeclose = 0x0002,
- viotaperead = 0x0003,
- viotapewrite = 0x0004,
- viotapegetinfo = 0x0005,
- viotapeop = 0x0006,
- viotapegetpos = 0x0007,
- viotapesetpos = 0x0008,
- viotapegetstatus = 0x0009
-};
-
enum viotaperc {
viotape_InvalidRange = 0x0601,
viotape_InvalidToken = 0x0602,
@@ -223,14 +182,11 @@ static const struct vio_error_entry viotape_err_table[] = {
#define VIOT_WRITING 2
/* Our info on the tapes */
-struct tape_descr {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
-static struct tape_descr *viotape_unitinfo;
-static dma_addr_t viotape_unitinfo_token;
+static struct {
+ const char *rsrcname;
+ const char *type;
+ const char *model;
+} viotape_unitinfo[VIOTAPE_MAX_TAPE];
static struct mtget viomtget[VIOTAPE_MAX_TAPE];
@@ -381,53 +337,6 @@ int tape_rc_to_errno(int tape_rc, char *operation, int tapeno)
return -err->errno;
}
-/* Get info on all tapes from OS/400 */
-static int get_viotape_info(void)
-{
- HvLpEvent_Rc hvrc;
- int i;
- size_t len = sizeof(*viotape_unitinfo) * VIOTAPE_MAX_TAPE;
- struct op_struct *op = get_op_struct();
-
- if (op == NULL)
- return -ENOMEM;
-
- viotape_unitinfo = iseries_hv_alloc(len, &viotape_unitinfo_token,
- GFP_ATOMIC);
- if (viotape_unitinfo == NULL) {
- free_op_struct(op);
- return -ENOMEM;
- }
-
- memset(viotape_unitinfo, 0, len);
-
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_tape | viotapegetinfo,
- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64) (unsigned long) op, VIOVERSION << 16,
- viotape_unitinfo_token, len, 0, 0);
- if (hvrc != HvLpEvent_Rc_Good) {
- printk(VIOTAPE_KERN_WARN "hv error on op %d\n",
- (int)hvrc);
- free_op_struct(op);
- return -EIO;
- }
-
- wait_for_completion(&op->com);
-
- free_op_struct(op);
-
- for (i = 0;
- ((i < VIOTAPE_MAX_TAPE) && (viotape_unitinfo[i].rsrcname[0]));
- i++)
- viotape_numdev++;
- return 0;
-}
-
-
/* Write */
static ssize_t viotap_write(struct file *file, const char *buf,
size_t count, loff_t * ppos)
@@ -899,7 +808,6 @@ static void vioHandleTapeEvent(struct HvLpEvent *event)
tapeminor = event->xSubtype & VIOMINOR_SUBTYPE_MASK;
op = (struct op_struct *)event->xCorrelationToken;
switch (tapeminor) {
- case viotapegetinfo:
case viotapeopen:
case viotapeclose:
op->rc = tevent->sub_type_result;
@@ -942,11 +850,23 @@ static int viotape_probe(struct vio_dev *vdev, const struct vio_device_id *id)
{
int i = vdev->unit_address;
int j;
+ struct device_node *node = vdev->dev.archdata.of_node;
- if (i >= viotape_numdev)
+ if (i > VIOTAPE_MAX_TAPE)
+ return -ENODEV;
+ if (!node)
return -ENODEV;
+ if (i >= viotape_numdev)
+ viotape_numdev = i + 1;
+
tape_device[i] = &vdev->dev;
+ viotape_unitinfo[i].rsrcname = of_get_property(node,
+ "linux,vio_rsrcname", NULL);
+ viotape_unitinfo[i].type = of_get_property(node, "linux,vio_type",
+ NULL);
+ viotape_unitinfo[i].model = of_get_property(node, "linux,vio_model",
+ NULL);
state[i].cur_part = 0;
for (j = 0; j < MAX_PARTITIONS; ++j)
@@ -1044,11 +964,6 @@ int __init viotap_init(void)
goto unreg_chrdev;
}
- if ((ret = get_viotape_info()) < 0) {
- printk(VIOTAPE_KERN_WARN "Unable to obtain virtual device information");
- goto unreg_class;
- }
-
ret = vio_register_driver(&viotape_driver);
if (ret)
goto unreg_class;
@@ -1102,9 +1017,6 @@ static void __exit viotap_exit(void)
vio_unregister_driver(&viotape_driver);
class_destroy(tape_class);
unregister_chrdev(VIOTAPE_MAJOR, "viotape");
- if (viotape_unitinfo)
- iseries_hv_free(sizeof(viotape_unitinfo[0]) * VIOTAPE_MAX_TAPE,
- viotape_unitinfo, viotape_unitinfo_token);
viopath_close(viopath_hostLp, viomajorsubtype_tape, VIOTAPE_MAXREQ + 2);
vio_clearHandler(viomajorsubtype_tape);
clear_op_struct_pool();
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index e5a405b..2555dfd 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -75,6 +75,47 @@ enum viocdsubtype {
viocdcheck = 0x0007
};
+struct viotapelpevent {
+ struct HvLpEvent event;
+ u32 reserved;
+ u16 version;
+ u16 sub_type_result;
+ u16 tape;
+ u16 flags;
+ u32 token;
+ u64 len;
+ union {
+ struct {
+ u32 tape_op;
+ u32 count;
+ } op;
+ struct {
+ u32 type;
+ u32 resid;
+ u32 dsreg;
+ u32 gstat;
+ u32 erreg;
+ u32 file_no;
+ u32 block_no;
+ } get_status;
+ struct {
+ u32 block_no;
+ } get_pos;
+ } u;
+};
+
+enum viotapesubtype {
+ viotapeopen = 0x0001,
+ viotapeclose = 0x0002,
+ viotaperead = 0x0003,
+ viotapewrite = 0x0004,
+ viotapegetinfo = 0x0005,
+ viotapeop = 0x0006,
+ viotapegetpos = 0x0007,
+ viotapesetpos = 0x0008,
+ viotapegetstatus = 0x0009
+};
+
/*
* Each subtype can register a handler to process their events.
* The handler must have this interface.
--
1.5.3.2
^ permalink raw reply related
* [PATCH 08/11] [POWERPC] iSeries: move detection of virtual cdroms
From: Stephen Rothwell @ 2007-09-23 16:50 UTC (permalink / raw)
To: paulus; +Cc: ppc-dev, Christoph Hellwig
In-Reply-To: <20070921143750.4114b0b5.sfr@canb.auug.org.au>
Now we will only have entries in the device tree for the actual existing
devices (including their OS/400 properties). This way viocd.c gets all
the information about the devices from the device tree.
Signed-off-by: Stephen Rothwell <sfr@canb.auug.org.au>
---
arch/powerpc/kernel/vio.c | 3 -
arch/powerpc/platforms/iseries/Makefile | 2 +-
arch/powerpc/platforms/iseries/dt.c | 4 -
arch/powerpc/platforms/iseries/vio.c | 317 +++++++++++++++++++++++++++++++
drivers/cdrom/viocd.c | 116 ++----------
include/asm-powerpc/iseries/vio.h | 24 +++
6 files changed, 361 insertions(+), 105 deletions(-)
create mode 100644 arch/powerpc/platforms/iseries/vio.c
This version creates the device tree entries unconditionally.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
diff --git a/arch/powerpc/kernel/vio.c b/arch/powerpc/kernel/vio.c
index 9e1ff21..aec5fff 100644
--- a/arch/powerpc/kernel/vio.c
+++ b/arch/powerpc/kernel/vio.c
@@ -257,9 +257,6 @@ static int __init vio_bus_init(void)
int err;
struct device_node *node_vroot;
- if (firmware_has_feature(FW_FEATURE_ISERIES))
- iommu_vio_init();
-
err = bus_register(&vio_bus_type);
if (err) {
printk(KERN_ERR "failed to register VIO bus\n");
diff --git a/arch/powerpc/platforms/iseries/Makefile b/arch/powerpc/platforms/iseries/Makefile
index 60db509..a65f1b4 100644
--- a/arch/powerpc/platforms/iseries/Makefile
+++ b/arch/powerpc/platforms/iseries/Makefile
@@ -7,7 +7,7 @@ obj-y += hvlog.o hvlpconfig.o lpardata.o setup.o dt_mod.o mf.o lpevents.o \
hvcall.o proc.o htab.o iommu.o misc.o irq.o
obj-$(CONFIG_PCI) += pci.o vpdinfo.o
obj-$(CONFIG_SMP) += smp.o
-obj-$(CONFIG_VIOPATH) += viopath.o
+obj-$(CONFIG_VIOPATH) += viopath.o vio.o
obj-$(CONFIG_MODULES) += ksyms.o
quiet_cmd_dt_strings = DT_STR $@
diff --git a/arch/powerpc/platforms/iseries/dt.c b/arch/powerpc/platforms/iseries/dt.c
index 9e8a334..84fcee1 100644
--- a/arch/powerpc/platforms/iseries/dt.c
+++ b/arch/powerpc/platforms/iseries/dt.c
@@ -381,10 +381,6 @@ static void __init dt_vdevices(struct iseries_flat_dt *dt)
dt_do_vdevice(dt, "viodasd", reg, i, device_type_block,
"IBM,iSeries-viodasd", 1);
reg += HVMAXARCHITECTEDVIRTUALDISKS;
-
- for (i = 0; i < HVMAXARCHITECTEDVIRTUALCDROMS; i++)
- dt_do_vdevice(dt, "viocd", reg, i, device_type_block,
- "IBM,iSeries-viocd", 1);
reg += HVMAXARCHITECTEDVIRTUALCDROMS;
for (i = 0; i < HVMAXARCHITECTEDVIRTUALTAPES; i++)
diff --git a/arch/powerpc/platforms/iseries/vio.c b/arch/powerpc/platforms/iseries/vio.c
new file mode 100644
index 0000000..08f6884
--- /dev/null
+++ b/arch/powerpc/platforms/iseries/vio.c
@@ -0,0 +1,317 @@
+/*
+ * Legacy iSeries specific vio initialisation
+ * that needs to be built in (not a module).
+ *
+ * © Copyright 2007 IBM Corporation
+ * Author: Stephen Rothwell
+ * Some parts collected from various other files
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+#include <linux/of.h>
+#include <linux/init.h>
+#include <linux/gfp.h>
+#include <linux/completion.h>
+#include <linux/proc_fs.h>
+
+#include <asm/firmware.h>
+#include <asm/iseries/vio.h>
+#include <asm/iseries/iommu.h>
+#include <asm/iseries/hv_types.h>
+#include <asm/iseries/hv_lp_event.h>
+
+#define FIRST_VTY 0
+#define NUM_VTYS 1
+#define FIRST_VSCSI (FIRST_VTY + NUM_VTYS)
+#define NUM_VSCSIS 1
+#define FIRST_VLAN (FIRST_VSCSI + NUM_VSCSIS)
+#define NUM_VLANS HVMAXARCHITECTEDVIRTUALLANS
+#define FIRST_VIODASD (FIRST_VLAN + NUM_VLANS)
+#define NUM_VIODASDS HVMAXARCHITECTEDVIRTUALDISKS
+#define FIRST_VIOCD (FIRST_VIODASD + NUM_VIODASDS)
+#define NUM_VIOCDS HVMAXARCHITECTEDVIRTUALCDROMS
+#define FIRST_VIOTAPE (FIRST_VIOCD + NUM_VIOCDS)
+#define NUM_VIOTAPES HVMAXARCHITECTEDVIRTUALTAPES
+
+static struct property * __init new_property(const char *name, int length,
+ const void *value)
+{
+ struct property *np = kzalloc(sizeof(*np) + strlen(name) + 1 + length,
+ GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->name = (char *)(np + 1);
+ np->value = np->name + strlen(name) + 1;
+ strcpy(np->name, name);
+ memcpy(np->value, value, length);
+ np->length = length;
+ return np;
+}
+
+static void __init free_property(struct property *np)
+{
+ kfree(np);
+}
+
+static struct device_node * __init new_node(const char *path,
+ struct device_node *parent)
+{
+ struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
+
+ if (!np)
+ return NULL;
+ np->full_name = kmalloc(strlen(path) + 1, GFP_KERNEL);
+ if (!np->full_name) {
+ kfree(np);
+ return NULL;
+ }
+ strcpy(np->full_name, path);
+ of_node_set_flag(np, OF_DYNAMIC);
+ kref_init(&np->kref);
+ np->parent = of_node_get(parent);
+ return np;
+}
+
+static void __init free_node(struct device_node *np)
+{
+ struct property *next;
+ struct property *prop;
+
+ next = np->properties;
+ while (next) {
+ prop = next;
+ next = prop->next;
+ free_property(prop);
+ }
+ of_node_put(np->parent);
+ kfree(np->full_name);
+ kfree(np);
+}
+
+static int __init add_string_property(struct device_node *np, const char *name,
+ const char *value)
+{
+ struct property *nprop = new_property(name, strlen(value) + 1, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+static int __init add_raw_property(struct device_node *np, const char *name,
+ int length, const void *value)
+{
+ struct property *nprop = new_property(name, length, value);
+
+ if (!nprop)
+ return 0;
+ prom_add_property(np, nprop);
+ return 1;
+}
+
+struct viocd_waitevent {
+ struct completion com;
+ int rc;
+ u16 sub_result;
+};
+
+struct cdrom_info {
+ char rsrcname[10];
+ char type[4];
+ char model[3];
+};
+
+static void __init handle_cd_event(struct HvLpEvent *event)
+{
+ struct viocdlpevent *bevent;
+ struct viocd_waitevent *pwe;
+
+ if (!event)
+ /* Notification that a partition went away! */
+ return;
+
+ /* First, we should NEVER get an int here...only acks */
+ if (hvlpevent_is_int(event)) {
+ printk(KERN_WARNING "handle_cd_event: got an unexpected int\n");
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ return;
+ }
+
+ bevent = (struct viocdlpevent *)event;
+
+ switch (event->xSubtype & VIOMINOR_SUBTYPE_MASK) {
+ case viocdgetinfo:
+ pwe = (struct viocd_waitevent *)event->xCorrelationToken;
+ pwe->rc = event->xRc;
+ pwe->sub_result = bevent->sub_result;
+ complete(&pwe->com);
+ break;
+
+ default:
+ printk(KERN_WARNING "handle_cd_event: "
+ "message with unexpected subtype %0x04X!\n",
+ event->xSubtype & VIOMINOR_SUBTYPE_MASK);
+ if (hvlpevent_need_ack(event)) {
+ event->xRc = HvLpEvent_Rc_InvalidSubtype;
+ HvCallEvent_ackLpEvent(event);
+ }
+ }
+}
+
+static void __init get_viocd_info(struct device_node *vio_root)
+{
+ HvLpEvent_Rc hvrc;
+ u32 unit;
+ struct viocd_waitevent we;
+ struct cdrom_info *unitinfo;
+ dma_addr_t unitinfo_dmaaddr;
+ int ret;
+
+ ret = viopath_open(viopath_hostLp, viomajorsubtype_cdio, 2);
+ if (ret) {
+ printk(KERN_WARNING
+ "get_viocd_info: error opening path to host partition %d\n",
+ viopath_hostLp);
+ return;
+ }
+
+ /* Initialize our request handler */
+ vio_setHandler(viomajorsubtype_cdio, handle_cd_event);
+
+ unitinfo = iseries_hv_alloc(
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ &unitinfo_dmaaddr, GFP_ATOMIC);
+ if (!unitinfo) {
+ printk(KERN_WARNING
+ "get_viocd_info: error allocating unitinfo\n");
+ goto clear_handler;
+ }
+
+ memset(unitinfo, 0, sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS);
+
+ init_completion(&we.com);
+
+ hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
+ HvLpEvent_Type_VirtualIo,
+ viomajorsubtype_cdio | viocdgetinfo,
+ HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
+ viopath_sourceinst(viopath_hostLp),
+ viopath_targetinst(viopath_hostLp),
+ (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
+ sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS, 0);
+ if (hvrc != HvLpEvent_Rc_Good) {
+ printk(KERN_WARNING
+ "get_viocd_info: cdrom error sending event. rc %d\n",
+ (int)hvrc);
+ goto hv_free;
+ }
+
+ wait_for_completion(&we.com);
+
+ if (we.rc) {
+ printk(KERN_WARNING "get_viocd_info: bad rc %d:0x%04X\n",
+ we.rc, we.sub_result);
+ goto hv_free;
+ }
+
+ for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
+ unitinfo[unit].rsrcname[0]; unit++) {
+ struct device_node *np;
+ char name[64];
+ u32 reg = FIRST_VIOCD + unit;
+
+ snprintf(name, sizeof(name), "/vdevice/viocd@%08x", reg);
+ np = new_node(name, vio_root);
+ if (!np)
+ goto hv_free;
+ if (!add_string_property(np, "name", "viocd") ||
+ !add_string_property(np, "device_type", "block") ||
+ !add_string_property(np, "compatible",
+ "IBM,iSeries-viocd") ||
+ !add_raw_property(np, "reg", sizeof(reg), ®) ||
+ !add_raw_property(np, "linux,unit_address",
+ sizeof(unit), &unit) ||
+ !add_raw_property(np, "linux,vio_rsrcname",
+ sizeof(unitinfo[unit].rsrcname),
+ unitinfo[unit].rsrcname) ||
+ !add_raw_property(np, "linux,vio_type",
+ sizeof(unitinfo[unit].type),
+ unitinfo[unit].type) ||
+ !add_raw_property(np, "linux,vio_model",
+ sizeof(unitinfo[unit].model),
+ unitinfo[unit].model))
+ goto node_free;
+ np->name = of_get_property(np, "name", NULL);
+ np->type = of_get_property(np, "device_type", NULL);
+ of_attach_node(np);
+#ifdef CONFIG_PROC_DEVICETREE
+ if (vio_root->pde) {
+ struct proc_dir_entry *ent;
+
+ ent = proc_mkdir(strrchr(np->full_name, '/') + 1,
+ vio_root->pde);
+ if (ent)
+ proc_device_tree_add_node(np, ent);
+ }
+#endif
+ continue;
+
+ node_free:
+ free_node(np);
+ break;
+ }
+
+ hv_free:
+ iseries_hv_free(sizeof(*unitinfo) * HVMAXARCHITECTEDVIRTUALCDROMS,
+ unitinfo, unitinfo_dmaaddr);
+ clear_handler:
+ vio_clearHandler(viomajorsubtype_cdio);
+ viopath_close(viopath_hostLp, viomajorsubtype_cdio, 2);
+}
+
+static int __init iseries_vio_init(void)
+{
+ struct device_node *vio_root;
+
+ if (!firmware_has_feature(FW_FEATURE_ISERIES))
+ return -ENODEV;
+
+ iommu_vio_init();
+
+ vio_root = of_find_node_by_path("/vdevice");
+ if (!vio_root)
+ return -ENODEV;
+
+ if (viopath_hostLp == HvLpIndexInvalid) {
+ vio_set_hostlp();
+ /* If we don't have a host, bail out */
+ if (viopath_hostLp == HvLpIndexInvalid)
+ goto put_node;
+ }
+
+ get_viocd_info(vio_root);
+
+ return 0;
+
+ put_node:
+ of_node_put(vio_root);
+ return -ENODEV;
+}
+arch_initcall(iseries_vio_init);
diff --git a/drivers/cdrom/viocd.c b/drivers/cdrom/viocd.c
index c081e54..880b5dc 100644
--- a/drivers/cdrom/viocd.c
+++ b/drivers/cdrom/viocd.c
@@ -56,30 +56,6 @@
#define VIOCD_KERN_WARNING KERN_WARNING "viocd: "
#define VIOCD_KERN_INFO KERN_INFO "viocd: "
-struct viocdlpevent {
- struct HvLpEvent event;
- u32 reserved;
- u16 version;
- u16 sub_result;
- u16 disk;
- u16 flags;
- u32 token;
- u64 offset; /* On open, max number of disks */
- u64 len; /* On open, size of the disk */
- u32 block_size; /* Only set on open */
- u32 media_size; /* Only set on open */
-};
-
-enum viocdsubtype {
- viocdopen = 0x0001,
- viocdclose = 0x0002,
- viocdread = 0x0003,
- viocdwrite = 0x0004,
- viocdlockdoor = 0x0005,
- viocdgetinfo = 0x0006,
- viocdcheck = 0x0007
-};
-
/*
* Should probably make this a module parameter....sigh
*/
@@ -131,17 +107,13 @@ static struct capability_entry capability_table[] __initdata = {
/* These are our internal structures for keeping track of devices */
static int viocd_numdev;
-struct cdrom_info {
- char rsrcname[10];
- char type[4];
- char model[3];
-};
-
struct disk_info {
struct gendisk *viocd_disk;
struct cdrom_device_info viocd_info;
struct device *dev;
- struct cdrom_info unitinfo;
+ const char *rsrcname;
+ const char *type;
+ const char *model;
};
static struct disk_info viocd_diskinfo[VIOCD_MAX_CD];
@@ -159,9 +131,9 @@ static int proc_viocd_show(struct seq_file *m, void *v)
for (i = 0; i < viocd_numdev; i++) {
seq_printf(m, "viocd device %d is iSeries resource %10.10s"
"type %4.4s, model %3.3s\n",
- i, viocd_diskinfo[i].unitinfo.rsrcname,
- viocd_diskinfo[i].unitinfo.type,
- viocd_diskinfo[i].unitinfo.model);
+ i, viocd_diskinfo[i].rsrcname,
+ viocd_diskinfo[i].type,
+ viocd_diskinfo[i].model);
}
return 0;
}
@@ -211,61 +183,6 @@ struct block_device_operations viocd_fops = {
.media_changed = viocd_blk_media_changed,
};
-/* Get info on CD devices from OS/400 */
-static void __init get_viocd_info(void)
-{
- HvLpEvent_Rc hvrc;
- int i;
- struct viocd_waitevent we;
- struct cdrom_info *viocd_unitinfo;
- dma_addr_t unitinfo_dmaaddr;
-
- viocd_unitinfo = iseries_hv_alloc(
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- &unitinfo_dmaaddr, GFP_ATOMIC);
- if (viocd_unitinfo == NULL) {
- printk(VIOCD_KERN_WARNING "error allocating unitinfo\n");
- return;
- }
-
- memset(viocd_unitinfo, 0, sizeof(*viocd_unitinfo) * VIOCD_MAX_CD);
-
- init_completion(&we.com);
-
- hvrc = HvCallEvent_signalLpEventFast(viopath_hostLp,
- HvLpEvent_Type_VirtualIo,
- viomajorsubtype_cdio | viocdgetinfo,
- HvLpEvent_AckInd_DoAck, HvLpEvent_AckType_ImmediateAck,
- viopath_sourceinst(viopath_hostLp),
- viopath_targetinst(viopath_hostLp),
- (u64)&we, VIOVERSION << 16, unitinfo_dmaaddr, 0,
- sizeof(*viocd_unitinfo) * VIOCD_MAX_CD, 0);
- if (hvrc != HvLpEvent_Rc_Good) {
- printk(VIOCD_KERN_WARNING "cdrom error sending event. rc %d\n",
- (int)hvrc);
- goto error_ret;
- }
-
- wait_for_completion(&we.com);
-
- if (we.rc) {
- const struct vio_error_entry *err =
- vio_lookup_rc(viocd_err_table, we.sub_result);
- printk(VIOCD_KERN_WARNING "bad rc %d:0x%04X on getinfo: %s\n",
- we.rc, we.sub_result, err->msg);
- goto error_ret;
- }
-
- for (i = 0; (i < VIOCD_MAX_CD) && viocd_unitinfo[i].rsrcname[0]; i++) {
- viocd_diskinfo[viocd_numdev].unitinfo = viocd_unitinfo[i];
- viocd_numdev++;
- }
-
-error_ret:
- iseries_hv_free(sizeof(*viocd_unitinfo) * VIOCD_MAX_CD,
- viocd_unitinfo, unitinfo_dmaaddr);
-}
-
static int viocd_open(struct cdrom_device_info *cdi, int purpose)
{
struct disk_info *diskinfo = cdi->handle;
@@ -576,7 +493,6 @@ static void vio_handle_cd_event(struct HvLpEvent *event)
bevent->block_size / 512);
}
/* FALLTHROUGH !! */
- case viocdgetinfo:
case viocdlockdoor:
pwe = (struct viocd_waitevent *)event->xCorrelationToken;
return_complete:
@@ -660,22 +576,30 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
int deviceno;
struct disk_info *d;
struct cdrom_device_info *c;
- struct cdrom_info *ci;
struct request_queue *q;
+ struct device_node *node = vdev->dev.archdata.of_node;
deviceno = vdev->unit_address;
- if (deviceno >= viocd_numdev)
+ if (deviceno > VIOCD_MAX_CD)
return -ENODEV;
+ if (!node)
+ return -ENODEV;
+
+ if (deviceno >= viocd_numdev)
+ viocd_numdev = deviceno + 1;
d = &viocd_diskinfo[deviceno];
+ d->rsrcname = of_get_property(node, "linux,vio_rsrcname", NULL);
+ d->type = of_get_property(node, "linux,vio_type", NULL);
+ d->model = of_get_property(node, "linux,vio_model", NULL);
+
c = &d->viocd_info;
- ci = &d->unitinfo;
c->ops = &viocd_dops;
c->speed = 4;
c->capacity = 1;
c->handle = d;
- c->mask = ~find_capability(ci->type);
+ c->mask = ~find_capability(d->type);
sprintf(c->name, VIOCD_DEVICE "%c", 'a' + deviceno);
if (register_cdrom(c) != 0) {
@@ -685,7 +609,7 @@ static int viocd_probe(struct vio_dev *vdev, const struct vio_device_id *id)
}
printk(VIOCD_KERN_INFO "cd %s is iSeries resource %10.10s "
"type %4.4s, model %3.3s\n",
- c->name, ci->rsrcname, ci->type, ci->model);
+ c->name, d->rsrcname, d->type, d->model);
q = blk_init_queue(do_viocd_request, &viocd_reqlock);
if (q == NULL) {
printk(VIOCD_KERN_WARNING "Cannot allocate queue for %s!\n",
@@ -794,8 +718,6 @@ static int __init viocd_init(void)
/* Initialize our request handler */
vio_setHandler(viomajorsubtype_cdio, vio_handle_cd_event);
- get_viocd_info();
-
spin_lock_init(&viocd_reqlock);
ret = vio_register_driver(&viocd_driver);
diff --git a/include/asm-powerpc/iseries/vio.h b/include/asm-powerpc/iseries/vio.h
index 5a5cd0f..e5a405b 100644
--- a/include/asm-powerpc/iseries/vio.h
+++ b/include/asm-powerpc/iseries/vio.h
@@ -51,6 +51,30 @@
*/
#define VIO_MAX_SUBTYPES 8
+struct viocdlpevent {
+ struct HvLpEvent event;
+ u32 reserved;
+ u16 version;
+ u16 sub_result;
+ u16 disk;
+ u16 flags;
+ u32 token;
+ u64 offset; /* On open, max number of disks */
+ u64 len; /* On open, size of the disk */
+ u32 block_size; /* Only set on open */
+ u32 media_size; /* Only set on open */
+};
+
+enum viocdsubtype {
+ viocdopen = 0x0001,
+ viocdclose = 0x0002,
+ viocdread = 0x0003,
+ viocdwrite = 0x0004,
+ viocdlockdoor = 0x0005,
+ viocdgetinfo = 0x0006,
+ viocdcheck = 0x0007
+};
+
/*
* Each subtype can register a handler to process their events.
* The handler must have this interface.
--
1.5.3.2
^ permalink raw reply related
* Re: [PATCH 1/2] qemu platform, v2
From: Rob Landley @ 2007-09-23 22:01 UTC (permalink / raw)
To: Paul Mackerras
Cc: linuxppc-dev, Christoph Hellwig, Milton Miller, David Gibson
In-Reply-To: <18165.60185.316393.213864@cargo.ozlabs.ibm.com>
On Saturday 22 September 2007 11:27:05 pm Paul Mackerras wrote:
> Rob Landley writes:
>
> Just to correct a few misconceptions:
> > 2) PowerPC uses a device tree supplied by the hardware to identify the
> > available hardware, even for stuff living on PCI busses which it could
> > theoretically probe for but doesn't.
>
> The device tree doesn't have to include anything that can be probed
> for. On some platforms (e.g. pSeries) we choose to use the device
> tree rather than probing, but on most other platforms we probe.
>
> > I'd be following this more closely if compiling a device tree didn't
> > currently require an external utility (dtc or some such) that doesn't
> > come with the Linux kernel. No other target platform I've built kernels
> > for requires such an environmental dependency.
>
> No? You haven't built kernels for other platforms that have external
> dependencies such as perl, gcc, make, binutils, etc.? :)
Lemme clarify.
1) All of the other platforms have the _same_ requirements. I never had to
install anything to build "for arm", "for mips", "for sparc", or
for "x86_64".
The minimal requirements are: A compiler (gcc/binutils although I'm working
on extending tcc to replace these), make, linux kernel, C library (uClibc),
busybox, and bash. That's it. You can rebuild it under itself from source
with that, on x86, x86-64, arm, mips... Presumably sparc and m68k too (still
debugging there).
2) Perl isn't needed to build any target platform I've tried. (I even sent in
some patches way back to turn a perl script into a sed script for User Mode
Linux to _make_ this the case.) Yes you need perl to build glibc, but not to
build uClibc. :)
3) What I'm pointing out is that ppc needs an external dependency none of the
other platforms I've tried need. I consider this a bug. I didn't start
using "make headers_install" until it stopped needing an external unifdef.
> > (This is a problem both for hardwiring the
> > device tree into the kernel and for building a new boot rom from the
> > linux kernel's ppc boot wrapper that would contain such a device tree to
> > feed to the kernel.)
>
> It's only really been a problem for ps3 so far, since the embedded
> guys don't seem to have any difficulty with installing dtc.
If the only target that interested me was ppc, then I'd happily install dtc
for it. But focusing on cross-platform support as I am, I notice when a
platform has different requirements from any of the others.
> We are
> looking at what to do for ps3 and prep, and the answer may well
> involve bundling dtc in the kernel source (it's not too big, around
> 3400 lines).
Sounds good to me...
> Paul.
Rob
--
"One of my most productive days was throwing away 1000 lines of code."
- Ken Thompson.
^ permalink raw reply
* FDT for Microblaze and PPC405
From: Michal Simek @ 2007-09-23 18:40 UTC (permalink / raw)
To: linuxppc-dev
Hi,
I made EDK tcl script for generation DTS test scructure for FDT. Script
support Microblaze and PowerPC 405.
Script was primary built for generation U-BOOT configs files for Microblaze.
For Microblaze can you generate both files (FDT and U-BOOT).
For PowerPC can you generate only DTS file. Generation U-BOOT configs files
aren't supported yet. Script ends after generation DTS.
Script has 2.00.a mark.
It is available at www.monstr.eu.
Cheers,
Michal Simek
^ permalink raw reply
* [patch v3] Cell: Wrap master run control bit
From: Geoff Levand @ 2007-09-23 20:50 UTC (permalink / raw)
To: jk; +Cc: Masato Noguchi, linuxppc-dev@ozlabs.org, Arnd Bergmann
In-Reply-To: <46DD4783.9040103@am.sony.com>
Subject: Cell: Wrap master run control bit
From: Masato Noguchi <Masato.Noguchi@jp.sony.com>
Add platform specific SPU run control routines to the spufs. The current
spufs implementation uses the SPU master run control bit (MFC_SR1[S]) to
control SPE execution, but the PS3 hypervisor does not support the use of
this feature.
This change adds the run control wrapper routies spu_enable_spu() and
spu_disable_spu(). The bare metal routines use the master run control
bit, and the PS3 specific routines use the priv2 run control register.
An outstanding enhancement for the PS3 would be to add a guard to check
for incorrect access to the spu problem state when the spu context is
disabled. This check could be implemented with a flag added to the spu
context that would inhibit mapping problem state pages, and a routine
to unmap spu problem state pages. When the spu is enabled with
ps3_enable_spu() the flag would be set allowing pages to be mapped,
and when the spu is disabled with ps3_disable_spu() the flag would be
cleared and mapped problem state pages would be unmapped.
Signed-off-by: Masato Noguchi <Masato.Noguchi@jp.sony.com>
Signed-off-by: Geoff Levand <geoffrey.levand@am.sony.com>
---
Jeremy,
Here is an updated version for 2.6.24. Noguchi-san will
work on the LS unmapping feature for 2.6.25.
-Geoff
v2:
o Added comments about unmapping PS pages when disabled.
v3:
o Changed routines to return void instead of int.
o Rebased to apply to Jeremy's 2.6.23-rc work-around.
arch/powerpc/platforms/cell/spu_manage.c | 13 +++++++++++
arch/powerpc/platforms/cell/spufs/backing_ops.c | 6 +++++
arch/powerpc/platforms/cell/spufs/hw_ops.c | 10 ++++++++
arch/powerpc/platforms/cell/spufs/run.c | 4 +--
arch/powerpc/platforms/cell/spufs/spufs.h | 1
arch/powerpc/platforms/ps3/spu.c | 27 ++++++++++++++++++++++--
include/asm-powerpc/spu_priv1.h | 15 +++++++++++++
7 files changed, 72 insertions(+), 4 deletions(-)
--- a/arch/powerpc/platforms/cell/spu_manage.c
+++ b/arch/powerpc/platforms/cell/spu_manage.c
@@ -35,6 +35,7 @@
#include <asm/firmware.h>
#include <asm/prom.h>
+#include "spufs/spufs.h"
#include "interrupt.h"
struct device_node *spu_devnode(struct spu *spu)
@@ -369,6 +370,16 @@ static int of_destroy_spu(struct spu *sp
return 0;
}
+static void enable_spu_by_master_run(struct spu_context *ctx)
+{
+ ctx->ops->master_start(ctx);
+}
+
+static void disable_spu_by_master_run(struct spu_context *ctx)
+{
+ ctx->ops->master_stop(ctx);
+}
+
/* Hardcoded affinity idxs for qs20 */
#define QS20_SPES_PER_BE 8
static int qs20_reg_idxs[QS20_SPES_PER_BE] = { 0, 2, 4, 6, 7, 5, 3, 1 };
@@ -535,5 +546,7 @@ const struct spu_management_ops spu_mana
.enumerate_spus = of_enumerate_spus,
.create_spu = of_create_spu,
.destroy_spu = of_destroy_spu,
+ .enable_spu = enable_spu_by_master_run,
+ .disable_spu = disable_spu_by_master_run,
.init_affinity = init_affinity,
};
--- a/arch/powerpc/platforms/cell/spufs/backing_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/backing_ops.c
@@ -285,6 +285,11 @@ static void spu_backing_runcntl_write(st
spin_unlock(&ctx->csa.register_lock);
}
+static void spu_backing_runcntl_stop(struct spu_context *ctx)
+{
+ spu_backing_runcntl_write(ctx, SPU_RUNCNTL_STOP);
+}
+
static void spu_backing_master_start(struct spu_context *ctx)
{
struct spu_state *csa = &ctx->csa;
@@ -381,6 +386,7 @@ struct spu_context_ops spu_backing_ops =
.get_ls = spu_backing_get_ls,
.runcntl_read = spu_backing_runcntl_read,
.runcntl_write = spu_backing_runcntl_write,
+ .runcntl_stop = spu_backing_runcntl_stop,
.master_start = spu_backing_master_start,
.master_stop = spu_backing_master_stop,
.set_mfc_query = spu_backing_set_mfc_query,
--- a/arch/powerpc/platforms/cell/spufs/hw_ops.c
+++ b/arch/powerpc/platforms/cell/spufs/hw_ops.c
@@ -220,6 +220,15 @@ static void spu_hw_runcntl_write(struct
spin_unlock_irq(&ctx->spu->register_lock);
}
+static void spu_hw_runcntl_stop(struct spu_context *ctx)
+{
+ spin_lock_irq(&ctx->spu->register_lock);
+ out_be32(&ctx->spu->problem->spu_runcntl_RW, SPU_RUNCNTL_STOP);
+ while (in_be32(&ctx->spu->problem->spu_status_R) & SPU_STATUS_RUNNING)
+ cpu_relax();
+ spin_unlock_irq(&ctx->spu->register_lock);
+}
+
static void spu_hw_master_start(struct spu_context *ctx)
{
struct spu *spu = ctx->spu;
@@ -321,6 +330,7 @@ struct spu_context_ops spu_hw_ops = {
.get_ls = spu_hw_get_ls,
.runcntl_read = spu_hw_runcntl_read,
.runcntl_write = spu_hw_runcntl_write,
+ .runcntl_stop = spu_hw_runcntl_stop,
.master_start = spu_hw_master_start,
.master_stop = spu_hw_master_stop,
.set_mfc_query = spu_hw_set_mfc_query,
--- a/arch/powerpc/platforms/cell/spufs/run.c
+++ b/arch/powerpc/platforms/cell/spufs/run.c
@@ -302,7 +302,7 @@ long spufs_run_spu(struct spu_context *c
if (mutex_lock_interruptible(&ctx->run_mutex))
return -ERESTARTSYS;
- ctx->ops->master_start(ctx);
+ spu_enable_spu(ctx);
ctx->event_return = 0;
spu_acquire(ctx);
@@ -376,7 +376,7 @@ long spufs_run_spu(struct spu_context *c
ctx->stats.libassist++;
- ctx->ops->master_stop(ctx);
+ spu_disable_spu(ctx);
ret = spu_run_fini(ctx, npc, &status);
spu_yield(ctx);
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -170,6 +170,7 @@ struct spu_context_ops {
char*(*get_ls) (struct spu_context * ctx);
u32 (*runcntl_read) (struct spu_context * ctx);
void (*runcntl_write) (struct spu_context * ctx, u32 data);
+ void (*runcntl_stop) (struct spu_context * ctx);
void (*master_start) (struct spu_context * ctx);
void (*master_stop) (struct spu_context * ctx);
int (*set_mfc_query)(struct spu_context * ctx, u32 mask, u32 mode);
--- a/arch/powerpc/platforms/ps3/spu.c
+++ b/arch/powerpc/platforms/ps3/spu.c
@@ -28,6 +28,7 @@
#include <asm/spu_priv1.h>
#include <asm/lv1call.h>
+#include "../cell/spufs/spufs.h"
#include "platform.h"
/* spu_management_ops */
@@ -419,10 +420,34 @@ static int ps3_init_affinity(void)
return 0;
}
+/**
+ * ps3_enable_spu - Enable SPU run control.
+ *
+ * An outstanding enhancement for the PS3 would be to add a guard to check
+ * for incorrect access to the spu problem state when the spu context is
+ * disabled. This check could be implemented with a flag added to the spu
+ * context that would inhibit mapping problem state pages, and a routine
+ * to unmap spu problem state pages. When the spu is enabled with
+ * ps3_enable_spu() the flag would be set allowing pages to be mapped,
+ * and when the spu is disabled with ps3_disable_spu() the flag would be
+ * cleared and the mapped problem state pages would be unmapped.
+ */
+
+static void ps3_enable_spu(struct spu_context *ctx)
+{
+}
+
+static void ps3_disable_spu(struct spu_context *ctx)
+{
+ ctx->ops->runcntl_stop(ctx);
+}
+
const struct spu_management_ops spu_management_ps3_ops = {
.enumerate_spus = ps3_enumerate_spus,
.create_spu = ps3_create_spu,
.destroy_spu = ps3_destroy_spu,
+ .enable_spu = ps3_enable_spu,
+ .disable_spu = ps3_disable_spu,
.init_affinity = ps3_init_affinity,
};
@@ -505,8 +530,6 @@ static void mfc_sr1_set(struct spu *spu,
static const u64 allowed = ~(MFC_STATE1_LOCAL_STORAGE_DECODE_MASK
| MFC_STATE1_PROBLEM_STATE_MASK);
- sr1 |= MFC_STATE1_MASTER_RUN_CONTROL_MASK;
-
BUG_ON((sr1 & allowed) != (spu_pdata(spu)->cache.sr1 & allowed));
spu_pdata(spu)->cache.sr1 = sr1;
--- a/include/asm-powerpc/spu_priv1.h
+++ b/include/asm-powerpc/spu_priv1.h
@@ -24,6 +24,7 @@
#include <linux/types.h>
struct spu;
+struct spu_context;
/* access to priv1 registers */
@@ -178,6 +179,8 @@ struct spu_management_ops {
int (*enumerate_spus)(int (*fn)(void *data));
int (*create_spu)(struct spu *spu, void *data);
int (*destroy_spu)(struct spu *spu);
+ void (*enable_spu)(struct spu_context *ctx);
+ void (*disable_spu)(struct spu_context *ctx);
int (*init_affinity)(void);
};
@@ -207,6 +210,18 @@ spu_init_affinity (void)
return spu_management_ops->init_affinity();
}
+static inline void
+spu_enable_spu (struct spu_context *ctx)
+{
+ spu_management_ops->enable_spu(ctx);
+}
+
+static inline void
+spu_disable_spu (struct spu_context *ctx)
+{
+ spu_management_ops->disable_spu(ctx);
+}
+
/*
* The declarations folowing are put here for convenience
* and only intended to be used by the platform setup code.
^ permalink raw reply
* Re: Linux doesn not boot from u-boot on ML403
From: Josh Boyer @ 2007-09-23 19:44 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-embedded, Miroslaw Dach
In-Reply-To: <fa686aa40709230832m1d4a083ao2e43b57cc39e088@mail.gmail.com>
On Sun, 23 Sep 2007 09:32:25 -0600
"Grant Likely" <grant.likely@secretlab.ca> wrote:
> On 9/23/07, Miroslaw Dach <miroslaw.dach@psi.ch> wrote:
> > Hi Grant,
> >
> > Thank you very much for your advices which were very valuable for me.
> >
> > Recently I have followed your advice to move from kernel 2.6.21 to the
> > higher one in order to have the possibility to boot the kernel from
> > u-boot. I have copied across from you git tree the latest version of linux
> > kernel 2.6.23 rc-2.
> >
> > It compiles successfully with some warnings like below:
> > MODPOST vmlinux.o
> > WARNING: vmlinux.o(.text+0x223c): Section mismatch: reference to .init.text:early_init (between 'start_here' and 'initial_mmu')
> > WARNING: vmlinux.o(.text+0x2254): Section mismatch: reference to .init.text:machine_init (between 'start_here' and 'initial_mmu')
> > WARNING: vmlinux.o(.text+0x2258): Section mismatch: reference to .init.text:MMU_init (between 'start_here' and 'initial_mmu')
> > WARNING: vmlinux.o(.text+0x22b2): Section mismatch: reference to .init.text:start_kernel (between 'start_here' and 'initial_mmu')
> > WARNING: vmlinux.o(.text+0x22b6): Section mismatch: reference to .init.text:start_kernel (between 'start_here' and 'initial_mmu')
> > LD vmlinux
>
> Yes, I see this warning too. I haven't had a chance to debug it.
This warning should be fixed in arch/powerpc. You could probably look
at the fix there and port it to arch/ppc.
josh
^ permalink raw reply
* [PATCH4/4] [POWERPC] Fix cpm_uart driver
From: Jochen Friedrich @ 2007-09-23 20:17 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 424 bytes --]
In cpm_uart_core, functions cpm_uart_init_bd and cpm_uart_init_scc
an offset into DP RAM is calculated by substracting a physical
memory constant from an virtual address. This patch fixes the
problem by converting the virtual address into a physical
first.
Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
drivers/serial/cpm_uart/cpm_uart_core.c | 12 ++++++++----
1 files changed, 8 insertions(+), 4 deletions(-)
[-- Attachment #2: 2c5cf6868e9aa6eadea285e524d88859cc5e54fb.diff --]
[-- Type: text/x-patch, Size: 1298 bytes --]
diff --git a/drivers/serial/cpm_uart/cpm_uart_core.c b/drivers/serial/cpm_uart/cpm_uart_core.c
index cefde58..7f5db7c 100644
--- a/drivers/serial/cpm_uart/cpm_uart_core.c
+++ b/drivers/serial/cpm_uart/cpm_uart_core.c
@@ -752,8 +752,10 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
sup = pinfo->sccup;
/* Store address */
- pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
- pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
+ pinfo->sccup->scc_genscc.scc_rbase =
+ (u_char *)cpm_dpram_phys((u8 *)pinfo->rx_bd_base) - DPRAM_BASE;
+ pinfo->sccup->scc_genscc.scc_tbase =
+ (u_char *)cpm_dpram_phys((u8 *)pinfo->tx_bd_base) - DPRAM_BASE;
/* Set up the uart parameters in the
* parameter ram.
@@ -813,8 +815,10 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
up = pinfo->smcup;
/* Store address */
- pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE;
- pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE;
+ pinfo->smcup->smc_rbase =
+ (u_char *)cpm_dpram_phys((u8 *)pinfo->rx_bd_base) - DPRAM_BASE;
+ pinfo->smcup->smc_tbase =
+ (u_char *)cpm_dpram_phys((u8 *)pinfo->tx_bd_base) - DPRAM_BASE;
/*
* In case SMC1 is being relocated...
^ permalink raw reply related
* [PATCH3/4] [PPC] Compile fix for 8xx CPM Ehernet driver
From: Jochen Friedrich @ 2007-09-23 20:17 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 492 bytes --]
Add #include <asm/cacheflush.h> for flush_dcache_range
to make the driver compile again.
CC arch/ppc/8xx_io/enet.o
arch/ppc/8xx_io/enet.c: In function 'scc_enet_start_xmit':
arch/ppc/8xx_io/enet.c:240: error: implicit declaration of function
'flush_dcache_range'
make[1]: *** [arch/ppc/8xx_io/enet.o] Error 1
make: *** [arch/ppc/8xx_io] Error 2
Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
arch/ppc/8xx_io/enet.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)
[-- Attachment #2: c10ab471b95ac13c93b0ae36d169756ae694a77d.diff --]
[-- Type: text/x-patch, Size: 308 bytes --]
diff --git a/arch/ppc/8xx_io/enet.c b/arch/ppc/8xx_io/enet.c
index 703d47e..eace3bc 100644
--- a/arch/ppc/8xx_io/enet.c
+++ b/arch/ppc/8xx_io/enet.c
@@ -44,6 +44,7 @@
#include <asm/mpc8xx.h>
#include <asm/uaccess.h>
#include <asm/commproc.h>
+#include <asm/cacheflush.h>
/*
* Theory of Operation
^ permalink raw reply related
* [PATCH2/4] [PPC] Fix cpm_dpram_addr returning phys mem instead of virt mem
From: Jochen Friedrich @ 2007-09-23 20:17 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 515 bytes --]
cpm_dpram_addr returns physical memory of the DP RAM instead of
iomapped virtual memory. As there usually is a 1:1 MMU map of
the IMMR area, this is often not noticed. However, cpm_dpram_phys
assumes this iomapped virtual memory and returns garbage on the
1:1 mapped memory causing CPM1 uart console to fail.
This patch fixes the problem (copied from the powerpc tree).
Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
arch/ppc/8xx_io/commproc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
[-- Attachment #2: 7a0161f68ca0e487c0119bbc7ee09189b87c1b06.diff --]
[-- Type: text/x-patch, Size: 399 bytes --]
diff --git a/arch/ppc/8xx_io/commproc.c b/arch/ppc/8xx_io/commproc.c
index 7088428..9da880b 100644
--- a/arch/ppc/8xx_io/commproc.c
+++ b/arch/ppc/8xx_io/commproc.c
@@ -459,7 +459,7 @@ EXPORT_SYMBOL(cpm_dpdump);
void *cpm_dpram_addr(unsigned long offset)
{
- return ((immap_t *)IMAP_ADDR)->im_cpm.cp_dpmem + offset;
+ return (void *)(dpram_vbase + offset);
}
EXPORT_SYMBOL(cpm_dpram_addr);
^ permalink raw reply related
* [PATCH1/4] [POWERPC] Fix copy'n'paste typo in commproc.c
From: Jochen Friedrich @ 2007-09-23 20:17 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: linux-kernel
[-- Attachment #1: Type: text/plain, Size: 992 bytes --]
The powerpc version of commproc.c doesn't export cpm_dpram_addr twice
and cpm_dpram_phys not at all due to a typo. This patch fixes this
problem.
CC arch/powerpc/sysdev/commproc.o
arch/powerpc/sysdev/commproc.c:398: error: redefinition of '__kcrctab_cpm_dpram_addr'
arch/powerpc/sysdev/commproc.c:392: error: previous definition of '__kcrctab_cpm_dpram_addr' was here
arch/powerpc/sysdev/commproc.c:398: error: redefinition of '__kstrtab_cpm_dpram_addr'
arch/powerpc/sysdev/commproc.c:392: error: previous definition of '__kstrtab_cpm_dpram_addr' was here
arch/powerpc/sysdev/commproc.c:398: error: redefinition of '__ksymtab_cpm_dpram_addr'
arch/powerpc/sysdev/commproc.c:392: error: previous definition of '__ksymtab_cpm_dpram_addr' was here
make[1]: *** [arch/powerpc/sysdev/commproc.o] Error 1
make: *** [arch/powerpc/sysdev] Error 2
Signed-off-by: Jochen Friedrich <jochen@scram.de>
---
arch/powerpc/sysdev/commproc.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
[-- Attachment #2: 828fc894599eb4bb5a015277687adbb75bb94cc0.diff --]
[-- Type: text/x-patch, Size: 355 bytes --]
diff --git a/arch/powerpc/sysdev/commproc.c b/arch/powerpc/sysdev/commproc.c
index 4f67b89..dd5417a 100644
--- a/arch/powerpc/sysdev/commproc.c
+++ b/arch/powerpc/sysdev/commproc.c
@@ -395,4 +395,4 @@ uint cpm_dpram_phys(u8* addr)
{
return (dpram_pbase + (uint)(addr - dpram_vbase));
}
-EXPORT_SYMBOL(cpm_dpram_addr);
+EXPORT_SYMBOL(cpm_dpram_phys);
^ permalink raw reply related
* [PATCH0/4] Various bug fixes
From: Jochen Friedrich @ 2007-09-23 20:16 UTC (permalink / raw)
To: linuxppc-embedded; +Cc: linux-kernel
Here is a series fixing some bugs for 8xx powerpc CPUs.
1. [POWERPC] Fix copy'n'paste typo in commproc.c
2. [PPC] Fix cpm_dpram_addr returning phys mem instead of virt mem
3. [PPC] Compile fix for 8xx CPM Ehernet driver
4. [POWERPC] Fix cpm_uart driver
This series can be pulled from git://git.bocc.de/dbox2.git ppc-fixes
Thanks,
Jochen
^ permalink raw reply
* Re: Linux doesn not boot from u-boot on ML403
From: Grant Likely @ 2007-09-23 15:32 UTC (permalink / raw)
To: Miroslaw Dach; +Cc: linuxppc-embedded
In-Reply-To: <Pine.LNX.4.44.0709231519510.25165-100000@slslc02.psi.ch>
On 9/23/07, Miroslaw Dach <miroslaw.dach@psi.ch> wrote:
> Hi Grant,
>
> Thank you very much for your advices which were very valuable for me.
>
> Recently I have followed your advice to move from kernel 2.6.21 to the
> higher one in order to have the possibility to boot the kernel from
> u-boot. I have copied across from you git tree the latest version of linux
> kernel 2.6.23 rc-2.
>
> It compiles successfully with some warnings like below:
> MODPOST vmlinux.o
> WARNING: vmlinux.o(.text+0x223c): Section mismatch: reference to .init.text:early_init (between 'start_here' and 'initial_mmu')
> WARNING: vmlinux.o(.text+0x2254): Section mismatch: reference to .init.text:machine_init (between 'start_here' and 'initial_mmu')
> WARNING: vmlinux.o(.text+0x2258): Section mismatch: reference to .init.text:MMU_init (between 'start_here' and 'initial_mmu')
> WARNING: vmlinux.o(.text+0x22b2): Section mismatch: reference to .init.text:start_kernel (between 'start_here' and 'initial_mmu')
> WARNING: vmlinux.o(.text+0x22b6): Section mismatch: reference to .init.text:start_kernel (between 'start_here' and 'initial_mmu')
> LD vmlinux
Yes, I see this warning too. I haven't had a chance to debug it.
>
>
> My observation is that the linux 2.6.23 rc-2 is not that stable as 2.6.21.
> In most cases It boots successfully (ie. zImage.elf) but occasionally it
> fails during booting. It has never occurred with 2.6.21 which I also
> copied from your side.
Hmm, what failure mode are you seeing? I haven't experienced that
problem. However, -rc7 is now out, so I'd recommend moving up to it.
(Hint: use git to make it easy to pull the latest version and either
'quilt' or 'stgit' to manage your changes on top of the mainline tree;
it will make up/downgrading to different kernel version much easier)
> Second question:
>
> In addition I wanted to ask you about u-boot tree which you have mentioned
> in the post on u-boot mailing list. This post was about uart lite for
> ml403 in u-boot.
>
> I was not able to find the project which you have mentioned there:
> git://git.secretlab.ca/git/u-boot.git
That's because there is not such tree. :-) I retired that tree a
while ago because it's no longer current. You can use the mainline
u-boot tree:
git://www.denx.de/git/u-boot.git
>
> This what interests me in particular concerning u-boot is the uart lite
> and temac interfaces from ml403.
:-( I don't think either uartlite or temac drivers has been ported to u-boot.
Cheers,
g.
--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
grant.likely@secretlab.ca
(403) 399-0195
^ permalink raw reply
* Re: Linux doesn not boot from u-boot on ML403
From: Miroslaw Dach @ 2007-09-23 13:27 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-embedded
Hi Grant,
Thank you very much for your advices which were very valuable for me.
Recently I have followed your advice to move from kernel 2.6.21 to the
higher one in order to have the possibility to boot the kernel from
u-boot. I have copied across from you git tree the latest version of linux
kernel 2.6.23 rc-2.
It compiles successfully with some warnings like below:
MODPOST vmlinux.o
WARNING: vmlinux.o(.text+0x223c): Section mismatch: reference to .init.text:early_init (between 'start_here' and 'initial_mmu')
WARNING: vmlinux.o(.text+0x2254): Section mismatch: reference to .init.text:machine_init (between 'start_here' and 'initial_mmu')
WARNING: vmlinux.o(.text+0x2258): Section mismatch: reference to .init.text:MMU_init (between 'start_here' and 'initial_mmu')
WARNING: vmlinux.o(.text+0x22b2): Section mismatch: reference to .init.text:start_kernel (between 'start_here' and 'initial_mmu')
WARNING: vmlinux.o(.text+0x22b6): Section mismatch: reference to .init.text:start_kernel (between 'start_here' and 'initial_mmu')
LD vmlinux
My observation is that the linux 2.6.23 rc-2 is not that stable as 2.6.21.
In most cases It boots successfully (ie. zImage.elf) but occasionally it
fails during booting. It has never occurred with 2.6.21 which I also
copied from your side.
For both kernels I use the same xparamerets_ml403.h file and very similar
.config file
Do you have some idea if it is known problem with booting in 2.6.23 rc-2?
It of course could be something wrong with my ml403 board but I just
wanted to get your opinion about the stability issue. Maybe it is better
to use 2.6.22?
Second question:
In addition I wanted to ask you about u-boot tree which you have mentioned
in the post on u-boot mailing list. This post was about uart lite for
ml403 in u-boot.
I was not able to find the project which you have mentioned there:
git://git.secretlab.ca/git/u-boot.git
This what interests me in particular concerning u-boot is the uart lite
and temac interfaces from ml403.
Thank you very much in advance for any hint
Best Regards
Mirek
^ permalink raw reply
* Downtime
From: Stephen Rothwell @ 2007-09-23 13:02 UTC (permalink / raw)
To: ppc-dev; +Cc: ppc-embedded
[-- Attachment #1: Type: text/plain, Size: 337 bytes --]
Hi all,
Just letting you all know that ozlabs.org will be down for about 5 hours from 1:54 am Canberra time (UTC+10) Monday morning (i.e. about 2 hours 40 minutes from now) due to electrical work in our hosting data centre.
--
Cheers,
Stephen Rothwell sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/
[-- Attachment #2: Type: application/pgp-signature, Size: 189 bytes --]
^ 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