* Re: SYSFS: need a noncaching read
From: Robert Schwebel @ 2007-09-12 5:32 UTC (permalink / raw)
To: Heiko Schocher; +Cc: linuxppc-dev, linux-kernel, Detlev Zundel
In-Reply-To: <1189503798.6674.46.camel@Zeus.EmbLux>
On Tue, Sep 11, 2007 at 11:43:17AM +0200, Heiko Schocher wrote:
> I have developed a device driver and use the sysFS to export some
> registers to userspace.
Uuuh, uggly. Don't do that. Device drivers are there to abstract things,
not to play around with registers from userspace.
> I opened the sysFS File for one register and did some reads from this
> File, but I alwas becoming the same value from the register, whats not
> OK, because they are changing. So I found out that the sysFS caches
> the reads ... :-(
Yes, it does. What you can do is close()ing the file handle between
accesses, which makes it work but is slow.
> Is there a way to retrigger the reads (in that way, that the sysFS
> rereads the values from the driver), without closing and opening the
> sysFS Files? Or must I better use the ioctl () Driver-interface for
> exporting these registers?
What kind of problem do you want to solve? Userspace is for
applications, and applications usually don't have to know about hardware
details like registers. So if you have to do something every 10 ms from
userspace, your design is probably wrong.
If you absolutely need to do such things from userspace, have a look at
uio. But in most cases the answer is: make a proper abstraction for the
problem you wanna solve and write a proper driver.
Robert
--
Pengutronix - Linux Solutions for Science and Industry
Entwicklungszentrum Nord http://www.pengutronix.de
^ permalink raw reply
* Re: Which 2.6 kernel for MPC5200
From: Robert Schwebel @ 2007-09-12 6:28 UTC (permalink / raw)
To: Jon Smirl; +Cc: Babarovic Ivica, linuxppc-embedded
In-Reply-To: <9e4733910709101622u6978baa6n8618975f75ae1315@mail.gmail.com>
Jon,
On Mon, Sep 10, 2007 at 07:22:39PM -0400, Jon Smirl wrote:
> > Then you need to apply the bestcomm patches. You can get them here:
> >
> > http://www.246tnt.com/mpc52xx/dev_full/
>
> I just finished rebasing the Efika version of those patches to current mainline.
>
> I'm working on merging support for my Phytec pcm030 into them.
We have the OSELAS.BSP patch stack for the PCM030 working ontop of
Linus' git. It still uses an older version of the Bestcom patches, so if
you do some work in that area, please keep me informed about your
progress.
Robert
--
Pengutronix - Linux Solutions for Science and Industry
Entwicklungszentrum Nord http://www.pengutronix.de
^ permalink raw reply
* RE: [PATCH] [POWERPC] Fix interrupt routing and setup of ULI M1575 onFSL boards
From: Swarthout Edward L-SWARTHOU @ 2007-09-12 6:33 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <Pine.LNX.4.64.0708170003210.21006@blarg.am.freescale.net>
From: Kumar Gala:
...
> Fixed RTC support that requires a dummy memory read on the P2P
> bridge to unlock the RTC and setup the default of the RTC alarm
> registers to match with a basic x86 style CMOS RTC.
...
> diff --git a/arch/powerpc/platforms/fsl_uli1575.c
...
> +/* We have to do a dummy read on the P2P for the RTC to work, WTF
> +static void __devinit quirk_final_uli5249(struct pci_dev *dev)
...
> + for (i =3D 0; i < PCI_BUS_NUM_RESOURCES; i++) {
> + if ((bus->resource[i]) &&
> + (bus->resource[i]->flags & IORESOURCE_MEM)) {
> + dummy =3D ioremap(bus->resource[i]->start, 0x4);
> + if (dummy) {
> + in_8(dummy);
This read (to resource->start) can cause a hang on 8572ds when there
is a PCI card plugged into the uli slot and the card is configured
(but not enabled) in the memory space.
The read is going to the slot, 2.11, which has 0x8000_0000 assigned.
=20
To be safe, the read needs to go to a device internal to the uli.
-ELS
^ permalink raw reply
* Re: PCI target implementation on AMCC PPC CPUs
From: Matthias Fuchs @ 2007-09-12 7:17 UTC (permalink / raw)
To: David Hawkins; +Cc: Leonid, linuxppc-embedded
In-Reply-To: <46E6D131.2030904@ovro.caltech.edu>
Hi David,
I must admit, that the AMCC PowerPC's PCI interrupt capabilities could
be better:-) In both directions the host CPU has to do PCI
configuration cycles either to generate or acknowledge an interrupt.
The later is problematic for some OS coming from Redmond: you
have to do pci configuration cycles from interrupt level - and
these OS do not 'like' that.
In later designs and where possible we also switched to alternative
interrupt mechanisms (GPIO for target to host and gated flags in FPGA
registers for the other direction). Multiple interrupt sources
are identified by messages that are written to the other sides
memory.
I think we should stop this discussion because its a little bit
off-topic on this list.
Matthias
On Tuesday 11 September 2007 19:32, David Hawkins wrote:
> Hi Matthias,
>
> > we build a couple of PCI target designs using AMCC PowerPCs.
> > You are right that some things could be better. But ..
> >
> > On Thursday 06 September 2007 22:26, David Hawkins wrote:
> >> There are several fundamental problems with the AMCC 440EP
> >> acting as a PCI target/slave;
> >>
> >> 2. Look in the data sheet and see if you can figure out
> >> how the host processor can generate an interrupt to
> >> the PowerPC core ... oops, you can't. That kind of
> >> makes it difficult to work with doesn't it.
> >
> > You CAN! You can generate an interrupt to the PowerPC from the host
> > CPU bei writing to the PCI command register. You have to read the user manual
> > carefully. Perhaps it not that obvious.
>
> Really!? Someone should tell AMCC tech support then.
> When I failed to find a method (other than hooking up
> an external GPIO), I contacted them and they came to
> the same conclusion (on the 440EP anyway).
>
> I'll look in the latest user manual to be sure ...
>
> PPC440EP_UM2000_v1_23.pdf
>
> p394 has their 'cheesy' implementation of PCI INTA# control;
> toggle a single bit.
>
> Then backing up a little, p388 has the PCI command register ...
> Nope, no comment there that a write causes an interrupt to
> the PowerPC core.
>
> Ok, so going back to the UIC in Chapter 10, p224.
>
> Ah-ha, PCI CMD write generates an interrupt 5!
>
> So, I stand corrected; the host can generate an interrupt to
> the PowerPC core, and the method is 'cheesier' than the PCI
> INTA# control.
>
> And my experience with AMCC's tech support is now a notch
> lower, as even they did not offer this as a solution :)
>
> I sure am glad I changed to a Freescale processor ;)
>
> Cheers,
> Dave
^ permalink raw reply
* Re: FDT for Microblaze and PPC405
From: Michal Simek @ 2007-09-12 7:34 UTC (permalink / raw)
To: David Gibson; +Cc: linuxppc-dev
In-Reply-To: <20070912020339.GC16001@localhost.localdomain>
Hi David and Grant
>> > For example emaclite driver needs information about turning on/off ping pong
buffer...
>> >
>> > I would like to make this properly.
>>
>> FDT design is just as much art as it is science. It takes taste and
>> judgement to desgin a nice set of bindings. Your best option is to
>> draft something and post it to the linuxppc-embedded mailing list for
>> review.
>
>Yes, this is the preferred procedure, for now.
OK. Science is good for me because I am looking for theme for dissertation thesis
and FPGA based FDT can be good choice.
>> > And second question is on early console logs and timers setting. I read
>about aliases in FDT. I think that aliases can cover this setting.
>> > For example my design contain 4 serial line and I would like to know which
>serial line is set on early console.
>>
>> You use the chosen node for this. In the chosen node, you add a
>> property called "linux,stdout-path" which holds the path to your
>> console. You can look at examples under arch/powerpc/boot/dts/*
>Yes. Currently we don't use /aliases in the flat device tree. This
>is possibly a mistake, and something I'm thinking about changing.
>But, for now, linux,stdout-path in /chosen is the way to do this.
OK. I will make the first draft and send it to list for review but it will be
only part of patch rely on with ppc405 because we don't have microblaze kernel code.
Michal Simek
^ permalink raw reply
* [PATCH 01/15] Extract the file descriptor search logic in SPU coredump code
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
Extract the logic for searching through the file descriptors for spu contexts
into a separate routine, coredump_next_context(), so we can use it elsewhere
in future. In the process we flatten the for loop, and move the NOSCHED test
into coredump_next_context().
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 58 +++++++++++++++++---------
1 files changed, 38 insertions(+), 20 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 5e31799..99f8e0b 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -109,16 +109,11 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
return total;
}
-static int spufs_add_one_context(struct file *file, int dfd)
+static int spufs_add_one_context(struct spu_context *ctx, int dfd)
{
- struct spu_context *ctx;
struct spufs_ctx_info *ctx_info;
int size;
- ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
- if (ctx->flags & SPU_CREATE_NOSCHED)
- return 0;
-
ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL);
if (unlikely(!ctx_info))
return -ENOMEM;
@@ -142,22 +137,45 @@ static int spufs_add_one_context(struct file *file, int dfd)
* internal functionality to dump them without needing to actually
* open the files.
*/
-static int spufs_arch_notes_size(void)
+static struct spu_context *coredump_next_context(int *fd)
{
struct fdtable *fdt = files_fdtable(current->files);
- int size = 0, fd;
-
- for (fd = 0; fd < fdt->max_fds; fd++) {
- if (FD_ISSET(fd, fdt->open_fds)) {
- struct file *file = fcheck(fd);
-
- if (file && file->f_op == &spufs_context_fops) {
- int rval = spufs_add_one_context(file, fd);
- if (rval < 0)
- break;
- size += rval;
- }
- }
+ struct file *file;
+ struct spu_context *ctx = NULL;
+
+ for (; *fd < fdt->max_fds; (*fd)++) {
+ if (!FD_ISSET(*fd, fdt->open_fds))
+ continue;
+
+ file = fcheck(*fd);
+
+ if (!file || file->f_op != &spufs_context_fops)
+ continue;
+
+ ctx = SPUFS_I(file->f_dentry->d_inode)->i_ctx;
+ if (ctx->flags & SPU_CREATE_NOSCHED)
+ continue;
+
+ /* start searching the next fd next time we're called */
+ (*fd)++;
+ break;
+ }
+
+ return ctx;
+}
+
+static int spufs_arch_notes_size(void)
+{
+ struct spu_context *ctx;
+ int size = 0, rc, fd;
+
+ fd = 0;
+ while ((ctx = coredump_next_context(&fd)) != NULL) {
+ rc = spufs_add_one_context(ctx, fd);
+ if (rc < 0)
+ break;
+
+ size += rc;
}
return size;
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 02/15] Remove ctx_info and ctx_info_list
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Remove the ctx_info struct entirely, and also the ctx_info_list. This fixes
a race where two processes can clobber each other's ctx_info structs.
Instead of using the list, we just repeat the search through the file
descriptor table.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 79 ++++++-------------------
1 files changed, 19 insertions(+), 60 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 99f8e0b..6663669 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -31,15 +31,6 @@
#include "spufs.h"
-struct spufs_ctx_info {
- struct list_head list;
- int dfd;
- int memsize; /* in bytes */
- struct spu_context *ctx;
-};
-
-static LIST_HEAD(ctx_info_list);
-
static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer,
size_t size, loff_t *off)
{
@@ -73,25 +64,17 @@ static int spufs_dump_seek(struct file *file, loff_t off)
return 1;
}
-static void spufs_fill_memsize(struct spufs_ctx_info *ctx_info)
+static u64 ctx_ls_size(struct spu_context *ctx)
{
- struct spu_context *ctx;
- unsigned long long lslr;
-
- ctx = ctx_info->ctx;
- lslr = ctx->csa.priv2.spu_lslr_RW;
- ctx_info->memsize = lslr + 1;
+ return ctx->csa.priv2.spu_lslr_RW + 1;
}
-static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
+static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
{
- int dfd, memsize, i, sz, total = 0;
+ int i, sz, total = 0;
char *name;
char fullname[80];
- dfd = ctx_info->dfd;
- memsize = ctx_info->memsize;
-
for (i = 0; spufs_coredump_read[i].name; i++) {
name = spufs_coredump_read[i].name;
sz = spufs_coredump_read[i].size;
@@ -101,7 +84,7 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
total += sizeof(struct elf_note);
total += roundup(strlen(fullname) + 1, 4);
if (!strcmp(name, "mem"))
- total += roundup(memsize, 4);
+ total += roundup(ctx_ls_size(ctx), 4);
else
total += roundup(sz, 4);
}
@@ -109,25 +92,6 @@ static int spufs_ctx_note_size(struct spufs_ctx_info *ctx_info)
return total;
}
-static int spufs_add_one_context(struct spu_context *ctx, int dfd)
-{
- struct spufs_ctx_info *ctx_info;
- int size;
-
- ctx_info = kzalloc(sizeof(*ctx_info), GFP_KERNEL);
- if (unlikely(!ctx_info))
- return -ENOMEM;
-
- ctx_info->dfd = dfd;
- ctx_info->ctx = ctx;
-
- spufs_fill_memsize(ctx_info);
-
- size = spufs_ctx_note_size(ctx_info);
- list_add(&ctx_info->list, &ctx_info_list);
- return size;
-}
-
/*
* The additional architecture-specific notes for Cell are various
* context files in the spu context.
@@ -171,7 +135,7 @@ static int spufs_arch_notes_size(void)
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
- rc = spufs_add_one_context(ctx, fd);
+ rc = spufs_ctx_note_size(ctx, fd);
if (rc < 0)
break;
@@ -181,12 +145,11 @@ static int spufs_arch_notes_size(void)
return size;
}
-static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
- struct file *file)
+static void spufs_arch_write_note(struct spu_context *ctx, int i,
+ struct file *file, int dfd)
{
- struct spu_context *ctx;
loff_t pos = 0;
- int sz, dfd, rc, total = 0;
+ int sz, rc, total = 0;
const int bufsz = PAGE_SIZE;
char *name;
char fullname[80], *buf;
@@ -196,18 +159,13 @@ static void spufs_arch_write_note(struct spufs_ctx_info *ctx_info, int i,
if (!buf)
return;
- dfd = ctx_info->dfd;
name = spufs_coredump_read[i].name;
if (!strcmp(name, "mem"))
- sz = ctx_info->memsize;
+ sz = ctx_ls_size(ctx);
else
sz = spufs_coredump_read[i].size;
- ctx = ctx_info->ctx;
- if (!ctx)
- goto out;
-
sprintf(fullname, "SPU/%d/%s", dfd, name);
en.n_namesz = strlen(fullname) + 1;
en.n_descsz = sz;
@@ -237,16 +195,17 @@ out:
static void spufs_arch_write_notes(struct file *file)
{
- int j;
- struct spufs_ctx_info *ctx_info, *next;
+ struct spu_context *ctx;
+ int fd, j;
+
+ fd = 0;
+ while ((ctx = coredump_next_context(&fd)) != NULL) {
+ spu_acquire_saved(ctx);
- list_for_each_entry_safe(ctx_info, next, &ctx_info_list, list) {
- spu_acquire_saved(ctx_info->ctx);
for (j = 0; j < spufs_coredump_num_notes; j++)
- spufs_arch_write_note(ctx_info, j, file);
- spu_release_saved(ctx_info->ctx);
- list_del(&ctx_info->list);
- kfree(ctx_info);
+ spufs_arch_write_note(ctx, j, file, fd);
+
+ spu_release_saved(ctx);
}
}
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 03/15] Call spu_acquire_saved() before calculating the SPU note sizes
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
It makes sense to stop the SPU processes as soon as possible. Also if we
dont acquire_saved() I think there's a possibility that the value in
csa.priv2.spu_lslr_RW won't be accurate.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 6663669..21283f6 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -135,7 +135,9 @@ static int spufs_arch_notes_size(void)
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
+ spu_acquire_saved(ctx);
rc = spufs_ctx_note_size(ctx, fd);
+ spu_release_saved(ctx);
if (rc < 0)
break;
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 04/15] Use computed sizes/#defines rather than literals in SPU coredump code
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
The spufs_coredump_reader array contains the size of the data that will be
returned by the read routine. Currently these are specified as literals, and
though some are obvious, sizeof(u32) == 4, others are not, 69 * 8 == ???
Instead, use sizeof() whatever type is returned by each routine, or in
the case of spufs_mem_read() the #define LS_SIZE.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/file.c | 21 +++++++++++----------
1 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index a4a8770..18ddde8 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2231,23 +2231,24 @@ struct tree_descr spufs_dir_nosched_contents[] = {
};
struct spufs_coredump_reader spufs_coredump_read[] = {
- { "regs", __spufs_regs_read, NULL, 128 * 16 },
- { "fpcr", __spufs_fpcr_read, NULL, 16 },
+ { "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
+ { "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
{ "lslr", NULL, __spufs_lslr_get, 11 },
{ "decr", NULL, __spufs_decr_get, 11 },
{ "decr_status", NULL, __spufs_decr_status_get, 11 },
- { "mem", __spufs_mem_read, NULL, 256 * 1024, },
- { "signal1", __spufs_signal1_read, NULL, 4 },
+ { "mem", __spufs_mem_read, NULL, LS_SIZE, },
+ { "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
{ "signal1_type", NULL, __spufs_signal1_type_get, 2 },
- { "signal2", __spufs_signal2_read, NULL, 4 },
+ { "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
{ "signal2_type", NULL, __spufs_signal2_type_get, 2 },
{ "event_mask", NULL, __spufs_event_mask_get, 8 },
{ "event_status", NULL, __spufs_event_status_get, 8 },
- { "mbox_info", __spufs_mbox_info_read, NULL, 4 },
- { "ibox_info", __spufs_ibox_info_read, NULL, 4 },
- { "wbox_info", __spufs_wbox_info_read, NULL, 16 },
- { "dma_info", __spufs_dma_info_read, NULL, 69 * 8 },
- { "proxydma_info", __spufs_proxydma_info_read, NULL, 35 * 8 },
+ { "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
+ { "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
+ { "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
+ { "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)},
+ { "proxydma_info", __spufs_proxydma_info_read,
+ NULL, sizeof(struct spu_proxydma_info)},
{ "object-id", NULL, __spufs_object_id_get, 19 },
{ },
};
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 05/15] Write some SPU coredump values as ASCII
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Unfortunately GDB expects some of the SPU coredump values to be identical
in format to what is found in spufs. This means we need to dump some of
the values as ASCII strings, not the actual values.
Because we don't know what the values will be, we always print the values
with the format "0x%.16lx", that way we know the result will be 19 bytes.
do_coredump_read() doesn't take a __user buffer, so remove the annotation,
and because we know that it's safe to just snprintf() directly to it.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 8 +++++---
arch/powerpc/platforms/cell/spufs/file.c | 14 +++++++-------
2 files changed, 12 insertions(+), 10 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 21283f6..c65b717 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -31,7 +31,7 @@
#include "spufs.h"
-static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *buffer,
+static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
size_t size, loff_t *off)
{
u64 data;
@@ -41,8 +41,10 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void __user *b
return spufs_coredump_read[num].read(ctx, buffer, size, off);
data = spufs_coredump_read[num].get(ctx);
- ret = copy_to_user(buffer, &data, 8);
- return ret ? -EFAULT : 8;
+ ret = snprintf(buffer, size, "0x%.16lx", data);
+ if (ret >= size)
+ return size;
+ return ++ret; /* count trailing NULL */
}
/*
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 18ddde8..85edbec 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2233,16 +2233,16 @@ struct tree_descr spufs_dir_nosched_contents[] = {
struct spufs_coredump_reader spufs_coredump_read[] = {
{ "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
{ "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
- { "lslr", NULL, __spufs_lslr_get, 11 },
- { "decr", NULL, __spufs_decr_get, 11 },
- { "decr_status", NULL, __spufs_decr_status_get, 11 },
+ { "lslr", NULL, __spufs_lslr_get, 19 },
+ { "decr", NULL, __spufs_decr_get, 19 },
+ { "decr_status", NULL, __spufs_decr_status_get, 19 },
{ "mem", __spufs_mem_read, NULL, LS_SIZE, },
{ "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
- { "signal1_type", NULL, __spufs_signal1_type_get, 2 },
+ { "signal1_type", NULL, __spufs_signal1_type_get, 19 },
{ "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
- { "signal2_type", NULL, __spufs_signal2_type_get, 2 },
- { "event_mask", NULL, __spufs_event_mask_get, 8 },
- { "event_status", NULL, __spufs_event_status_get, 8 },
+ { "signal2_type", NULL, __spufs_signal2_type_get, 19 },
+ { "event_mask", NULL, __spufs_event_mask_get, 19 },
+ { "event_status", NULL, __spufs_event_status_get, 19 },
{ "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
{ "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
{ "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 06/15] Correctly calculate the size of the local-store to dump
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
The routine to dump the local store, __spufs_mem_read(), does not take the
spu_lslr_RW value into account - so we shouldn't check it when we're
calculating the size either.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 16 ++--------------
1 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index c65b717..52d6219 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -66,11 +66,6 @@ static int spufs_dump_seek(struct file *file, loff_t off)
return 1;
}
-static u64 ctx_ls_size(struct spu_context *ctx)
-{
- return ctx->csa.priv2.spu_lslr_RW + 1;
-}
-
static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
{
int i, sz, total = 0;
@@ -85,10 +80,7 @@ static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
total += sizeof(struct elf_note);
total += roundup(strlen(fullname) + 1, 4);
- if (!strcmp(name, "mem"))
- total += roundup(ctx_ls_size(ctx), 4);
- else
- total += roundup(sz, 4);
+ total += roundup(sz, 4);
}
return total;
@@ -164,11 +156,7 @@ static void spufs_arch_write_note(struct spu_context *ctx, int i,
return;
name = spufs_coredump_read[i].name;
-
- if (!strcmp(name, "mem"))
- sz = ctx_ls_size(ctx);
- else
- sz = spufs_coredump_read[i].size;
+ sz = spufs_coredump_read[i].size;
sprintf(fullname, "SPU/%d/%s", dfd, name);
en.n_namesz = strlen(fullname) + 1;
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 07/15] Don't return -ENOSYS as extra notes size if spufs is not loaded
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Because the SPU coredump code might be built as part of a module (spufs),
we have a stub which is called by the coredump code, this routine then calls
into spufs if it's loaded.
Unfortunately the stub returns -ENOSYS if spufs is not loaded, which is
interpreted by the coredump code as an extra note size of -38 bytes. This
leads to a corrupt core dump.
If spufs is not loaded there will be no SPU ELF notes to write, and so the
extra notes size will be == 0.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spu_coredump.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
index 4fd37ff..656a8c5 100644
--- a/arch/powerpc/platforms/cell/spu_coredump.c
+++ b/arch/powerpc/platforms/cell/spu_coredump.c
@@ -31,15 +31,19 @@ static DEFINE_MUTEX(spu_coredump_mutex);
int arch_notes_size(void)
{
- long ret;
+ int ret;
- ret = -ENOSYS;
mutex_lock(&spu_coredump_mutex);
+
if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
ret = spu_coredump_calls->arch_notes_size();
module_put(spu_coredump_calls->owner);
+ } else {
+ ret = 0;
}
+
mutex_unlock(&spu_coredump_mutex);
+
return ret;
}
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 08/15] Use spufs_coredump_num_notes everywhere, and don't NULL terminate
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
The spufs_coredump_read array is NULL terminated, and we also store the size.
We only need one or the other, and storing the size should save a teensy bit
of memory vs NULL terminating, so do that.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 2 +-
arch/powerpc/platforms/cell/spufs/file.c | 3 +--
2 files changed, 2 insertions(+), 3 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 52d6219..8348d21 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -72,7 +72,7 @@ static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
char *name;
char fullname[80];
- for (i = 0; spufs_coredump_read[i].name; i++) {
+ for (i = 0; i < spufs_coredump_num_notes; i++) {
name = spufs_coredump_read[i].name;
sz = spufs_coredump_read[i].size;
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 85edbec..220c7fe 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -2250,7 +2250,6 @@ struct spufs_coredump_reader spufs_coredump_read[] = {
{ "proxydma_info", __spufs_proxydma_info_read,
NULL, sizeof(struct spu_proxydma_info)},
{ "object-id", NULL, __spufs_object_id_get, 19 },
- { },
};
-int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read) - 1;
+int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 09/15] Internal __spufs_get_foo() routines should take a spu_context *
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
The SPUFS attribute get routines take a void * because the generic attribute
code doesn't know what sort of data it's passing around.
However our internal __spufs_get_foo() routines can take a spu_context *
directly, which saves plonking it in and out of a void * again.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/file.c | 40 +++++++++++-----------------
arch/powerpc/platforms/cell/spufs/spufs.h | 2 +-
2 files changed, 17 insertions(+), 25 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 220c7fe..d19220f 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1085,9 +1085,8 @@ static void spufs_signal1_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal1_type_get(void *data)
+static u64 __spufs_signal1_type_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->ops->signal1_type_get(ctx);
}
@@ -1097,7 +1096,7 @@ static u64 spufs_signal1_type_get(void *data)
u64 ret;
spu_acquire(ctx);
- ret = __spufs_signal1_type_get(data);
+ ret = __spufs_signal1_type_get(ctx);
spu_release(ctx);
return ret;
@@ -1114,9 +1113,8 @@ static void spufs_signal2_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal2_type_get(void *data)
+static u64 __spufs_signal2_type_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->ops->signal2_type_get(ctx);
}
@@ -1126,7 +1124,7 @@ static u64 spufs_signal2_type_get(void *data)
u64 ret;
spu_acquire(ctx);
- ret = __spufs_signal2_type_get(data);
+ ret = __spufs_signal2_type_get(ctx);
spu_release(ctx);
return ret;
@@ -1629,9 +1627,8 @@ static void spufs_decr_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_get(void *data)
+static u64 __spufs_decr_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->decr.slot[0];
}
@@ -1641,7 +1638,7 @@ static u64 spufs_decr_get(void *data)
struct spu_context *ctx = data;
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_decr_get(data);
+ ret = __spufs_decr_get(ctx);
spu_release_saved(ctx);
return ret;
}
@@ -1659,9 +1656,8 @@ static void spufs_decr_status_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_status_get(void *data)
+static u64 __spufs_decr_status_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING)
return SPU_DECR_STATUS_RUNNING;
else
@@ -1673,7 +1669,7 @@ static u64 spufs_decr_status_get(void *data)
struct spu_context *ctx = data;
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_decr_status_get(data);
+ ret = __spufs_decr_status_get(ctx);
spu_release_saved(ctx);
return ret;
}
@@ -1689,9 +1685,8 @@ static void spufs_event_mask_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_event_mask_get(void *data)
+static u64 __spufs_event_mask_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->event_mask.slot[0];
}
@@ -1701,16 +1696,15 @@ static u64 spufs_event_mask_get(void *data)
struct spu_context *ctx = data;
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_event_mask_get(data);
+ ret = __spufs_event_mask_get(ctx);
spu_release_saved(ctx);
return ret;
}
DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
spufs_event_mask_set, "0x%llx\n")
-static u64 __spufs_event_status_get(void *data)
+static u64 __spufs_event_status_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_state *state = &ctx->csa;
u64 stat;
stat = state->spu_chnlcnt_RW[0];
@@ -1725,7 +1719,7 @@ static u64 spufs_event_status_get(void *data)
u64 ret = 0;
spu_acquire_saved(ctx);
- ret = __spufs_event_status_get(data);
+ ret = __spufs_event_status_get(ctx);
spu_release_saved(ctx);
return ret;
}
@@ -1770,16 +1764,15 @@ static u64 spufs_id_get(void *data)
}
DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
-static u64 __spufs_object_id_get(void *data)
+static u64 __spufs_object_id_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->object_id;
}
static u64 spufs_object_id_get(void *data)
{
/* FIXME: Should there really be no locking here? */
- return __spufs_object_id_get(data);
+ return __spufs_object_id_get((struct spu_context *)data);
}
static void spufs_object_id_set(void *data, u64 id)
@@ -1791,9 +1784,8 @@ static void spufs_object_id_set(void *data, u64 id)
DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
spufs_object_id_set, "0x%llx\n");
-static u64 __spufs_lslr_get(void *data)
+static u64 __spufs_lslr_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
return ctx->csa.priv2.spu_lslr_RW;
}
@@ -1803,7 +1795,7 @@ static u64 spufs_lslr_get(void *data)
u64 ret;
spu_acquire_saved(ctx);
- ret = __spufs_lslr_get(data);
+ ret = __spufs_lslr_get(ctx);
spu_release_saved(ctx);
return ret;
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index 3dbffeb..f869a4b 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -296,7 +296,7 @@ struct spufs_coredump_reader {
char *name;
ssize_t (*read)(struct spu_context *ctx,
char __user *buffer, size_t size, loff_t *pos);
- u64 (*get)(void *data);
+ u64 (*get)(struct spu_context *ctx);
size_t size;
};
extern struct spufs_coredump_reader spufs_coredump_read[];
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 10/15] Add contents of npc file to SPU coredumps
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/file.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index d19220f..52f020a 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1606,12 +1606,17 @@ static void spufs_npc_set(void *data, u64 val)
spu_release(ctx);
}
+static u64 __spufs_npc_get(struct spu_context *ctx)
+{
+ return ctx->ops->npc_read(ctx);
+}
+
static u64 spufs_npc_get(void *data)
{
struct spu_context *ctx = data;
u64 ret;
spu_acquire(ctx);
- ret = ctx->ops->npc_read(ctx);
+ ret = __spufs_npc_get(ctx);
spu_release(ctx);
return ret;
}
@@ -2242,6 +2247,7 @@ struct spufs_coredump_reader spufs_coredump_read[] = {
{ "proxydma_info", __spufs_proxydma_info_read,
NULL, sizeof(struct spu_proxydma_info)},
{ "object-id", NULL, __spufs_object_id_get, 19 },
+ { "npc", NULL, __spufs_npc_get, 19 },
};
int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 11/15] Combine spufs_coredump_calls with spufs_calls
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Because spufs might be built as a module, we can't have other parts of the
kernel calling directly into it, we need stub routines that check first if the
module is loaded.
Currently we have two structures which hold callbacks for these stubs, the
syscalls are in spufs_calls and the coredump calls are in spufs_coredump_calls.
In both cases the logic for registering/unregistering is essentially the same,
so we can simplify things by combining the two.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/Makefile | 2 +-
arch/powerpc/platforms/cell/spu_coredump.c | 83 --------------------------
arch/powerpc/platforms/cell/spu_syscalls.c | 30 +++++++++
arch/powerpc/platforms/cell/spufs/coredump.c | 10 +---
arch/powerpc/platforms/cell/spufs/inode.c | 6 --
arch/powerpc/platforms/cell/spufs/spufs.h | 4 +
arch/powerpc/platforms/cell/spufs/syscalls.c | 2 +
include/asm-powerpc/spu.h | 12 +---
8 files changed, 41 insertions(+), 108 deletions(-)
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 40f78e9..61d12f1 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -19,7 +19,7 @@ spu-manage-$(CONFIG_PPC_CELLEB) += spu_manage.o
spu-manage-$(CONFIG_PPC_CELL_NATIVE) += spu_manage.o
obj-$(CONFIG_SPU_BASE) += spu_callbacks.o spu_base.o \
- spu_coredump.o spu_syscalls.o \
+ spu_syscalls.o \
$(spu-priv1-y) \
$(spu-manage-y) \
spufs/
diff --git a/arch/powerpc/platforms/cell/spu_coredump.c b/arch/powerpc/platforms/cell/spu_coredump.c
deleted file mode 100644
index 656a8c5..0000000
--- a/arch/powerpc/platforms/cell/spu_coredump.c
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * SPU core dump code
- *
- * (C) Copyright 2006 IBM Corp.
- *
- * Author: Dwayne Grant McConnell <decimal@us.ibm.com>
- *
- * 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, 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/file.h>
-#include <linux/module.h>
-#include <linux/syscalls.h>
-
-#include <asm/spu.h>
-
-static struct spu_coredump_calls *spu_coredump_calls;
-static DEFINE_MUTEX(spu_coredump_mutex);
-
-int arch_notes_size(void)
-{
- int ret;
-
- mutex_lock(&spu_coredump_mutex);
-
- if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
- ret = spu_coredump_calls->arch_notes_size();
- module_put(spu_coredump_calls->owner);
- } else {
- ret = 0;
- }
-
- mutex_unlock(&spu_coredump_mutex);
-
- return ret;
-}
-
-void arch_write_notes(struct file *file)
-{
- mutex_lock(&spu_coredump_mutex);
- if (spu_coredump_calls && try_module_get(spu_coredump_calls->owner)) {
- spu_coredump_calls->arch_write_notes(file);
- module_put(spu_coredump_calls->owner);
- }
- mutex_unlock(&spu_coredump_mutex);
-}
-
-int register_arch_coredump_calls(struct spu_coredump_calls *calls)
-{
- int ret = 0;
-
-
- mutex_lock(&spu_coredump_mutex);
- if (spu_coredump_calls)
- ret = -EBUSY;
- else
- spu_coredump_calls = calls;
- mutex_unlock(&spu_coredump_mutex);
- return ret;
-}
-EXPORT_SYMBOL_GPL(register_arch_coredump_calls);
-
-void unregister_arch_coredump_calls(struct spu_coredump_calls *calls)
-{
- BUG_ON(spu_coredump_calls != calls);
-
- mutex_lock(&spu_coredump_mutex);
- spu_coredump_calls = NULL;
- mutex_unlock(&spu_coredump_mutex);
-}
-EXPORT_SYMBOL_GPL(unregister_arch_coredump_calls);
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index 76815c5..cf00251 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -2,6 +2,7 @@
* SPU file system -- system call stubs
*
* (C) Copyright IBM Deutschland Entwicklung GmbH 2005
+ * (C) Copyright 2006-2007, IBM Corporation
*
* Author: Arnd Bergmann <arndb@de.ibm.com>
*
@@ -108,6 +109,35 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
return ret;
}
+int arch_notes_size(void)
+{
+ struct spufs_calls *calls;
+ int ret;
+
+ calls = spufs_calls_get();
+ if (!calls)
+ return 0;
+
+ ret = calls->coredump_extra_notes_size();
+
+ spufs_calls_put(calls);
+
+ return ret;
+}
+
+void arch_write_notes(struct file *file)
+{
+ struct spufs_calls *calls;
+
+ calls = spufs_calls_get();
+ if (!calls)
+ return;
+
+ calls->coredump_extra_notes_write(file);
+
+ spufs_calls_put(calls);
+}
+
int register_spu_syscalls(struct spufs_calls *calls)
{
int ret = 0;
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 8348d21..7395350 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -122,7 +122,7 @@ static struct spu_context *coredump_next_context(int *fd)
return ctx;
}
-static int spufs_arch_notes_size(void)
+int spufs_coredump_extra_notes_size(void)
{
struct spu_context *ctx;
int size = 0, rc, fd;
@@ -185,7 +185,7 @@ out:
free_page((unsigned long)buf);
}
-static void spufs_arch_write_notes(struct file *file)
+void spufs_coredump_extra_notes_write(struct file *file)
{
struct spu_context *ctx;
int fd, j;
@@ -200,9 +200,3 @@ static void spufs_arch_write_notes(struct file *file)
spu_release_saved(ctx);
}
}
-
-struct spu_coredump_calls spufs_coredump_calls = {
- .arch_notes_size = spufs_arch_notes_size,
- .arch_write_notes = spufs_arch_write_notes,
- .owner = THIS_MODULE,
-};
diff --git a/arch/powerpc/platforms/cell/spufs/inode.c b/arch/powerpc/platforms/cell/spufs/inode.c
index e210a4b..1109874 100644
--- a/arch/powerpc/platforms/cell/spufs/inode.c
+++ b/arch/powerpc/platforms/cell/spufs/inode.c
@@ -790,16 +790,11 @@ static int __init spufs_init(void)
ret = register_spu_syscalls(&spufs_calls);
if (ret)
goto out_fs;
- ret = register_arch_coredump_calls(&spufs_coredump_calls);
- if (ret)
- goto out_syscalls;
spufs_init_isolated_loader();
return 0;
-out_syscalls:
- unregister_spu_syscalls(&spufs_calls);
out_fs:
unregister_filesystem(&spufs_type);
out_sched:
@@ -815,7 +810,6 @@ static void __exit spufs_exit(void)
{
spu_sched_exit();
spufs_exit_isolated_loader();
- unregister_arch_coredump_calls(&spufs_coredump_calls);
unregister_spu_syscalls(&spufs_calls);
unregister_filesystem(&spufs_type);
kmem_cache_destroy(spufs_inode_cache);
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index f869a4b..c7b4e03 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -204,6 +204,10 @@ extern struct spufs_calls spufs_calls;
long spufs_run_spu(struct spu_context *ctx, u32 *npc, u32 *status);
long spufs_create(struct nameidata *nd, unsigned int flags,
mode_t mode, struct file *filp);
+/* ELF coredump callbacks for writing SPU ELF notes */
+extern int spufs_coredump_extra_notes_size(void);
+extern void spufs_coredump_extra_notes_write(struct file *file);
+
extern const struct file_operations spufs_context_fops;
/* gang management */
diff --git a/arch/powerpc/platforms/cell/spufs/syscalls.c b/arch/powerpc/platforms/cell/spufs/syscalls.c
index 22b138d..2c34f71 100644
--- a/arch/powerpc/platforms/cell/spufs/syscalls.c
+++ b/arch/powerpc/platforms/cell/spufs/syscalls.c
@@ -84,5 +84,7 @@ static long do_spu_create(const char __user *pathname, unsigned int flags,
struct spufs_calls spufs_calls = {
.create_thread = do_spu_create,
.spu_run = do_spu_run,
+ .coredump_extra_notes_size = spufs_coredump_extra_notes_size,
+ .coredump_extra_notes_write = spufs_coredump_extra_notes_write,
.owner = THIS_MODULE,
};
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index a0f2d28..10c40cd 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -244,13 +244,8 @@ struct spufs_calls {
struct file *neighbor);
long (*spu_run)(struct file *filp, __u32 __user *unpc,
__u32 __user *ustatus);
- struct module *owner;
-};
-
-/* coredump calls implemented in spufs */
-struct spu_coredump_calls {
- asmlinkage int (*arch_notes_size)(void);
- asmlinkage void (*arch_write_notes)(struct file *file);
+ int (*coredump_extra_notes_size)(void);
+ void (*coredump_extra_notes_write)(struct file *file);
struct module *owner;
};
@@ -277,9 +272,6 @@ struct spu_coredump_calls {
int register_spu_syscalls(struct spufs_calls *calls);
void unregister_spu_syscalls(struct spufs_calls *calls);
-int register_arch_coredump_calls(struct spu_coredump_calls *calls);
-void unregister_arch_coredump_calls(struct spu_coredump_calls *calls);
-
int spu_add_sysdev_attr(struct sysdev_attribute *attr);
void spu_remove_sysdev_attr(struct sysdev_attribute *attr);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 12/15] Cleanup ELF coredump extra notes logic
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
To start with, arch_notes_size() etc. is a little too ambiguous a name for
my liking, so change the function names to be more explicit.
Calling through macros is ugly, especially with hidden parameters, so don't
do that, call the routines directly.
Use ARCH_HAVE_EXTRA_ELF_NOTES as the only flag, and based on it decide
whether we want the extern declarations or the empty versions.
Since we have empty routines, actually use them in the coredump code to
save a few #ifdefs.
We want to change the handling of foffset so that the write routine updates
foffset as it goes, instead of using file->f_pos (so that writing to a pipe
works). So pass foffset to the write routine, and for now just set it to
file->f_pos at the end of writing.
It should also be possible for the write routine to fail, so change it to
return int and treat a non-zero return as failure.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spu_syscalls.c | 12 +++++++++---
fs/binfmt_elf.c | 14 +++-----------
include/asm-powerpc/elf.h | 9 ++-------
include/linux/elf.h | 14 ++++++++------
4 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index cf00251..d9b2fd2 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -21,6 +21,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <linux/file.h>
+#include <linux/fs.h>
#include <linux/module.h>
#include <linux/syscalls.h>
#include <linux/mutex.h>
@@ -109,7 +110,7 @@ asmlinkage long sys_spu_run(int fd, __u32 __user *unpc, __u32 __user *ustatus)
return ret;
}
-int arch_notes_size(void)
+int elf_coredump_extra_notes_size(void)
{
struct spufs_calls *calls;
int ret;
@@ -125,17 +126,22 @@ int arch_notes_size(void)
return ret;
}
-void arch_write_notes(struct file *file)
+int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
{
struct spufs_calls *calls;
calls = spufs_calls_get();
if (!calls)
- return;
+ return 0;
calls->coredump_extra_notes_write(file);
spufs_calls_put(calls);
+
+ /* Fudge foffset for now */
+ *foffset = file->f_pos;
+
+ return 0;
}
int register_spu_syscalls(struct spufs_calls *calls)
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 4482a06..b1013f3 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -1514,9 +1514,6 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
int thread_status_size = 0;
elf_addr_t *auxv;
unsigned long mm_flags;
-#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- int extra_notes_size;
-#endif
/*
* We no longer stop all VM operations.
@@ -1645,10 +1642,7 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
sz += thread_status_size;
-#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- extra_notes_size = ELF_CORE_EXTRA_NOTES_SIZE;
- sz += extra_notes_size;
-#endif
+ sz += elf_coredump_extra_notes_size();
fill_elf_note_phdr(&phdr, sz, offset);
offset += sz;
@@ -1698,10 +1692,8 @@ static int elf_core_dump(long signr, struct pt_regs *regs, struct file *file)
if (!writenote(notes + i, file, &foffset))
goto end_coredump;
-#ifdef ELF_CORE_WRITE_EXTRA_NOTES
- ELF_CORE_WRITE_EXTRA_NOTES;
- foffset += extra_notes_size;
-#endif
+ if (elf_coredump_extra_notes_write(file, &foffset))
+ goto end_coredump;
/* write out the thread status notes section */
list_for_each(t, &thread_list) {
diff --git a/include/asm-powerpc/elf.h b/include/asm-powerpc/elf.h
index de50799..e42820d 100644
--- a/include/asm-powerpc/elf.h
+++ b/include/asm-powerpc/elf.h
@@ -413,13 +413,8 @@ do { \
/* Notes used in ET_CORE. Note name is "SPU/<fd>/<filename>". */
#define NT_SPU 1
-extern int arch_notes_size(void);
-extern void arch_write_notes(struct file *file);
-
-#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
-#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
-
#define ARCH_HAVE_EXTRA_ELF_NOTES
-#endif /* CONFIG_PPC_CELL */
+
+#endif /* CONFIG_SPU_BASE */
#endif /* _ASM_POWERPC_ELF_H */
diff --git a/include/linux/elf.h b/include/linux/elf.h
index 8b17ffe..d2da84a 100644
--- a/include/linux/elf.h
+++ b/include/linux/elf.h
@@ -389,12 +389,14 @@ extern Elf64_Dyn _DYNAMIC [];
#endif
+/* Optional callbacks to write extra ELF notes. */
#ifndef ARCH_HAVE_EXTRA_ELF_NOTES
-static inline int arch_notes_size(void) { return 0; }
-static inline void arch_write_notes(struct file *file) { }
-
-#define ELF_CORE_EXTRA_NOTES_SIZE arch_notes_size()
-#define ELF_CORE_WRITE_EXTRA_NOTES arch_write_notes(file)
-#endif /* ARCH_HAVE_EXTRA_ELF_NOTES */
+static inline int elf_coredump_extra_notes_size(void) { return 0; }
+static inline int elf_coredump_extra_notes_write(struct file *file,
+ loff_t *foffset) { return 0; }
+#else
+extern int elf_coredump_extra_notes_size(void);
+extern int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset);
+#endif
#endif /* _LINUX_ELF_H */
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 13/15] Handle errors in SPU coredump code, and support coredump to a pipe
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Rework spufs_coredump_extra_notes_write() to check for and return errors.
If we're coredumping to a pipe we can't trust file->f_pos, we need to
maintain the foffset value passed to us. The cleanest way to do this is
to have the low level write routine increment foffset when we've
successfully written.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spu_syscalls.c | 8 +--
arch/powerpc/platforms/cell/spufs/coredump.c | 89 ++++++++++++++++++--------
arch/powerpc/platforms/cell/spufs/spufs.h | 2 +-
include/asm-powerpc/spu.h | 2 +-
4 files changed, 67 insertions(+), 34 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spu_syscalls.c b/arch/powerpc/platforms/cell/spu_syscalls.c
index d9b2fd2..0b69107 100644
--- a/arch/powerpc/platforms/cell/spu_syscalls.c
+++ b/arch/powerpc/platforms/cell/spu_syscalls.c
@@ -129,19 +129,17 @@ int elf_coredump_extra_notes_size(void)
int elf_coredump_extra_notes_write(struct file *file, loff_t *foffset)
{
struct spufs_calls *calls;
+ int ret;
calls = spufs_calls_get();
if (!calls)
return 0;
- calls->coredump_extra_notes_write(file);
+ ret = calls->coredump_extra_notes_write(file, foffset);
spufs_calls_put(calls);
- /* Fudge foffset for now */
- *foffset = file->f_pos;
-
- return 0;
+ return ret;
}
int register_spu_syscalls(struct spufs_calls *calls)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index 7395350..c3b5cd5 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -51,19 +51,34 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
* These are the only things you should do on a core-file: use only these
* functions to write out all the necessary info.
*/
-static int spufs_dump_write(struct file *file, const void *addr, int nr)
+static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
{
- return file->f_op->write(file, addr, nr, &file->f_pos) == nr;
+ ssize_t written;
+
+ written = file->f_op->write(file, addr, nr, &file->f_pos);
+ *foffset += written;
+
+ if (written != nr)
+ return -EIO;
+
+ return 0;
}
-static int spufs_dump_seek(struct file *file, loff_t off)
+static int spufs_dump_align(struct file *file, char *buf, loff_t new_off,
+ loff_t *foffset)
{
- if (file->f_op->llseek) {
- if (file->f_op->llseek(file, off, 0) != off)
- return 0;
- } else
- file->f_pos = off;
- return 1;
+ int rc, size;
+
+ size = min((loff_t)PAGE_SIZE, new_off - *foffset);
+ memset(buf, 0, size);
+
+ rc = 0;
+ while (rc == 0 && new_off > *foffset) {
+ size = min((loff_t)PAGE_SIZE, new_off - *foffset);
+ rc = spufs_dump_write(file, buf, size, foffset);
+ }
+
+ return rc;
}
static int spufs_ctx_note_size(struct spu_context *ctx, int dfd)
@@ -141,11 +156,11 @@ int spufs_coredump_extra_notes_size(void)
return size;
}
-static void spufs_arch_write_note(struct spu_context *ctx, int i,
- struct file *file, int dfd)
+static int spufs_arch_write_note(struct spu_context *ctx, int i,
+ struct file *file, int dfd, loff_t *foffset)
{
loff_t pos = 0;
- int sz, rc, total = 0;
+ int sz, rc, nread, total = 0;
const int bufsz = PAGE_SIZE;
char *name;
char fullname[80], *buf;
@@ -153,7 +168,7 @@ static void spufs_arch_write_note(struct spu_context *ctx, int i,
buf = (void *)get_zeroed_page(GFP_KERNEL);
if (!buf)
- return;
+ return -ENOMEM;
name = spufs_coredump_read[i].name;
sz = spufs_coredump_read[i].size;
@@ -163,40 +178,60 @@ static void spufs_arch_write_note(struct spu_context *ctx, int i,
en.n_descsz = sz;
en.n_type = NT_SPU;
- if (!spufs_dump_write(file, &en, sizeof(en)))
+ rc = spufs_dump_write(file, &en, sizeof(en), foffset);
+ if (rc)
goto out;
- if (!spufs_dump_write(file, fullname, en.n_namesz))
+
+ rc = spufs_dump_write(file, fullname, en.n_namesz, foffset);
+ if (rc)
goto out;
- if (!spufs_dump_seek(file, roundup((unsigned long)file->f_pos, 4)))
+
+ rc = spufs_dump_align(file, buf, roundup(*foffset, 4), foffset);
+ if (rc)
goto out;
do {
- rc = do_coredump_read(i, ctx, buf, bufsz, &pos);
- if (rc > 0) {
- if (!spufs_dump_write(file, buf, rc))
+ nread = do_coredump_read(i, ctx, buf, bufsz, &pos);
+ if (nread > 0) {
+ rc = spufs_dump_write(file, buf, nread, foffset);
+ if (rc)
goto out;
- total += rc;
+ total += nread;
}
- } while (rc == bufsz && total < sz);
+ } while (nread == bufsz && total < sz);
+
+ if (nread < 0) {
+ rc = nread;
+ goto out;
+ }
+
+ rc = spufs_dump_align(file, buf, roundup(*foffset - total + sz, 4),
+ foffset);
- spufs_dump_seek(file, roundup((unsigned long)file->f_pos
- - total + sz, 4));
out:
free_page((unsigned long)buf);
+ return rc;
}
-void spufs_coredump_extra_notes_write(struct file *file)
+int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset)
{
struct spu_context *ctx;
- int fd, j;
+ int fd, j, rc;
fd = 0;
while ((ctx = coredump_next_context(&fd)) != NULL) {
spu_acquire_saved(ctx);
- for (j = 0; j < spufs_coredump_num_notes; j++)
- spufs_arch_write_note(ctx, j, file, fd);
+ for (j = 0; j < spufs_coredump_num_notes; j++) {
+ rc = spufs_arch_write_note(ctx, j, file, fd, foffset);
+ if (rc) {
+ spu_release_saved(ctx);
+ return rc;
+ }
+ }
spu_release_saved(ctx);
}
+
+ return 0;
}
diff --git a/arch/powerpc/platforms/cell/spufs/spufs.h b/arch/powerpc/platforms/cell/spufs/spufs.h
index c7b4e03..ca47b99 100644
--- a/arch/powerpc/platforms/cell/spufs/spufs.h
+++ b/arch/powerpc/platforms/cell/spufs/spufs.h
@@ -206,7 +206,7 @@ long spufs_create(struct nameidata *nd, unsigned int flags,
mode_t mode, struct file *filp);
/* ELF coredump callbacks for writing SPU ELF notes */
extern int spufs_coredump_extra_notes_size(void);
-extern void spufs_coredump_extra_notes_write(struct file *file);
+extern int spufs_coredump_extra_notes_write(struct file *file, loff_t *foffset);
extern const struct file_operations spufs_context_fops;
diff --git a/include/asm-powerpc/spu.h b/include/asm-powerpc/spu.h
index 10c40cd..eed63dd 100644
--- a/include/asm-powerpc/spu.h
+++ b/include/asm-powerpc/spu.h
@@ -245,7 +245,7 @@ struct spufs_calls {
long (*spu_run)(struct file *filp, __u32 __user *unpc,
__u32 __user *ustatus);
int (*coredump_extra_notes_size)(void);
- void (*coredump_extra_notes_write)(struct file *file);
+ int (*coredump_extra_notes_write)(struct file *file, loff_t *foffset);
struct module *owner;
};
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 14/15] Respect RLIMIT_CORE in spu coredump code
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Currently the spu coredump code doesn't respect the ulimit, it should.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/coredump.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/coredump.c b/arch/powerpc/platforms/cell/spufs/coredump.c
index c3b5cd5..b8ab2c6 100644
--- a/arch/powerpc/platforms/cell/spufs/coredump.c
+++ b/arch/powerpc/platforms/cell/spufs/coredump.c
@@ -53,8 +53,12 @@ static ssize_t do_coredump_read(int num, struct spu_context *ctx, void *buffer,
*/
static int spufs_dump_write(struct file *file, const void *addr, int nr, loff_t *foffset)
{
+ unsigned long limit = current->signal->rlim[RLIMIT_CORE].rlim_cur;
ssize_t written;
+ if (*foffset + nr > limit)
+ return -EIO;
+
written = file->f_op->write(file, addr, nr, &file->f_pos);
*foffset += written;
--
1.5.1.3.g7a33b
^ permalink raw reply related
* [PATCH 15/15] Add DEFINE_SPUFS_ATTRIBUTE()
From: Michael Ellerman @ 2007-09-12 7:43 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
This patch adds DEFINE_SPUFS_ATTRIBUTE(), a wraper around
DEFINE_SIMPLE_ATTRIBUTE which does the specified locking for the get
routine for us.
Unfortunately we need two get routines (a locked and unlocked version) to
support the coredump code. This patch hides one of those (the locked version)
inside the macro foo.
Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
arch/powerpc/platforms/cell/spufs/file.c | 216 +++++++++++-------------------
1 files changed, 76 insertions(+), 140 deletions(-)
diff --git a/arch/powerpc/platforms/cell/spufs/file.c b/arch/powerpc/platforms/cell/spufs/file.c
index 52f020a..46ec8eb 100644
--- a/arch/powerpc/platforms/cell/spufs/file.c
+++ b/arch/powerpc/platforms/cell/spufs/file.c
@@ -1076,6 +1076,36 @@ static const struct file_operations spufs_signal2_nosched_fops = {
.mmap = spufs_signal2_mmap,
};
+/*
+ * This is a wrapper around DEFINE_SIMPLE_ATTRIBUTE which does the
+ * work of acquiring (or not) the SPU context before calling through
+ * to the actual get routine. The set routine is called directly.
+ */
+#define SPU_ATTR_NOACQUIRE 0
+#define SPU_ATTR_ACQUIRE 1
+#define SPU_ATTR_ACQUIRE_SAVED 2
+
+#define DEFINE_SPUFS_ATTRIBUTE(__name, __get, __set, __fmt, __acquire) \
+static u64 __##__get(void *data) \
+{ \
+ struct spu_context *ctx = data; \
+ u64 ret; \
+ \
+ if (__acquire == SPU_ATTR_ACQUIRE) { \
+ spu_acquire(ctx); \
+ ret = __get(ctx); \
+ spu_release(ctx); \
+ } else if (__acquire == SPU_ATTR_ACQUIRE_SAVED) { \
+ spu_acquire_saved(ctx); \
+ ret = __get(ctx); \
+ spu_release_saved(ctx); \
+ } else \
+ ret = __get(ctx); \
+ \
+ return ret; \
+} \
+DEFINE_SIMPLE_ATTRIBUTE(__name, __##__get, __set, __fmt);
+
static void spufs_signal1_type_set(void *data, u64 val)
{
struct spu_context *ctx = data;
@@ -1085,24 +1115,13 @@ static void spufs_signal1_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal1_type_get(struct spu_context *ctx)
+static u64 spufs_signal1_type_get(struct spu_context *ctx)
{
return ctx->ops->signal1_type_get(ctx);
}
+DEFINE_SPUFS_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
+ spufs_signal1_type_set, "%llu", SPU_ATTR_ACQUIRE);
-static u64 spufs_signal1_type_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
-
- spu_acquire(ctx);
- ret = __spufs_signal1_type_get(ctx);
- spu_release(ctx);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_signal1_type, spufs_signal1_type_get,
- spufs_signal1_type_set, "%llu");
static void spufs_signal2_type_set(void *data, u64 val)
{
@@ -1113,24 +1132,12 @@ static void spufs_signal2_type_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_signal2_type_get(struct spu_context *ctx)
+static u64 spufs_signal2_type_get(struct spu_context *ctx)
{
return ctx->ops->signal2_type_get(ctx);
}
-
-static u64 spufs_signal2_type_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
-
- spu_acquire(ctx);
- ret = __spufs_signal2_type_get(ctx);
- spu_release(ctx);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
- spufs_signal2_type_set, "%llu");
+DEFINE_SPUFS_ATTRIBUTE(spufs_signal2_type, spufs_signal2_type_get,
+ spufs_signal2_type_set, "%llu", SPU_ATTR_ACQUIRE);
#if SPUFS_MMAP_4K
static unsigned long spufs_mss_mmap_nopfn(struct vm_area_struct *vma,
@@ -1606,22 +1613,12 @@ static void spufs_npc_set(void *data, u64 val)
spu_release(ctx);
}
-static u64 __spufs_npc_get(struct spu_context *ctx)
+static u64 spufs_npc_get(struct spu_context *ctx)
{
return ctx->ops->npc_read(ctx);
}
-
-static u64 spufs_npc_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire(ctx);
- ret = __spufs_npc_get(ctx);
- spu_release(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
- "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_npc_ops, spufs_npc_get, spufs_npc_set,
+ "0x%llx\n", SPU_ATTR_ACQUIRE);
static void spufs_decr_set(void *data, u64 val)
{
@@ -1632,23 +1629,13 @@ static void spufs_decr_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_get(struct spu_context *ctx)
+static u64 spufs_decr_get(struct spu_context *ctx)
{
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->decr.slot[0];
}
-
-static u64 spufs_decr_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = __spufs_decr_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
- "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_decr_ops, spufs_decr_get, spufs_decr_set,
+ "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED);
static void spufs_decr_status_set(void *data, u64 val)
{
@@ -1661,25 +1648,16 @@ static void spufs_decr_status_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_decr_status_get(struct spu_context *ctx)
+static u64 spufs_decr_status_get(struct spu_context *ctx)
{
if (ctx->csa.priv2.mfc_control_RW & MFC_CNTL_DECREMENTER_RUNNING)
return SPU_DECR_STATUS_RUNNING;
else
return 0;
}
-
-static u64 spufs_decr_status_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = __spufs_decr_status_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
- spufs_decr_status_set, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_decr_status_ops, spufs_decr_status_get,
+ spufs_decr_status_set, "0x%llx\n",
+ SPU_ATTR_ACQUIRE_SAVED);
static void spufs_event_mask_set(void *data, u64 val)
{
@@ -1690,25 +1668,17 @@ static void spufs_event_mask_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 __spufs_event_mask_get(struct spu_context *ctx)
+static u64 spufs_event_mask_get(struct spu_context *ctx)
{
struct spu_lscsa *lscsa = ctx->csa.lscsa;
return lscsa->event_mask.slot[0];
}
-static u64 spufs_event_mask_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = __spufs_event_mask_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
- spufs_event_mask_set, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_event_mask_ops, spufs_event_mask_get,
+ spufs_event_mask_set, "0x%llx\n",
+ SPU_ATTR_ACQUIRE_SAVED);
-static u64 __spufs_event_status_get(struct spu_context *ctx)
+static u64 spufs_event_status_get(struct spu_context *ctx)
{
struct spu_state *state = &ctx->csa;
u64 stat;
@@ -1717,19 +1687,8 @@ static u64 __spufs_event_status_get(struct spu_context *ctx)
return state->spu_chnldata_RW[0];
return 0;
}
-
-static u64 spufs_event_status_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret = 0;
-
- spu_acquire_saved(ctx);
- ret = __spufs_event_status_get(ctx);
- spu_release_saved(ctx);
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
- NULL, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_event_status_ops, spufs_event_status_get,
+ NULL, "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
static void spufs_srr0_set(void *data, u64 val)
{
@@ -1740,44 +1699,32 @@ static void spufs_srr0_set(void *data, u64 val)
spu_release_saved(ctx);
}
-static u64 spufs_srr0_get(void *data)
+static u64 spufs_srr0_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
struct spu_lscsa *lscsa = ctx->csa.lscsa;
- u64 ret;
- spu_acquire_saved(ctx);
- ret = lscsa->srr0.slot[0];
- spu_release_saved(ctx);
- return ret;
+ return lscsa->srr0.slot[0];
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
- "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_srr0_ops, spufs_srr0_get, spufs_srr0_set,
+ "0x%llx\n", SPU_ATTR_ACQUIRE_SAVED)
-static u64 spufs_id_get(void *data)
+static u64 spufs_id_get(struct spu_context *ctx)
{
- struct spu_context *ctx = data;
u64 num;
- spu_acquire(ctx);
if (ctx->state == SPU_STATE_RUNNABLE)
num = ctx->spu->number;
else
num = (unsigned int)-1;
- spu_release(ctx);
return num;
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_id_ops, spufs_id_get, NULL, "0x%llx\n",
+ SPU_ATTR_ACQUIRE)
-static u64 __spufs_object_id_get(struct spu_context *ctx)
-{
- return ctx->object_id;
-}
-
-static u64 spufs_object_id_get(void *data)
+static u64 spufs_object_id_get(struct spu_context *ctx)
{
/* FIXME: Should there really be no locking here? */
- return __spufs_object_id_get((struct spu_context *)data);
+ return ctx->object_id;
}
static void spufs_object_id_set(void *data, u64 id)
@@ -1786,26 +1733,15 @@ static void spufs_object_id_set(void *data, u64 id)
ctx->object_id = id;
}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
- spufs_object_id_set, "0x%llx\n");
+DEFINE_SPUFS_ATTRIBUTE(spufs_object_id_ops, spufs_object_id_get,
+ spufs_object_id_set, "0x%llx\n", SPU_ATTR_NOACQUIRE);
-static u64 __spufs_lslr_get(struct spu_context *ctx)
+static u64 spufs_lslr_get(struct spu_context *ctx)
{
return ctx->csa.priv2.spu_lslr_RW;
}
-
-static u64 spufs_lslr_get(void *data)
-{
- struct spu_context *ctx = data;
- u64 ret;
-
- spu_acquire_saved(ctx);
- ret = __spufs_lslr_get(ctx);
- spu_release_saved(ctx);
-
- return ret;
-}
-DEFINE_SIMPLE_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n")
+DEFINE_SPUFS_ATTRIBUTE(spufs_lslr_ops, spufs_lslr_get, NULL, "0x%llx\n",
+ SPU_ATTR_ACQUIRE_SAVED);
static int spufs_info_open(struct inode *inode, struct file *file)
{
@@ -2230,24 +2166,24 @@ struct tree_descr spufs_dir_nosched_contents[] = {
struct spufs_coredump_reader spufs_coredump_read[] = {
{ "regs", __spufs_regs_read, NULL, sizeof(struct spu_reg128[128])},
{ "fpcr", __spufs_fpcr_read, NULL, sizeof(struct spu_reg128) },
- { "lslr", NULL, __spufs_lslr_get, 19 },
- { "decr", NULL, __spufs_decr_get, 19 },
- { "decr_status", NULL, __spufs_decr_status_get, 19 },
+ { "lslr", NULL, spufs_lslr_get, 19 },
+ { "decr", NULL, spufs_decr_get, 19 },
+ { "decr_status", NULL, spufs_decr_status_get, 19 },
{ "mem", __spufs_mem_read, NULL, LS_SIZE, },
{ "signal1", __spufs_signal1_read, NULL, sizeof(u32) },
- { "signal1_type", NULL, __spufs_signal1_type_get, 19 },
+ { "signal1_type", NULL, spufs_signal1_type_get, 19 },
{ "signal2", __spufs_signal2_read, NULL, sizeof(u32) },
- { "signal2_type", NULL, __spufs_signal2_type_get, 19 },
- { "event_mask", NULL, __spufs_event_mask_get, 19 },
- { "event_status", NULL, __spufs_event_status_get, 19 },
+ { "signal2_type", NULL, spufs_signal2_type_get, 19 },
+ { "event_mask", NULL, spufs_event_mask_get, 19 },
+ { "event_status", NULL, spufs_event_status_get, 19 },
{ "mbox_info", __spufs_mbox_info_read, NULL, sizeof(u32) },
{ "ibox_info", __spufs_ibox_info_read, NULL, sizeof(u32) },
{ "wbox_info", __spufs_wbox_info_read, NULL, 4 * sizeof(u32)},
{ "dma_info", __spufs_dma_info_read, NULL, sizeof(struct spu_dma_info)},
{ "proxydma_info", __spufs_proxydma_info_read,
NULL, sizeof(struct spu_proxydma_info)},
- { "object-id", NULL, __spufs_object_id_get, 19 },
- { "npc", NULL, __spufs_npc_get, 19 },
+ { "object-id", NULL, spufs_object_id_get, 19 },
+ { "npc", NULL, spufs_npc_get, 19 },
};
int spufs_coredump_num_notes = ARRAY_SIZE(spufs_coredump_read);
--
1.5.1.3.g7a33b
^ permalink raw reply related
* Re: [PATCH 15/15] Add DEFINE_SPUFS_ATTRIBUTE()
From: Michael Ellerman @ 2007-09-12 7:49 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Jeremy Kerr, linux-kernel
In-Reply-To: <f5fe712aef37d925902f3f6183f024b916cc89db.1189583010.git.michael@ellerman.id.au>
[-- Attachment #1: Type: text/plain, Size: 1003 bytes --]
On Wed, 2007-09-12 at 17:43 +1000, Michael Ellerman wrote:
> This patch adds DEFINE_SPUFS_ATTRIBUTE(), a wraper around
> DEFINE_SIMPLE_ATTRIBUTE which does the specified locking for the get
> routine for us.
>
> Unfortunately we need two get routines (a locked and unlocked version) to
> support the coredump code. This patch hides one of those (the locked version)
> inside the macro foo.
>
> Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
> ---
> arch/powerpc/platforms/cell/spufs/file.c | 216 +++++++++++-------------------
> 1 files changed, 76 insertions(+), 140 deletions(-)
jk said:
> "Good god man!"
Yeah, I'm a bit lukewarm on this one. But the diffstat is nice, 50% code
reduction ain't bad :)
cheers
--
Michael Ellerman
OzLabs, IBM Australia Development Lab
wwweb: http://michael.ellerman.id.au
phone: +61 2 6212 1183 (tie line 70 21183)
We do not inherit the earth from our ancestors,
we borrow it from our children. - S.M.A.R.T Person
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 189 bytes --]
^ permalink raw reply
* Re: [PATCH] [RFC][POWERPC] Merge 32 and 64 bit pci_process_bridge_OF_ranges() instances
From: Arnd Bergmann @ 2007-09-12 8:13 UTC (permalink / raw)
To: Vitaly Bordug; +Cc: linuxppc-dev
In-Reply-To: <20070912035602.0be0d47e@localhost.localdomain>
On Wednesday 12 September 2007, Vitaly Bordug wrote:
>
> Well, it's more a rewrite than a move, based on 64-bit implementation.
ok.
> > Could you perhaps split the patch into two separate changesets, one
> > that makes both functions identical in place, and one that merges
> > them to live in a common location?
> >
> I'm not sure I'm following what you are requesting. What is a benefit of
> code duplication? I was thinking about, if it will look good enough, to
> provide this function at generic level but changing its name a little,
> while leaving old stuff in place, and encouraging people to use it in
> favour of 32 or 64-bit-specific approaches. That way we won't kill many
> boards at once(in case, for example,odd dts with missed ranges for
> pci subnode).
I wasn't suggesting to leave the duplicated code in, but rather to
make the review easier by first modifying the code in place.
If you're taking the 64 bit code as a base, you can for instance make
the first patch leave pci_32 alone, and modify the 64 bit
pci_process_bridge_OF_ranges to look exactly like the merged version.
That allows us to see what changed in the 64 bit case.
The second patch would then move the functions over, but leave the
code identical to the result of the first patch.
> > > diff --git a/include/asm-powerpc/ppc-pci.h
> > > b/include/asm-powerpc/ppc-pci.h index b847aa1..882b8bc 100644
> > > --- a/include/asm-powerpc/ppc-pci.h
> > > +++ b/include/asm-powerpc/ppc-pci.h
> > > @@ -15,6 +15,13 @@
> > > #include <linux/pci.h>
> > > #include <asm/pci-bridge.h>
> > >
> > > +struct ranges_pci {
> > > + unsigned int pci_space;
> > > + u64 pci_addr;
> > > + phys_addr_t phys_addr;
> > > + u64 size;
> > > +} __attribute__((packed));
> > > +
> >
> > This structure definition uses unaligned members because of the
> > 'packed' attribute. Is that really what you intended?
> >
> yes, exactly, because I'm mapping this struct on ranges extracted from
> the dts instead of juggling with ranges[foo] offsets.
I see. It does however look wrong to me, because you are using a hardcoded
phys_addr_t type. This breaks when phys_addr has a different size from what
you expect, e.g. when booting a pure 32 bit kernel on a machine that has
a 64 bit physical address space.
Arnd <><
^ permalink raw reply
* Re: [PATCH 01/15] Extract the file descriptor search logic in SPU coredump code
From: Jeremy Kerr @ 2007-09-12 8:17 UTC (permalink / raw)
To: Michael Ellerman; +Cc: linuxppc-dev, Andrew Morton, linux-kernel
In-Reply-To: <2900ea4dbfd6e98e71ff400cbd25d1283a278972.1189583010.git.michael@ellerman.id.au>
Hi Michael,
This series looks good to me, thanks for the fixes. I'll do some testing
tomorrow but it looks like it'll be fine as-is.
Andrew - almost all of these are for spufs, the notable exception being:
[PATCH 12/15] Cleanup ELF coredump extra notes logic
which touches the generic elf/coredump path.
Are you ok for me to merge this to my spufs tree, and upstream via
paulus?
Cheers,
Jeremy
^ permalink raw reply
* Re: [PATCH 1/3] Implement arch disable/enable irq hooks.
From: Johannes Berg @ 2007-09-12 8:23 UTC (permalink / raw)
To: Paul Mackerras; +Cc: linuxppc-dev
In-Reply-To: <18151.1452.702936.394284@cargo.ozlabs.ibm.com>
[-- Attachment #1: Type: text/plain, Size: 587 bytes --]
On Wed, 2007-09-12 at 07:16 +1000, Paul Mackerras wrote:
> > +/* Overrides the weak version in kernel/power/main.c */
> > +void arch_suspend_disable_irqs(void)
> > +{
> > + if (ppc_md.suspend_disable_irqs)
> > + ppc_md.suspend_disable_irqs();
> > + else
> > + generic_suspend_disable_irqs();
>
> Any particular reason why we need a ppc_md hook here? Do we expect
> some platform to need to do something different?
Yes, we need to hook into these for the PMU and platform functions on
powermac. Once I get to convert that to the generic infrastructure...
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply
* Re: [PATCH 01/15] Extract the file descriptor search logic in SPU coredump code
From: Andrew Morton @ 2007-09-12 8:35 UTC (permalink / raw)
To: Jeremy Kerr; +Cc: linuxppc-dev, linux-kernel
In-Reply-To: <200709121817.43263.jk@ozlabs.org>
On Wed, 12 Sep 2007 18:17:42 +1000 Jeremy Kerr <jk@ozlabs.org> wrote:
> This series looks good to me, thanks for the fixes. I'll do some testing
> tomorrow but it looks like it'll be fine as-is.
>
> Andrew - almost all of these are for spufs, the notable exception being:
>
> [PATCH 12/15] Cleanup ELF coredump extra notes logic
>
> which touches the generic elf/coredump path.
>
> Are you ok for me to merge this to my spufs tree, and upstream via
> paulus?
Sure. I'd only get in the way with spufs stuff.
^ 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