* Re: [PATCH v2] powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
From: Anton Vorontsov @ 2008-07-15 16:10 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <C3A1E950-3D5F-4172-90B6-1566D4A70B7C@kernel.crashing.org>
On Tue, Jul 15, 2008 at 08:21:38AM -0500, Kumar Gala wrote:
>
> On Jul 4, 2008, at 11:53 AM, Anton Vorontsov wrote:
>
>> This patch adds few bindings for the new drivers to be submitted
>> through
>> the appropriate maintainers.
>>
>> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
>> ---
>>
>> Updated to decrypt MCU, and to split the bindings into appropriate
>> files.
>>
>> .../powerpc/device-tree/fsl/mcu-mpc8349emitx.txt | 17 +++++++++
>> Documentation/powerpc/device-tree/fsl/qe/usb.txt | 37 +++++++++++
>> +++++++++
>> Documentation/powerpc/device-tree/fsl/upm-nand.txt | 28 +++++++++++
>> ++++
>> Documentation/powerpc/device-tree/gpio/led.txt | 15 ++++++++
>> 4 files changed, 97 insertions(+), 0 deletions(-)
>> create mode 100644 Documentation/powerpc/device-tree/fsl/mcu-
>> mpc8349emitx.txt
>> create mode 100644 Documentation/powerpc/device-tree/fsl/qe/usb.txt
>> create mode 100644 Documentation/powerpc/device-tree/fsl/upm-nand.txt
>> create mode 100644 Documentation/powerpc/device-tree/gpio/led.txt
>
> applied.
Ugh, you fixed bindings' directory in Jochen's CPM patch, but not in
my patch:
commit 91993d56812fd09b6cccea12d3c83df623cb0ea6
Author: Anton Vorontsov <avorontsov@ru.mvista.com>
Date: Fri Jul 4 20:53:28 2008 +0400
powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
This patch adds few bindings for the new drivers to be submitted through
the appropriate maintainers.
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
diff --git a/Documentation/powerpc/device-tree/fsl/mcu-mpc8349emitx.txt b/Documentation/powerpc/device-tree/fsl/mcu-mpc8349emit
new file mode 100644
index 0000000..0f76633
--- /dev/null
+++ b/Documentation/powerpc/device-tree/fsl/mcu-mpc8349emitx.txt
....
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH v2.6.26] powerpc: Add support for multiple gfar mdio interfaces
From: Kumar Gala @ 2008-07-15 16:15 UTC (permalink / raw)
To: Andy Fleming; +Cc: linuxppc-dev
In-Reply-To: <1209751430-25656-1-git-send-email-afleming@freescale.com>
On May 2, 2008, at 1:03 PM, Andy Fleming wrote:
> The old code assumed there was only one, but the 8572 actually has 3.
>
> Also, our usual id, 0xe0024520, gets resolved to -1 somewhere, and
> this was
> preventing the multiple buses from having different ids. So we only
> keep
> the low 20 bits, which have the interesting info, anyway.
>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
> arch/powerpc/sysdev/fsl_soc.c | 84 +++++++++++++++++
> +----------------------
> 1 files changed, 38 insertions(+), 46 deletions(-)
applied.
- k
^ permalink raw reply
* Re: [PATCH v2] powerpc: Fix a bunch of sparse warnings in the qe_lib
From: Kumar Gala @ 2008-07-15 16:15 UTC (permalink / raw)
To: Andy Fleming; +Cc: linuxppc-dev, timur.tabi
In-Reply-To: <1210184384-28425-1-git-send-email-afleming@freescale.com>
On May 7, 2008, at 1:19 PM, Andy Fleming wrote:
> Mostly having to do with not marking things __iomem. And some failure
> to use appropriate accessors to read MMIO regs.
>
> Signed-off-by: Andy Fleming <afleming@freescale.com>
> ---
> arch/powerpc/sysdev/qe_lib/qe.c | 6 +++---
> arch/powerpc/sysdev/qe_lib/ucc.c | 6 +++---
> arch/powerpc/sysdev/qe_lib/ucc_fast.c | 16 ++++++++--------
> include/asm-powerpc/ucc_fast.h | 8 ++++----
> 4 files changed, 18 insertions(+), 18 deletions(-)
applied.
- k
^ permalink raw reply
* Re: 2.6.26 does not boot on Pegasos
From: Jon Smirl @ 2008-07-15 16:15 UTC (permalink / raw)
To: Matt Sealey; +Cc: linuxppc-dev list
In-Reply-To: <487CC1F5.5090706@genesi-usa.com>
On 7/15/08, Matt Sealey <matt@genesi-usa.com> wrote:
> If you built this kernel yourself, you need to do it from a system with
> an up-to-date binutils (2.18) otherwise, it does this.
>
> If you got it from somewhere (like a distribution) then please tell us
> where, as there are some other troubles with load-base location for
> Fedora and so on...
Is it hard to put a check into the kernel make system to look for
binutils 2.17 and refuse to build with a nice error message? I poked
around in the makefile but I'm not 100% sure of how it works.
>
> --
> Matt Sealey <matt@genesi-usa.com>
> Genesi, Manager, Developer Relations
>
>
> Gabriel Paubert wrote:
>
> > Hi,
> >
> > I just tried to boot 2.6.26 on a Pegasos and the kernel does not boot.
> > The last message I have is:
> > gunzip (0xffffffff <----- some more hex digits)
> >
> > The configuration has been created from a working 2.6.25 one with
> > make oldconfig and answering N to new config options.
> >
> > Anybody has seen this or do I have to start digging deeper?
> >
> > Regards,
> > Gabriel
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-dev
> >
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@ozlabs.org
> https://ozlabs.org/mailman/listinfo/linuxppc-dev
>
--
Jon Smirl
jonsmirl@gmail.com
^ permalink raw reply
* Re: [PATCH 1/2] [POWERPC] 86xx: suspend support
From: Kumar Gala @ 2008-07-15 16:16 UTC (permalink / raw)
To: Anton Vorontsov; +Cc: Scott Wood, linuxppc-dev, Timur Tabi, Jason Jin
In-Reply-To: <20080606192443.GA20132@polina.dev.rtsoft.ru>
On Jun 6, 2008, at 2:24 PM, Anton Vorontsov wrote:
> This patch adds suspend (standby, not suspend-to-ram) support for
> MPC86xx
> processors.
>
> In standby mode MPC86xx is able to wakeup only upon external
> interrupts
> (including sreset).
>
> Signed-off-by: Scott Wood <scottwood@freescale.com>
> Signed-off-by: Jason Jin <Jason.jin@freescale.com>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> ---
> arch/powerpc/Kconfig | 2 +-
> arch/powerpc/platforms/86xx/Makefile | 1 +
> arch/powerpc/platforms/86xx/mpc86xx_suspend.c | 92 ++++++++++++++++
> +++++++++
> 3 files changed, 94 insertions(+), 1 deletions(-)
> create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_suspend.c
I'd like to understand how much PM support these patches really add w/
regards to the work Scott's done for 83xx PM.
- k
^ permalink raw reply
* Re: [PATCH 1/2] [POWERPC] 86xx: suspend support
From: Anton Vorontsov @ 2008-07-15 16:49 UTC (permalink / raw)
To: Kumar Gala; +Cc: Scott Wood, linuxppc-dev, Timur Tabi, Jason Jin
In-Reply-To: <899616AF-593D-4B7A-A64E-3F15934CE6CF@kernel.crashing.org>
On Tue, Jul 15, 2008 at 11:16:14AM -0500, Kumar Gala wrote:
>
> On Jun 6, 2008, at 2:24 PM, Anton Vorontsov wrote:
>
>> This patch adds suspend (standby, not suspend-to-ram) support for
>> MPC86xx
>> processors.
>>
>> In standby mode MPC86xx is able to wakeup only upon external
>> interrupts
>> (including sreset).
>>
>> Signed-off-by: Scott Wood <scottwood@freescale.com>
>> Signed-off-by: Jason Jin <Jason.jin@freescale.com>
>> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
>> ---
>> arch/powerpc/Kconfig | 2 +-
>> arch/powerpc/platforms/86xx/Makefile | 1 +
>> arch/powerpc/platforms/86xx/mpc86xx_suspend.c | 92 ++++++++++++++++
>> +++++++++
>> 3 files changed, 94 insertions(+), 1 deletions(-)
>> create mode 100644 arch/powerpc/platforms/86xx/mpc86xx_suspend.c
>
> I'd like to understand how much PM support these patches really add w/
> regards to the work Scott's done for 83xx PM.
This support provides "sleep" mode, i.e. almost all internal core
functions are off, some peripherals could be turned off, but sysclk
must be preserved. Upon wakeup CPU continues execution where it was
put to sleep. This is also called standby mode.
This patch does not implement "deep sleep" (suspend-to-ram) mode yet.
Deep sleep can save more power: CPU can be turned off completely (except
SDRAM -- it must still receive refresh cycles).
But deep sleep is also more tricky to implement.. During deep sleep CPU
losing all track of execution and state, thus upon wakeup CPU starts
execution of the firmware, so the firmware should be also aware of deep
sleep capability.
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Please Help me for generating the download.bit image
From: Naresh Bhat @ 2008-07-15 17:13 UTC (permalink / raw)
To: linuxppc-embedded
[-- Attachment #1: Type: text/plain, Size: 338 bytes --]
Hi All,
While generating the "linux_system.bit" for my ML403 board I am getting this
error
/bin/sh: line 1: 6954 Aborted bitgen -w -f bitgen.ut
system_linux
make: *** [implementation/system_linux.bit] Error 134
Done!
can anybody tell why I am getting this error? Please help me on this
issue....-:(
--
Naresh Bhat
[-- Attachment #2: Type: text/html, Size: 520 bytes --]
^ permalink raw reply
* Videomode 800x480
From: Alex_SYS @ 2008-07-15 17:24 UTC (permalink / raw)
To: linuxppc-embedded
Hello, I have the problem that I need a Framebuffer resolution 800x480!
Since now I have filled the fb_info, var and fix Structs!
But there was the problem with the resolution!
I have found out that the problem is the videomode!
In modedb there is unfortunately no 800x480 Videomode, and I have tried my
own 800x480 Struct, but the Kernel does`t want my settings (I tried to
change an 800x600 to 800x480 only by changing yres to 480).
Can someone tell me please a working fb_videomode struct for 800x480?
The syncs are setted up by U-Boot .
Thank you very much
--
View this message in context: http://www.nabble.com/Videomode-800x480-tp18470632p18470632.html
Sent from the linuxppc-embedded mailing list archive at Nabble.com.
^ permalink raw reply
* Re: [PATCH v2] powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
From: Kumar Gala @ 2008-07-15 16:23 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080715161053.GA9356@polina.dev.rtsoft.ru>
>>
> Ugh, you fixed bindings' directory in Jochen's CPM patch, but not in
> my patch:
>
> commit 91993d56812fd09b6cccea12d3c83df623cb0ea6
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: Fri Jul 4 20:53:28 2008 +0400
>
> powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
>
> This patch adds few bindings for the new drivers to be submitted
> through
> the appropriate maintainers.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>
> diff --git a/Documentation/powerpc/device-tree/fsl/mcu-
> mpc8349emitx.txt b/Documentation/powerpc/device-tree/fsl/mcu-
> mpc8349emit
> new file mode 100644
> index 0000000..0f76633
> --- /dev/null
> +++ b/Documentation/powerpc/device-tree/fsl/mcu-mpc8349emitx.txt
> ....
Rebased the tree and fixed it. Can you look over the files and make
sure everything looks ok. (I'm partially concerned about the QE usb
node).
- k
^ permalink raw reply
* Re: [PATCH v2] powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
From: Kumar Gala @ 2008-07-15 16:17 UTC (permalink / raw)
To: avorontsov; +Cc: linuxppc-dev
In-Reply-To: <20080715161053.GA9356@polina.dev.rtsoft.ru>
>>
> Ugh, you fixed bindings' directory in Jochen's CPM patch, but not in
> my patch:
>
> commit 91993d56812fd09b6cccea12d3c83df623cb0ea6
> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
> Date: Fri Jul 4 20:53:28 2008 +0400
>
> powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
>
> This patch adds few bindings for the new drivers to be submitted
> through
> the appropriate maintainers.
>
> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>
> diff --git a/Documentation/powerpc/device-tree/fsl/mcu-
> mpc8349emitx.txt b/Documentation/powerpc/device-tree/fsl/mcu-
> mpc8349emit
> new file mode 100644
> index 0000000..0f76633
> --- /dev/null
> +++ b/Documentation/powerpc/device-tree/fsl/mcu-mpc8349emitx.txt
> ....
duh. will fix it up.
- k
^ permalink raw reply
* Re: GPIO drivers, other patches?
From: Anton Vorontsov @ 2008-07-15 17:42 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev list
In-Reply-To: <20080715160048.GA31615@polina.dev.rtsoft.ru>
On Tue, Jul 15, 2008 at 08:00:48PM +0400, Anton Vorontsov wrote:
> On Tue, Jul 15, 2008 at 10:10:21AM -0500, Kumar Gala wrote:
> > Anton,
> >
> > I think I've gotten most of the patches from you,
>
> Yes, much thanks!
>
> > but I know there are
> > few I've lost. Can you just repost any patches that aren't in my
> > powerpc-next tree.
While testing the tree in run-time found that this patch is missing:
[PATCH 3/4] powerpc: rtc_cmos_setup: assign interrupts only if there is i8259 PIC
http://patchwork.ozlabs.org/linuxppc/patch?id=18915
Without this patch rtc will fail to probe on MPC8610HPCD:
rtc_cmos rtc_cmos: rtc core: registered rtc_cmos as rtc0
rtc_cmos: probe of rtc_cmos failed with error -38
Did you deliberately hold off this patch, i.e. should I ask Benjamin
to take this through his tree?
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* Re: [PATCH v2] powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
From: Anton Vorontsov @ 2008-07-15 17:48 UTC (permalink / raw)
To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <9340606A-7A87-4475-A133-81F5B59C7960@kernel.crashing.org>
On Tue, Jul 15, 2008 at 11:23:42AM -0500, Kumar Gala wrote:
>>>
>> Ugh, you fixed bindings' directory in Jochen's CPM patch, but not in
>> my patch:
>>
>> commit 91993d56812fd09b6cccea12d3c83df623cb0ea6
>> Author: Anton Vorontsov <avorontsov@ru.mvista.com>
>> Date: Fri Jul 4 20:53:28 2008 +0400
>>
>> powerpc: add FHCI USB, FSL MCU, FSL UPM and GPIO LEDs bindings
>>
>> This patch adds few bindings for the new drivers to be submitted
>> through
>> the appropriate maintainers.
>>
>> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
>> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
>>
>> diff --git a/Documentation/powerpc/device-tree/fsl/mcu-
>> mpc8349emitx.txt b/Documentation/powerpc/device-tree/fsl/mcu-
>> mpc8349emit
>> new file mode 100644
>> index 0000000..0f76633
>> --- /dev/null
>> +++ b/Documentation/powerpc/device-tree/fsl/mcu-mpc8349emitx.txt
>> ....
>
> Rebased the tree and fixed it. Can you look over the files and make
> sure everything looks ok. (I'm partially concerned about the QE usb
> node).
Yes, everything looks fine. b-w-of specified old QE USB bindings,
and no single driver actually used them.
Thanks,
--
Anton Vorontsov
email: cbouatmailru@gmail.com
irc://irc.freenode.net/bd2
^ permalink raw reply
* RE: 82xx performance
From: Rune Torgersen @ 2008-07-15 18:12 UTC (permalink / raw)
To: Milton Miller; +Cc: linuxppc-dev
In-Reply-To: <9dc3e1e709ad1aa47ae4c73f18c4d5e0@bga.com>
> 9919_unit Linux 2.6.25 powerpc-linux-gnu 434 32 32 =20
> > 1.0000 1
> > 9919_unit Linux 2.6.18 powerpc-linux-gnu 445 32 32 =20
> > 1.0100 1
>=20
> Hmm, processor MHz is off by 11/445
I noticed that.
> And memory latency is off 13/500.
>=20
> That sounds like it will be 16/666.
>=20
> Are you using the same board and the same firmware?
Yes. Same board, same firmware, same filesystem, just booted with
different kernels.
>=20
> If so, look at /proc/cpuinfo and/or the boot log to see what
> frequency linux thinks the processor is running at. It sounds
> like someone introduced or fixed a rounding error error calculating
> the timebase frequency for your board.
2.6.18 /proc/cpuinfo
processor : 0
cpu : G2_LE
revision : 1.4 (pvr 8082 2014)
bogomips : 296.96
chipset : 8250
vendor : Innovative Systems LLC
machine : AP Gold
mem size : 0x40000000
console baud : 115200
core clock : 447 MHz
CPM clock : 298 MHz
bus clock : 99 MHz
2.6.25 /proc/cpuinfo
processor : 0
cpu : G2_LE
clock : 447.897600MHz
revision : 1.4 (pvr 8082 2014)
bogomips : 49.53
timebase : 24883200
platform : Innovative Systems ApMax
> Please try the sleep test: sleep for 100 seconds, and time with
> either a stopwatch or another system. I think you will find they
> take different amounts of time, and all the results need to be scaled.
> You might be able to see it reading the hardware clock.
Sleep 100 takes excactly 100 seconds on both kernels (verified with
stopwatch and external ntp server)
^ permalink raw reply
* RE: 82xx performance
From: Rune Torgersen @ 2008-07-15 18:25 UTC (permalink / raw)
To: Arnd Bergmann, linuxppc-dev
In-Reply-To: <200807142244.07450.arnd@arndb.de>
> * Maybe there is a kernel version that supports your hardware in both
> arch/ppc/ and arch/powerpc. In that case, you could see if=20
> the platform
> change had an impact.
Using arch/ppc I got a 2.6.25 kernel to boot, and the kernel compile
test I did is almost identical (within 1%) of what the arch/powerpc
2.6.25 did, so it seems to be a difference between 2.6.18 and 2.6.25
(I'll see if I can find an exact version, as I think my ppc port can be
compiled for all versions from 2.6.18 to 25)
And running oprofile didn't help much, as it seems not to have been able
to figure out what in the kernel got called. (the Freescale 82xx dcoes
not have hw performance registers)
^ permalink raw reply
* Re: Videomode 800x480
From: Anatolij Gustschin @ 2008-07-15 18:29 UTC (permalink / raw)
To: Alex_SYS; +Cc: linuxppc-embedded
In-Reply-To: <18470632.post@talk.nabble.com>
Hello,
Alex_SYS wrote:
> Hello, I have the problem that I need a Framebuffer resolution 800x480!
> Since now I have filled the fb_info, var and fix Structs!
> But there was the problem with the resolution!
> I have found out that the problem is the videomode!
> In modedb there is unfortunately no 800x480 Videomode, and I have tried my
> own 800x480 Struct, but the Kernel does`t want my settings (I tried to
> change an 800x600 to 800x480 only by changing yres to 480).
> Can someone tell me please a working fb_videomode struct for 800x480?
Values for 800x480 fb_videomode depend on the TFT-panel that
you are using. Without the spec of this panel it is hard to guess.
It is also hard to guess the value for .pixclock as we do not know
if internal or external clock is used as the source for display
reference clock. What is the value of GDC DCM0 register (at
offset 0x1fd0000 or 0x1fd0100 from the GDC base)?
Try something like this:
.xres = 800
.yres = 480
.pixclock = 40000
.left_margin = 86
.right_margin = 42
.upper_margin = 33
.lower_margin = 10
.hsync_len = 128
.vsync_len = 2
> The syncs are setted up by U-Boot .
then you probably should retrieve proper values for fb_videomode
from display controller registers set up by U-Boot. If you do not
have the spec for your panel, it is the way to go. Consult the
GDC manual (Display control registers section) and
Documentation/fb/framebuffer.txt in the linux source tree.
Best regards,
Anatolij
^ permalink raw reply
* DTC: libfdt Install Woes
From: Jon Loeliger @ 2008-07-15 19:26 UTC (permalink / raw)
To: linuxppc-dev@ozlabs.org
David,
Somewhat recently, the DTC commit 6a6c972cdf9e
"dtc: Clean up included Makefile fragments"
removed this line
LIBFDT_INCLUDES = fdt.h libfdt.h
from the libfdt/Makefile.libfdt. As a result,
the standalone "make install" is onw failing.
We could put that line back, or remove the
top-level Makefile install target that is
trying to use this definition.
I'm not sure which direction you want to head here.
Thanks,
jdl
^ permalink raw reply
* Re: 82xx performance
From: Arnd Bergmann @ 2008-07-15 19:50 UTC (permalink / raw)
To: linuxppc-dev
In-Reply-To: <DCEAAC0833DD314AB0B58112AD99B93B04AE6877@ismail.innsys.innovsys.com>
On Tuesday 15 July 2008, Rune Torgersen wrote:
> Using arch/ppc I got a 2.6.25 kernel to boot, and the kernel compile
> test I did is almost identical (within 1%) of what the arch/powerpc
> 2.6.25 did, so it seems to be a difference between 2.6.18 and 2.6.25
> (I'll see if I can find an exact version, as I think my ppc port can be
> compiled for all versions from 2.6.18 to 25)
You probably already know git-bisect, but if you don't, you should
definitely give it a try. It's the best tool to find which patch
exactly broke your performance.
Arnd <><
^ permalink raw reply
* [patch 0/9] Cell patches for 2.6.27, version 2
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev
Hi Ben,
These are the remaining patches I have lined up for 2.6.27.
Thanks for including the others already. There were a few
comments in the last round that I hope all got addressed now.
I'm not sure about the final two patches for the IOMMU, I think
you wanted to investigate the situation more, but I haven't
seen an update from you any more. I'm convinced going to weak
ordering is the right move for the cell IOMMU, and even if it
is not, it will not break anything on current machines because
the firmware already overrides this setting.
I have left the copy_to_user in AZFS in place, I think we
need to follow up on this again, to either document that
copy_fromto_user needs to be able to work on uncached memory,
or to do an extra copy, but I think this should not hold up
the AZFS merge. All other comments for it have been addressed.
You can pull from the usual location at
master.kernel.org:/pub/scm/linux/kernel/git/arnd/cell-2.6.git cell-next
Arnd <><
--
^ permalink raw reply
* [patch 1/9] powerpc/cell/edac: log a syndrome code in case of correctable error
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Maxim Shchetynin
In-Reply-To: <20080715195139.316677337@arndb.de>
From: Maxim Shchetynin <maxim@de.ibm.com>
If correctable error occurs the syndrome code was logged as 0. This patch
lets EDAC to log a correct syndrome code to make problem investigation
easier.
Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/edac/cell_edac.c | 5 +++--
1 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index b54112f..0e024fe 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -33,7 +33,7 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
{
struct cell_edac_priv *priv = mci->pvt_info;
struct csrow_info *csrow = &mci->csrows[0];
- unsigned long address, pfn, offset;
+ unsigned long address, pfn, offset, syndrome;
dev_dbg(mci->dev, "ECC CE err on node %d, channel %d, ar = 0x%016lx\n",
priv->node, chan, ar);
@@ -44,10 +44,11 @@ static void cell_edac_count_ce(struct mem_ctl_info *mci, int chan, u64 ar)
address = (address << 1) | chan;
pfn = address >> PAGE_SHIFT;
offset = address & ~PAGE_MASK;
+ syndrome = (ar & 0x000000001fe00000ul) >> 21;
/* TODO: Decoding of the error addresss */
edac_mc_handle_ce(mci, csrow->first_page + pfn, offset,
- 0, 0, chan, "");
+ syndrome, 0, chan, "");
}
static void cell_edac_count_ue(struct mem_ctl_info *mci, int chan, u64 ar)
--
1.5.4.3
--
^ permalink raw reply related
* [patch 2/9] powerpc/axonram: use only one block device major number
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Maxim Shchetynin
In-Reply-To: <20080715195139.316677337@arndb.de>
From: Maxim Shchetynin <maxim@de.ibm.com>
Axonram module registers one block device for each DDR2 DIMM found
on a system. This means that each DDR2 DIMM becomes its own block device
major number. This patch lets axonram module to register the only one
block device for all DDR2 DIMMs which also spares kernel resources.
Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/sysdev/axonram.c | 23 +++++++++++++++--------
1 files changed, 15 insertions(+), 8 deletions(-)
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 7f59188..9b639ed 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -57,6 +57,8 @@
#define AXON_RAM_SECTOR_SIZE 1 << AXON_RAM_SECTOR_SHIFT
#define AXON_RAM_IRQ_FLAGS IRQF_SHARED | IRQF_TRIGGER_RISING
+static int azfs_major, azfs_minor;
+
struct axon_ram_bank {
struct of_device *device;
struct gendisk *disk;
@@ -227,19 +229,14 @@ axon_ram_probe(struct of_device *device, const struct of_device_id *device_id)
goto failed;
}
- bank->disk->first_minor = 0;
+ bank->disk->major = azfs_major;
+ bank->disk->first_minor = azfs_minor;
bank->disk->fops = &axon_ram_devops;
bank->disk->private_data = bank;
bank->disk->driverfs_dev = &device->dev;
sprintf(bank->disk->disk_name, "%s%d",
AXON_RAM_DEVICE_NAME, axon_ram_bank_id);
- bank->disk->major = register_blkdev(0, bank->disk->disk_name);
- if (bank->disk->major < 0) {
- dev_err(&device->dev, "Cannot register block device\n");
- rc = -EFAULT;
- goto failed;
- }
bank->disk->queue = blk_alloc_queue(GFP_KERNEL);
if (bank->disk->queue == NULL) {
@@ -276,6 +273,8 @@ axon_ram_probe(struct of_device *device, const struct of_device_id *device_id)
goto failed;
}
+ azfs_minor += bank->disk->minors;
+
return 0;
failed:
@@ -310,7 +309,6 @@ axon_ram_remove(struct of_device *device)
device_remove_file(&device->dev, &dev_attr_ecc);
free_irq(bank->irq_id, device);
- unregister_blkdev(bank->disk->major, bank->disk->disk_name);
del_gendisk(bank->disk);
iounmap((void __iomem *) bank->io_addr);
kfree(bank);
@@ -341,6 +339,14 @@ static struct of_platform_driver axon_ram_driver = {
static int __init
axon_ram_init(void)
{
+ azfs_major = register_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
+ if (azfs_major < 0) {
+ printk(KERN_ERR "%s cannot become block device major number\n",
+ AXON_RAM_MODULE_NAME);
+ return -EFAULT;
+ }
+ azfs_minor = 0;
+
return of_register_platform_driver(&axon_ram_driver);
}
@@ -351,6 +357,7 @@ static void __exit
axon_ram_exit(void)
{
of_unregister_platform_driver(&axon_ram_driver);
+ unregister_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
}
module_init(axon_ram_init);
--
1.5.4.3
--
^ permalink raw reply related
* [patch 3/9] powerpc/axonram: enable partitioning of the Axons DDR2 DIMMs
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Maxim Shchetynin
In-Reply-To: <20080715195139.316677337@arndb.de>
From: Maxim Shchetynin <maxim@de.ibm.com>
DDR2 memory DIMMs on the Axon could be accessed only as one partition
when using file system drivers which are using the direct_access() method.
This patch enables for such file system drivers to access Axon's DDR2 memory
even if it is splitted in several partitions.
Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/sysdev/axonram.c | 5 ++++-
1 files changed, 4 insertions(+), 1 deletions(-)
diff --git a/arch/powerpc/sysdev/axonram.c b/arch/powerpc/sysdev/axonram.c
index 9b639ed..9e105cb 100644
--- a/arch/powerpc/sysdev/axonram.c
+++ b/arch/powerpc/sysdev/axonram.c
@@ -150,7 +150,10 @@ axon_ram_direct_access(struct block_device *device, sector_t sector,
struct axon_ram_bank *bank = device->bd_disk->private_data;
loff_t offset;
- offset = sector << AXON_RAM_SECTOR_SHIFT;
+ offset = sector;
+ if (device->bd_part != NULL)
+ offset += device->bd_part->start_sect;
+ offset <<= AXON_RAM_SECTOR_SHIFT;
if (offset >= bank->size) {
dev_err(&bank->device->dev, "Access outside of address space\n");
return -ERANGE;
--
1.5.4.3
--
^ permalink raw reply related
* [patch 4/9] powerpc/cell/cpufreq: add spu aware cpufreq governor
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Christian Krafft, Jeremy Kerr, Dave Jones
In-Reply-To: <20080715195139.316677337@arndb.de>
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain, Size: 7043 bytes --]
From: Christian Krafft <krafft@de.ibm.com>
This patch adds a cpufreq governor that takes the number of running spus
into account. It's very similar to the ondemand governor, but not as complex.
Instead of hacking spu load into the ondemand governor it might be easier to
have cpufreq accepting multiple governors per cpu in future.
Don't know if this is the right way, but it would keep the governors simple.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Acked-by: Dave Jones <davej@redhat.com>
Cc: Jeremy Kerr <jk@ozlabs.org>
---
arch/powerpc/platforms/cell/Kconfig | 9 +
arch/powerpc/platforms/cell/Makefile | 1 +
arch/powerpc/platforms/cell/cpufreq_spudemand.c | 184 +++++++++++++++++++++++
3 files changed, 194 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/cell/cpufreq_spudemand.c
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 3959fcf..6ee571f 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -107,6 +107,15 @@ config CBE_CPUFREQ_PMI
processor will not only be able to run at lower speed,
but also at lower core voltage.
+config CBE_CPUFREQ_SPU_GOVERNOR
+ tristate "CBE frequency scaling based on SPU usage"
+ depends on SPU_FS && CPU_FREQ
+ default m
+ help
+ This governor checks for spu usage to adjust the cpu frequency.
+ If no spu is running on a given cpu, that cpu will be throttled to
+ the minimal possible frequency.
+
endmenu
config OPROFILE_CELL
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index c2a7e4e..7fcf09b 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -8,6 +8,7 @@ obj-$(CONFIG_CBE_THERM) += cbe_thermal.o
obj-$(CONFIG_CBE_CPUFREQ_PMI) += cbe_cpufreq_pmi.o
obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o
cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o
+obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
diff --git a/arch/powerpc/platforms/cell/cpufreq_spudemand.c b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
new file mode 100644
index 0000000..a3c6c01
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cpufreq_spudemand.c
@@ -0,0 +1,184 @@
+/*
+ * spu aware cpufreq governor for the cell processor
+ *
+ * © Copyright IBM Corporation 2006-2008
+ *
+ * Author: Christian Krafft <krafft@de.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/cpufreq.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/workqueue.h>
+#include <asm/atomic.h>
+#include <asm/machdep.h>
+#include <asm/spu.h>
+
+#define POLL_TIME 100000 /* in µs */
+#define EXP 753 /* exp(-1) in fixed-point */
+
+struct spu_gov_info_struct {
+ unsigned long busy_spus; /* fixed-point */
+ struct cpufreq_policy *policy;
+ struct delayed_work work;
+ unsigned int poll_int; /* µs */
+};
+static DEFINE_PER_CPU(struct spu_gov_info_struct, spu_gov_info);
+
+static struct workqueue_struct *kspugov_wq;
+
+static int calc_freq(struct spu_gov_info_struct *info)
+{
+ int cpu;
+ int busy_spus;
+
+ cpu = info->policy->cpu;
+ busy_spus = atomic_read(&cbe_spu_info[cpu_to_node(cpu)].busy_spus);
+
+ CALC_LOAD(info->busy_spus, EXP, busy_spus * FIXED_1);
+ pr_debug("cpu %d: busy_spus=%d, info->busy_spus=%ld\n",
+ cpu, busy_spus, info->busy_spus);
+
+ return info->policy->max * info->busy_spus / FIXED_1;
+}
+
+static void spu_gov_work(struct work_struct *work)
+{
+ struct spu_gov_info_struct *info;
+ int delay;
+ unsigned long target_freq;
+
+ info = container_of(work, struct spu_gov_info_struct, work.work);
+
+ /* after cancel_delayed_work_sync we unset info->policy */
+ BUG_ON(info->policy == NULL);
+
+ target_freq = calc_freq(info);
+ __cpufreq_driver_target(info->policy, target_freq, CPUFREQ_RELATION_H);
+
+ delay = usecs_to_jiffies(info->poll_int);
+ queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+}
+
+static void spu_gov_init_work(struct spu_gov_info_struct *info)
+{
+ int delay = usecs_to_jiffies(info->poll_int);
+ INIT_DELAYED_WORK_DEFERRABLE(&info->work, spu_gov_work);
+ queue_delayed_work_on(info->policy->cpu, kspugov_wq, &info->work, delay);
+}
+
+static void spu_gov_cancel_work(struct spu_gov_info_struct *info)
+{
+ cancel_delayed_work_sync(&info->work);
+}
+
+static int spu_gov_govern(struct cpufreq_policy *policy, unsigned int event)
+{
+ unsigned int cpu = policy->cpu;
+ struct spu_gov_info_struct *info, *affected_info;
+ int i;
+ int ret = 0;
+
+ info = &per_cpu(spu_gov_info, cpu);
+
+ switch (event) {
+ case CPUFREQ_GOV_START:
+ if (!cpu_online(cpu)) {
+ printk(KERN_ERR "cpu %d is not online\n", cpu);
+ ret = -EINVAL;
+ break;
+ }
+
+ if (!policy->cur) {
+ printk(KERN_ERR "no cpu specified in policy\n");
+ ret = -EINVAL;
+ break;
+ }
+
+ /* initialize spu_gov_info for all affected cpus */
+ for_each_cpu_mask(i, policy->cpus) {
+ affected_info = &per_cpu(spu_gov_info, i);
+ affected_info->policy = policy;
+ }
+
+ info->poll_int = POLL_TIME;
+
+ /* setup timer */
+ spu_gov_init_work(info);
+
+ break;
+
+ case CPUFREQ_GOV_STOP:
+ /* cancel timer */
+ spu_gov_cancel_work(info);
+
+ /* clean spu_gov_info for all affected cpus */
+ for_each_cpu_mask (i, policy->cpus) {
+ info = &per_cpu(spu_gov_info, i);
+ info->policy = NULL;
+ }
+
+ break;
+ }
+
+ return ret;
+}
+
+static struct cpufreq_governor spu_governor = {
+ .name = "spudemand",
+ .governor = spu_gov_govern,
+ .owner = THIS_MODULE,
+};
+
+/*
+ * module init and destoy
+ */
+
+static int __init spu_gov_init(void)
+{
+ int ret;
+
+ kspugov_wq = create_workqueue("kspugov");
+ if (!kspugov_wq) {
+ printk(KERN_ERR "creation of kspugov failed\n");
+ ret = -EFAULT;
+ goto out;
+ }
+
+ ret = cpufreq_register_governor(&spu_governor);
+ if (ret) {
+ printk(KERN_ERR "registration of governor failed\n");
+ destroy_workqueue(kspugov_wq);
+ goto out;
+ }
+out:
+ return ret;
+}
+
+static void __exit spu_gov_exit(void)
+{
+ cpufreq_unregister_governor(&spu_governor);
+ destroy_workqueue(kspugov_wq);
+}
+
+
+module_init(spu_gov_init);
+module_exit(spu_gov_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
+
--
1.5.4.3
--
^ permalink raw reply related
* [patch 5/9] powerpc/cell: cleanup sysreset_hack for IBM cell blades
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Christian Krafft
In-Reply-To: <20080715195139.316677337@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch adds a config option for the sysreset_hack used for
IBM Cell blades. The code is moves from pervasive.c into ras.c and
gets it's own init method.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/platforms/cell/Kconfig | 8 +++++
arch/powerpc/platforms/cell/pervasive.c | 27 +-----------------
arch/powerpc/platforms/cell/pervasive.h | 9 ++++++
arch/powerpc/platforms/cell/ras.c | 46 +++++++++++++++++++++++++++++++
4 files changed, 64 insertions(+), 26 deletions(-)
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 6ee571f..2d1957b 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -83,6 +83,14 @@ config CBE_RAS
depends on PPC_CELL_NATIVE
default y
+config PPC_IBM_CELL_RESETBUTTON
+ bool "IBM Cell Blade Pinhole reset button"
+ depends on CBE_RAS && PPC_IBM_CELL_BLADE
+ default y
+ help
+ Support Pinhole Resetbutton on IBM Cell blades.
+ This adds a method to trigger system reset via front panel pinhole button.
+
config CBE_THERM
tristate "CBE thermal support"
default m
diff --git a/arch/powerpc/platforms/cell/pervasive.c b/arch/powerpc/platforms/cell/pervasive.c
index 8a3631c..efdacc8 100644
--- a/arch/powerpc/platforms/cell/pervasive.c
+++ b/arch/powerpc/platforms/cell/pervasive.c
@@ -38,8 +38,6 @@
#include "pervasive.h"
-static int sysreset_hack;
-
static void cbe_power_save(void)
{
unsigned long ctrl, thread_switch_control;
@@ -87,9 +85,6 @@ static void cbe_power_save(void)
static int cbe_system_reset_exception(struct pt_regs *regs)
{
- int cpu;
- struct cbe_pmd_regs __iomem *pmd;
-
switch (regs->msr & SRR1_WAKEMASK) {
case SRR1_WAKEEE:
do_IRQ(regs);
@@ -98,19 +93,7 @@ static int cbe_system_reset_exception(struct pt_regs *regs)
timer_interrupt(regs);
break;
case SRR1_WAKEMT:
- /*
- * The BMC can inject user triggered system reset exceptions,
- * but cannot set the system reset reason in srr1,
- * so check an extra register here.
- */
- if (sysreset_hack && (cpu = smp_processor_id()) == 0) {
- pmd = cbe_get_cpu_pmd_regs(cpu);
- if (in_be64(&pmd->ras_esc_0) & 0xffff) {
- out_be64(&pmd->ras_esc_0, 0);
- return 0;
- }
- }
- break;
+ return cbe_sysreset_hack();
#ifdef CONFIG_CBE_RAS
case SRR1_WAKESYSERR:
cbe_system_error_exception(regs);
@@ -134,8 +117,6 @@ void __init cbe_pervasive_init(void)
if (!cpu_has_feature(CPU_FTR_PAUSE_ZERO))
return;
- sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
-
for_each_possible_cpu(cpu) {
struct cbe_pmd_regs __iomem *regs = cbe_get_cpu_pmd_regs(cpu);
if (!regs)
@@ -144,12 +125,6 @@ void __init cbe_pervasive_init(void)
/* Enable Pause(0) control bit */
out_be64(®s->pmcr, in_be64(®s->pmcr) |
CBE_PMD_PAUSE_ZERO_CONTROL);
-
- /* Enable JTAG system-reset hack */
- if (sysreset_hack)
- out_be32(®s->fir_mode_reg,
- in_be32(®s->fir_mode_reg) |
- CBE_PMD_FIR_MODE_M8);
}
ppc_md.power_save = cbe_power_save;
diff --git a/arch/powerpc/platforms/cell/pervasive.h b/arch/powerpc/platforms/cell/pervasive.h
index 7b50947..fd4d7b7 100644
--- a/arch/powerpc/platforms/cell/pervasive.h
+++ b/arch/powerpc/platforms/cell/pervasive.h
@@ -30,4 +30,13 @@ extern void cbe_system_error_exception(struct pt_regs *regs);
extern void cbe_maintenance_exception(struct pt_regs *regs);
extern void cbe_thermal_exception(struct pt_regs *regs);
+#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
+extern int cbe_sysreset_hack(void);
+#else
+static inline int cbe_sysreset_hack(void)
+{
+ return 1;
+}
+#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
+
#endif
diff --git a/arch/powerpc/platforms/cell/ras.c b/arch/powerpc/platforms/cell/ras.c
index 505f9b9..2a14b05 100644
--- a/arch/powerpc/platforms/cell/ras.c
+++ b/arch/powerpc/platforms/cell/ras.c
@@ -236,6 +236,52 @@ static struct notifier_block cbe_ptcal_reboot_notifier = {
.notifier_call = cbe_ptcal_notify_reboot
};
+#ifdef CONFIG_PPC_IBM_CELL_RESETBUTTON
+static int sysreset_hack;
+
+static int __init cbe_sysreset_init(void)
+{
+ struct cbe_pmd_regs __iomem *regs;
+
+ sysreset_hack = machine_is_compatible("IBM,CBPLUS-1.0");
+ if (!sysreset_hack)
+ return 0;
+
+ regs = cbe_get_cpu_pmd_regs(0);
+ if (!regs)
+ return 0;
+
+ /* Enable JTAG system-reset hack */
+ out_be32(®s->fir_mode_reg,
+ in_be32(®s->fir_mode_reg) |
+ CBE_PMD_FIR_MODE_M8);
+
+ return 0;
+}
+device_initcall(cbe_sysreset_init);
+
+int cbe_sysreset_hack(void)
+{
+ struct cbe_pmd_regs __iomem *regs;
+
+ /*
+ * The BMC can inject user triggered system reset exceptions,
+ * but cannot set the system reset reason in srr1,
+ * so check an extra register here.
+ */
+ if (sysreset_hack && (smp_processor_id() == 0)) {
+ regs = cbe_get_cpu_pmd_regs(0);
+ if (!regs)
+ return 0;
+ if (in_be64(®s->ras_esc_0) & 0x0000ffff) {
+ out_be64(®s->ras_esc_0, 0);
+ return 0;
+ }
+ }
+ return 1;
+}
+#endif /* CONFIG_PPC_IBM_CELL_RESETBUTTON */
+
int __init cbe_ptcal_init(void)
{
int ret;
--
1.5.4.3
--
^ permalink raw reply related
* [patch 6/9] powerpc/cell: add support for power button of future IBM cell blades
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Christian Krafft
In-Reply-To: <20080715195139.316677337@arndb.de>
From: Christian Krafft <krafft@de.ibm.com>
This patch adds support for the power button on future IBM cell blades.
It actually doesn't shut down the machine. Instead it exposes an
input device /dev/input/event0 to userspace which sends KEY_POWER
if power button has been pressed.
haldaemon actually recognizes the button, so a plattform independent acpid
replacement should handle it correctly.
Signed-off-by: Christian Krafft <krafft@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
arch/powerpc/platforms/cell/Kconfig | 8 ++
arch/powerpc/platforms/cell/Makefile | 2 +
arch/powerpc/platforms/cell/cbe_powerbutton.c | 117 +++++++++++++++++++++++++
include/asm-powerpc/pmi.h | 1 +
4 files changed, 128 insertions(+), 0 deletions(-)
create mode 100644 arch/powerpc/platforms/cell/cbe_powerbutton.c
diff --git a/arch/powerpc/platforms/cell/Kconfig b/arch/powerpc/platforms/cell/Kconfig
index 2d1957b..c14d7d8 100644
--- a/arch/powerpc/platforms/cell/Kconfig
+++ b/arch/powerpc/platforms/cell/Kconfig
@@ -91,6 +91,14 @@ config PPC_IBM_CELL_RESETBUTTON
Support Pinhole Resetbutton on IBM Cell blades.
This adds a method to trigger system reset via front panel pinhole button.
+config PPC_IBM_CELL_POWERBUTTON
+ tristate "IBM Cell Blade power button"
+ depends on PPC_IBM_CELL_BLADE && PPC_PMI && INPUT_EVDEV
+ default y
+ help
+ Support Powerbutton on IBM Cell blades.
+ This will enable the powerbutton as an input device.
+
config CBE_THERM
tristate "CBE thermal support"
default m
diff --git a/arch/powerpc/platforms/cell/Makefile b/arch/powerpc/platforms/cell/Makefile
index 7fcf09b..7fd8308 100644
--- a/arch/powerpc/platforms/cell/Makefile
+++ b/arch/powerpc/platforms/cell/Makefile
@@ -10,6 +10,8 @@ obj-$(CONFIG_CBE_CPUFREQ) += cbe-cpufreq.o
cbe-cpufreq-y += cbe_cpufreq_pervasive.o cbe_cpufreq.o
obj-$(CONFIG_CBE_CPUFREQ_SPU_GOVERNOR) += cpufreq_spudemand.o
+obj-$(CONFIG_PPC_IBM_CELL_POWERBUTTON) += cbe_powerbutton.o
+
ifeq ($(CONFIG_SMP),y)
obj-$(CONFIG_PPC_CELL_NATIVE) += smp.o
endif
diff --git a/arch/powerpc/platforms/cell/cbe_powerbutton.c b/arch/powerpc/platforms/cell/cbe_powerbutton.c
new file mode 100644
index 0000000..dcddaa5
--- /dev/null
+++ b/arch/powerpc/platforms/cell/cbe_powerbutton.c
@@ -0,0 +1,117 @@
+/*
+ * driver for powerbutton on IBM cell blades
+ *
+ * (C) Copyright IBM Corp. 2005-2008
+ *
+ * Author: Christian Krafft <krafft@de.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/input.h>
+#include <linux/platform_device.h>
+#include <asm/pmi.h>
+#include <asm/prom.h>
+
+static struct input_dev *button_dev;
+static struct platform_device *button_pdev;
+
+static void cbe_powerbutton_handle_pmi(pmi_message_t pmi_msg)
+{
+ BUG_ON(pmi_msg.type != PMI_TYPE_POWER_BUTTON);
+
+ input_report_key(button_dev, KEY_POWER, 1);
+ input_sync(button_dev);
+ input_report_key(button_dev, KEY_POWER, 0);
+ input_sync(button_dev);
+}
+
+static struct pmi_handler cbe_pmi_handler = {
+ .type = PMI_TYPE_POWER_BUTTON,
+ .handle_pmi_message = cbe_powerbutton_handle_pmi,
+};
+
+static int __init cbe_powerbutton_init(void)
+{
+ int ret = 0;
+ struct input_dev *dev;
+
+ if (!machine_is_compatible("IBM,CBPLUS-1.0")) {
+ printk(KERN_ERR "%s: Not a cell blade.\n", __func__);
+ ret = -ENODEV;
+ goto out;
+ }
+
+ dev = input_allocate_device();
+ if (!dev) {
+ ret = -ENOMEM;
+ printk(KERN_ERR "%s: Not enough memory.\n", __func__);
+ goto out;
+ }
+
+ set_bit(EV_KEY, dev->evbit);
+ set_bit(KEY_POWER, dev->keybit);
+
+ dev->name = "Power Button";
+ dev->id.bustype = BUS_HOST;
+
+ /* this makes the button look like an acpi power button
+ * no clue whether anyone relies on that though */
+ dev->id.product = 0x02;
+ dev->phys = "LNXPWRBN/button/input0";
+
+ button_pdev = platform_device_register_simple("power_button", 0, NULL, 0);
+ if (IS_ERR(button_pdev)) {
+ ret = PTR_ERR(button_pdev);
+ goto out_free_input;
+ }
+
+ dev->dev.parent = &button_pdev->dev;
+ ret = input_register_device(dev);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed to register device\n", __func__);
+ goto out_free_pdev;
+ }
+
+ button_dev = dev;
+
+ ret = pmi_register_handler(&cbe_pmi_handler);
+ if (ret) {
+ printk(KERN_ERR "%s: Failed to register with pmi.\n", __func__);
+ goto out_free_pdev;
+ }
+
+ goto out;
+
+out_free_pdev:
+ platform_device_unregister(button_pdev);
+out_free_input:
+ input_free_device(dev);
+out:
+ return ret;
+}
+
+static void __exit cbe_powerbutton_exit(void)
+{
+ pmi_unregister_handler(&cbe_pmi_handler);
+ platform_device_unregister(button_pdev);
+ input_free_device(button_dev);
+}
+
+module_init(cbe_powerbutton_init);
+module_exit(cbe_powerbutton_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Christian Krafft <krafft@de.ibm.com>");
diff --git a/include/asm-powerpc/pmi.h b/include/asm-powerpc/pmi.h
index e1dc090..b4e91fb 100644
--- a/include/asm-powerpc/pmi.h
+++ b/include/asm-powerpc/pmi.h
@@ -30,6 +30,7 @@
#ifdef __KERNEL__
#define PMI_TYPE_FREQ_CHANGE 0x01
+#define PMI_TYPE_POWER_BUTTON 0x02
#define PMI_READ_TYPE 0
#define PMI_READ_DATA0 1
#define PMI_READ_DATA1 2
--
1.5.4.3
--
^ permalink raw reply related
* [patch 7/9] azfs: initial submit of azfs, a non-buffered filesystem
From: arnd @ 2008-07-15 19:51 UTC (permalink / raw)
To: benh, cbe-oss-dev, linuxppc-dev; +Cc: Maxim Shchetynin
In-Reply-To: <20080715195139.316677337@arndb.de>
From: Maxim Shchetynin <maxim@linux.vnet.ibm.com>
AZFS is a file system which keeps all files on memory mapped random
access storage. It was designed to work on the axonram device driver
for IBM QS2x blade servers, but can operate on any block device
that exports a direct_access method.
Signed-off-by: Maxim Shchetynin <maxim@de.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
Documentation/filesystems/azfs.txt | 22 +
arch/powerpc/configs/cell_defconfig | 1 +
fs/Kconfig | 15 +
fs/Makefile | 1 +
fs/azfs/Makefile | 7 +
fs/azfs/inode.c | 1184 +++++++++++++++++++++++++++++++++++
6 files changed, 1230 insertions(+), 0 deletions(-)
create mode 100644 Documentation/filesystems/azfs.txt
create mode 100644 fs/azfs/Makefile
create mode 100644 fs/azfs/inode.c
diff --git a/Documentation/filesystems/azfs.txt b/Documentation/filesystems/azfs.txt
new file mode 100644
index 0000000..c4bf659
--- /dev/null
+++ b/Documentation/filesystems/azfs.txt
@@ -0,0 +1,22 @@
+AZFS is a file system which keeps all files on memory backed random
+access storage. It was designed to work on the axonram device driver
+for IBM QS2x blade servers, but can operate on any block device
+that exports a direct_access method.
+
+Everything in AZFS is temporary in the sense that all the data stored
+therein is lost when you switch off or reboot a system. If you unmount
+an AZFS instance, all the data will be kept on device as long your system
+is not shut down or rebooted. You can later mount AZFS on from device again
+to get access to your files.
+
+AZFS uses a block device only for data but not for file information.
+All inodes (file and directory information) is kept in RAM.
+
+When you mount AZFS you are able to specify a file system block size with
+'-o bs=<size in bytes>' option. There are no software limitations for
+a block size but you would not be able to mmap files on AZFS if block size
+is less than a system page size. If no '-o bs' option is specified on mount
+a block size of the used block device is used as a default block size for AZFS.
+
+Other available mount options for AZFS are '-o uid=<id>' and '-o gid=<id>',
+which allow you to set the owner and group of the root of the file system.
diff --git a/arch/powerpc/configs/cell_defconfig b/arch/powerpc/configs/cell_defconfig
index c420e47..235a0c8 100644
--- a/arch/powerpc/configs/cell_defconfig
+++ b/arch/powerpc/configs/cell_defconfig
@@ -240,6 +240,7 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
# CPU Frequency drivers
#
CONFIG_AXON_RAM=m
+CONFIG_AZ_FS=m
# CONFIG_FSL_ULI1575 is not set
#
diff --git a/fs/Kconfig b/fs/Kconfig
index 2694648..2d4e42b 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -1017,6 +1017,21 @@ config HUGETLBFS
config HUGETLB_PAGE
def_bool HUGETLBFS
+config AZ_FS
+ tristate "AZFS filesystem support"
+ help
+ azfs is a file system for I/O attached memory backing. It requires
+ a block device with direct_access capability, e.g. axonram.
+ Mounting such device with azfs gives memory mapped access to the
+ underlying memory to user space.
+
+ Read <file:Documentation/filesystems/azfs.txt> for details.
+
+ To compile this file system support as a module, choose M here: the
+ module will be called azfs.
+
+ If unsure, say N.
+
config CONFIGFS_FS
tristate "Userspace-driven configuration filesystem"
depends on SYSFS
diff --git a/fs/Makefile b/fs/Makefile
index 1e7a11b..20e3253 100644
--- a/fs/Makefile
+++ b/fs/Makefile
@@ -119,3 +119,4 @@ obj-$(CONFIG_HPPFS) += hppfs/
obj-$(CONFIG_DEBUG_FS) += debugfs/
obj-$(CONFIG_OCFS2_FS) += ocfs2/
obj-$(CONFIG_GFS2_FS) += gfs2/
+obj-$(CONFIG_AZ_FS) += azfs/
diff --git a/fs/azfs/Makefile b/fs/azfs/Makefile
new file mode 100644
index 0000000..ff04d41
--- /dev/null
+++ b/fs/azfs/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for azfs routines
+#
+
+obj-$(CONFIG_AZ_FS) += azfs.o
+
+azfs-y := inode.o
diff --git a/fs/azfs/inode.c b/fs/azfs/inode.c
new file mode 100644
index 0000000..00dc2af
--- /dev/null
+++ b/fs/azfs/inode.c
@@ -0,0 +1,1184 @@
+/*
+ * (C) Copyright IBM Deutschland Entwicklung GmbH 2007
+ *
+ * Author: Maxim Shchetynin <maxim@de.ibm.com>
+ *
+ * Non-buffered filesystem driver.
+ * It registers a filesystem which may be used for all kind of block devices
+ * which have a direct_access() method in block_device_operations.
+ *
+ * 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/backing-dev.h>
+#include <linux/blkdev.h>
+#include <linux/cache.h>
+#include <linux/dcache.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/genhd.h>
+#include <linux/kernel.h>
+#include <linux/limits.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/mount.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/mutex.h>
+#include <linux/namei.h>
+#include <linux/pagemap.h>
+#include <linux/parser.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/stat.h>
+#include <linux/statfs.h>
+#include <linux/string.h>
+#include <linux/time.h>
+#include <linux/types.h>
+#include <linux/aio.h>
+#include <linux/uio.h>
+#include <asm/bug.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/string.h>
+
+#define AZFS_FILESYSTEM_NAME "azfs"
+#define AZFS_FILESYSTEM_FLAGS FS_REQUIRES_DEV
+
+#define AZFS_SUPERBLOCK_MAGIC 0xABBA1972
+#define AZFS_SUPERBLOCK_FLAGS MS_SYNCHRONOUS | \
+ MS_DIRSYNC | \
+ MS_ACTIVE
+
+#define AZFS_BDI_CAPABILITIES BDI_CAP_NO_ACCT_DIRTY | \
+ BDI_CAP_NO_WRITEBACK | \
+ BDI_CAP_MAP_COPY | \
+ BDI_CAP_MAP_DIRECT | \
+ BDI_CAP_VMFLAGS
+
+#define AZFS_CACHE_FLAGS SLAB_HWCACHE_ALIGN | \
+ SLAB_RECLAIM_ACCOUNT | \
+ SLAB_MEM_SPREAD
+
+struct azfs_super {
+ struct list_head list;
+ unsigned long media_size;
+ unsigned long block_size;
+ unsigned short block_shift;
+ unsigned long sector_size;
+ unsigned short sector_shift;
+ uid_t uid;
+ gid_t gid;
+ unsigned long ph_addr;
+ unsigned long io_addr;
+ struct block_device *blkdev;
+ struct dentry *root;
+ struct list_head block_list;
+ rwlock_t lock;
+};
+
+struct azfs_super_list {
+ struct list_head head;
+ spinlock_t lock;
+};
+
+struct azfs_block {
+ struct list_head list;
+ unsigned long id;
+ unsigned long count;
+};
+
+struct azfs_znode {
+ struct list_head block_list;
+ rwlock_t lock;
+ loff_t size;
+ struct inode vfs_inode;
+};
+
+static struct azfs_super_list super_list;
+static struct kmem_cache *azfs_znode_cache __read_mostly = NULL;
+static struct kmem_cache *azfs_block_cache __read_mostly = NULL;
+
+#define I2S(inode) \
+ inode->i_sb->s_fs_info
+#define I2Z(inode) \
+ container_of(inode, struct azfs_znode, vfs_inode)
+
+#define for_each_block(block, block_list) \
+ list_for_each_entry(block, block_list, list)
+#define for_each_block_reverse(block, block_list) \
+ list_for_each_entry_reverse(block, block_list, list)
+#define for_each_block_safe(block, temp, block_list) \
+ list_for_each_entry_safe(block, temp, block_list, list)
+#define for_each_block_safe_reverse(block, temp, block_list) \
+ list_for_each_entry_safe_reverse(block, temp, block_list, list)
+
+/**
+ * azfs_block_init - create and initialise a new block in a list
+ * @block_list: destination list
+ * @id: block id
+ * @count: size of a block
+ */
+static inline struct azfs_block*
+azfs_block_init(struct list_head *block_list,
+ unsigned long id, unsigned long count)
+{
+ struct azfs_block *block;
+
+ block = kmem_cache_alloc(azfs_block_cache, GFP_KERNEL);
+ if (!block)
+ return NULL;
+
+ block->id = id;
+ block->count = count;
+
+ INIT_LIST_HEAD(&block->list);
+ list_add_tail(&block->list, block_list);
+
+ return block;
+}
+
+/**
+ * azfs_block_free - remove block from a list and free it back in cache
+ * @block: block to be removed
+ */
+static inline void
+azfs_block_free(struct azfs_block *block)
+{
+ list_del(&block->list);
+ kmem_cache_free(azfs_block_cache, block);
+}
+
+/**
+ * azfs_block_move - move block to another list
+ * @block: block to be moved
+ * @block_list: destination list
+ */
+static inline void
+azfs_block_move(struct azfs_block *block, struct list_head *block_list)
+{
+ list_move_tail(&block->list, block_list);
+}
+
+/**
+ * azfs_block_find - get a block id of a part of a file
+ * @inode: inode
+ * @from: offset for read/write operation
+ * @size: pointer to a value of the amount of data to be read/written
+ */
+static unsigned long
+azfs_block_find(struct inode *inode, unsigned long from, unsigned long *size)
+{
+ struct azfs_super *super;
+ struct azfs_znode *znode;
+ struct azfs_block *block;
+ unsigned long block_id, west, east;
+
+ super = I2S(inode);
+ znode = I2Z(inode);
+
+ read_lock(&znode->lock);
+
+ while (from + *size > znode->size) {
+ read_unlock(&znode->lock);
+ i_size_write(inode, from + *size);
+ inode->i_op->truncate(inode);
+ read_lock(&znode->lock);
+ }
+
+ if (list_empty(&znode->block_list)) {
+ read_unlock(&znode->lock);
+ *size = 0;
+ return 0;
+ }
+
+ block_id = from >> super->block_shift;
+
+ for_each_block(block, &znode->block_list) {
+ if (block->count > block_id)
+ break;
+ block_id -= block->count;
+ }
+
+ west = from % super->block_size;
+ east = ((block->count - block_id) << super->block_shift) - west;
+
+ if (*size > east)
+ *size = east;
+
+ block_id = ((block->id + block_id) << super->block_shift) + west;
+
+ read_unlock(&znode->lock);
+
+ return block_id;
+}
+
+static struct inode*
+azfs_new_inode(struct super_block *, struct inode *, int, dev_t);
+
+/**
+ * azfs_mknod - mknod() method for inode_operations
+ * @dir, @dentry, @mode, @dev: see inode_operations methods
+ */
+static int
+azfs_mknod(struct inode *dir, struct dentry *dentry, int mode, dev_t dev)
+{
+ struct inode *inode;
+
+ inode = azfs_new_inode(dir->i_sb, dir, mode, dev);
+ if (!inode)
+ return -ENOSPC;
+
+ if (S_ISREG(mode))
+ I2Z(inode)->size = 0;
+
+ dget(dentry);
+ d_instantiate(dentry, inode);
+
+ return 0;
+}
+
+/**
+ * azfs_create - create() method for inode_operations
+ * @dir, @dentry, @mode, @nd: see inode_operations methods
+ */
+static int
+azfs_create(struct inode *dir, struct dentry *dentry, int mode,
+ struct nameidata *nd)
+{
+ return azfs_mknod(dir, dentry, mode | S_IFREG, 0);
+}
+
+/**
+ * azfs_mkdir - mkdir() method for inode_operations
+ * @dir, @dentry, @mode: see inode_operations methods
+ */
+static int
+azfs_mkdir(struct inode *dir, struct dentry *dentry, int mode)
+{
+ int rc;
+
+ rc = azfs_mknod(dir, dentry, mode | S_IFDIR, 0);
+ if (!rc)
+ inc_nlink(dir);
+
+ return rc;
+}
+
+/**
+ * azfs_symlink - symlink() method for inode_operations
+ * @dir, @dentry, @name: see inode_operations methods
+ */
+static int
+azfs_symlink(struct inode *dir, struct dentry *dentry, const char *name)
+{
+ struct inode *inode;
+ int rc;
+
+ inode = azfs_new_inode(dir->i_sb, dir, S_IFLNK | S_IRWXUGO, 0);
+ if (!inode)
+ return -ENOSPC;
+
+ rc = page_symlink(inode, name, strlen(name) + 1);
+ if (rc) {
+ iput(inode);
+ return rc;
+ }
+
+ dget(dentry);
+ d_instantiate(dentry, inode);
+
+ return 0;
+}
+
+/**
+ * azfs_aio_read - aio_read() method for file_operations
+ * @iocb, @iov, @nr_segs, @pos: see file_operations methods
+ */
+static ssize_t
+azfs_aio_read(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct azfs_super *super;
+ struct inode *inode;
+ void *target;
+ unsigned long pin;
+ unsigned long size, todo, step;
+ ssize_t rc;
+
+ inode = iocb->ki_filp->f_mapping->host;
+ super = I2S(inode);
+
+ mutex_lock(&inode->i_mutex);
+
+ if (pos >= i_size_read(inode)) {
+ rc = 0;
+ goto out;
+ }
+
+ target = iov->iov_base;
+ todo = min((loff_t) iov->iov_len, i_size_read(inode) - pos);
+
+ for (step = todo; step; step -= size) {
+ size = step;
+ pin = azfs_block_find(inode, pos, &size);
+ if (!size) {
+ rc = -ENOSPC;
+ goto out;
+ }
+ pin += super->io_addr;
+ /*
+ * FIXME: pin is actually an __iomem pointer, is
+ * that safe? -arnd
+ */
+ if (copy_to_user(target, (void*) pin, size)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ iocb->ki_pos += size;
+ pos += size;
+ target += size;
+ }
+
+ rc = todo;
+
+out:
+ mutex_unlock(&inode->i_mutex);
+
+ return rc;
+}
+
+/**
+ * azfs_aio_write - aio_write() method for file_operations
+ * @iocb, @iov, @nr_segs, @pos: see file_operations methods
+ */
+static ssize_t
+azfs_aio_write(struct kiocb *iocb, const struct iovec *iov,
+ unsigned long nr_segs, loff_t pos)
+{
+ struct azfs_super *super;
+ struct inode *inode;
+ void *source;
+ unsigned long pin;
+ unsigned long size, todo, step;
+ ssize_t rc;
+
+ inode = iocb->ki_filp->f_mapping->host;
+ super = I2S(inode);
+
+ source = iov->iov_base;
+ todo = iov->iov_len;
+
+ mutex_lock(&inode->i_mutex);
+
+ for (step = todo; step; step -= size) {
+ size = step;
+ pin = azfs_block_find(inode, pos, &size);
+ if (!size) {
+ rc = -ENOSPC;
+ goto out;
+ }
+ pin += super->io_addr;
+ /*
+ * FIXME: pin is actually an __iomem pointer, is
+ * that safe? -arnd
+ */
+ if (copy_from_user((void*) pin, source, size)) {
+ rc = -EFAULT;
+ goto out;
+ }
+
+ iocb->ki_pos += size;
+ pos += size;
+ source += size;
+ }
+
+ rc = todo;
+
+out:
+ mutex_unlock(&inode->i_mutex);
+
+ return rc;
+}
+
+/**
+ * azfs_open - open() method for file_operations
+ * @inode, @file: see file_operations methods
+ */
+static int
+azfs_open(struct inode *inode, struct file *file)
+{
+ if (file->f_flags & O_TRUNC) {
+ i_size_write(inode, 0);
+ inode->i_op->truncate(inode);
+ }
+ if (file->f_flags & O_APPEND)
+ inode->i_fop->llseek(file, 0, SEEK_END);
+
+ return 0;
+}
+
+/**
+ * azfs_mmap - mmap() method for file_operations
+ * @file, @vm: see file_operations methods
+ */
+static int
+azfs_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct azfs_super *super;
+ struct azfs_znode *znode;
+ struct inode *inode;
+ unsigned long cursor, pin;
+ unsigned long todo, size, vm_start;
+ pgprot_t page_prot;
+
+ inode = file->f_dentry->d_inode;
+ znode = I2Z(inode);
+ super = I2S(inode);
+
+ if (super->block_size < PAGE_SIZE)
+ return -EINVAL;
+
+ cursor = vma->vm_pgoff << super->block_shift;
+ todo = vma->vm_end - vma->vm_start;
+
+ if (cursor + todo > i_size_read(inode))
+ return -EINVAL;
+
+ page_prot = pgprot_val(vma->vm_page_prot);
+#ifdef CONFIG_PPC
+ page_prot |= (_PAGE_NO_CACHE | _PAGE_RW);
+ page_prot &= ~_PAGE_GUARDED;
+#else
+ page_prot = pgprot_noncached(page_prot);
+#endif
+ vma->vm_page_prot = __pgprot(page_prot);
+
+ vm_start = vma->vm_start;
+ for (size = todo; todo; todo -= size, size = todo) {
+ pin = azfs_block_find(inode, cursor, &size);
+ if (!size)
+ return -EAGAIN;
+ pin += super->ph_addr;
+ pin >>= PAGE_SHIFT;
+ if (remap_pfn_range(vma, vm_start, pin, size, vma->vm_page_prot))
+ return -EAGAIN;
+
+ vm_start += size;
+ cursor += size;
+ }
+
+ return 0;
+}
+
+/**
+ * azfs_truncate - truncate() method for inode_operations
+ * @inode: see inode_operations methods
+ */
+static void
+azfs_truncate(struct inode *inode)
+{
+ struct azfs_super *super;
+ struct azfs_znode *znode;
+ struct azfs_block *block, *tmp_block, *temp, *west, *east;
+ unsigned long id, count;
+ signed long delta;
+
+ super = I2S(inode);
+ znode = I2Z(inode);
+
+ delta = i_size_read(inode) + (super->block_size - 1);
+ delta >>= super->block_shift;
+ delta -= inode->i_blocks;
+
+ if (delta == 0) {
+ znode->size = i_size_read(inode);
+ return;
+ }
+
+ write_lock(&znode->lock);
+
+ while (delta > 0) {
+ west = east = NULL;
+
+ write_lock(&super->lock);
+
+ if (list_empty(&super->block_list)) {
+ write_unlock(&super->lock);
+ break;
+ }
+
+ for (count = delta; count; count--) {
+ for_each_block(block, &super->block_list)
+ if (block->count >= count) {
+ east = block;
+ break;
+ }
+ if (east)
+ break;
+ }
+
+ for_each_block_reverse(block, &znode->block_list) {
+ if (block->id + block->count == east->id)
+ west = block;
+ break;
+ }
+
+ if (east->count == count) {
+ if (west) {
+ west->count += east->count;
+ azfs_block_free(east);
+ } else {
+ azfs_block_move(east, &znode->block_list);
+ }
+ } else {
+ if (west) {
+ west->count += count;
+ } else {
+ if (!azfs_block_init(&znode->block_list,
+ east->id, count)) {
+ write_unlock(&super->lock);
+ break;
+ }
+ }
+
+ east->id += count;
+ east->count -= count;
+ }
+
+ write_unlock(&super->lock);
+
+ inode->i_blocks += count;
+
+ delta -= count;
+ }
+
+ while (delta < 0) {
+ for_each_block_safe_reverse(block, tmp_block, &znode->block_list) {
+ id = block->id;
+ count = block->count;
+ if ((signed long) count + delta > 0) {
+ block->count += delta;
+ id += block->count;
+ count -= block->count;
+ block = NULL;
+ }
+
+ west = east = NULL;
+
+ write_lock(&super->lock);
+
+ for_each_block(temp, &super->block_list) {
+ if (!west && (temp->id + temp->count == id))
+ west = temp;
+ else if (!east && (id + count == temp->id))
+ east = temp;
+ if (west && east)
+ break;
+ }
+
+ if (west && east) {
+ west->count += count + east->count;
+ azfs_block_free(east);
+ if (block)
+ azfs_block_free(block);
+ } else if (west) {
+ west->count += count;
+ if (block)
+ azfs_block_free(block);
+ } else if (east) {
+ east->id -= count;
+ east->count += count;
+ if (block)
+ azfs_block_free(block);
+ } else {
+ if (!block) {
+ if (!azfs_block_init(&super->block_list,
+ id, count)) {
+ write_unlock(&super->lock);
+ break;
+ }
+ } else {
+ azfs_block_move(block, &super->block_list);
+ }
+ }
+
+ write_unlock(&super->lock);
+
+ inode->i_blocks -= count;
+
+ delta += count;
+
+ break;
+ }
+ }
+
+ write_unlock(&znode->lock);
+
+ znode->size = min(i_size_read(inode),
+ (loff_t) inode->i_blocks << super->block_shift);
+}
+
+/**
+ * azfs_getattr - getattr() method for inode_operations
+ * @mnt, @dentry, @stat: see inode_operations methods
+ */
+static int
+azfs_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+ struct azfs_super *super;
+ struct inode *inode;
+ unsigned short shift;
+
+ inode = dentry->d_inode;
+ super = I2S(inode);
+
+ generic_fillattr(inode, stat);
+ stat->blocks = inode->i_blocks;
+ shift = super->block_shift - super->sector_shift;
+ if (shift)
+ stat->blocks <<= shift;
+
+ return 0;
+}
+
+static const struct address_space_operations azfs_aops = {
+ .write_begin = simple_write_begin,
+ .write_end = simple_write_end
+};
+
+static struct backing_dev_info azfs_bdi = {
+ .ra_pages = 0,
+ .capabilities = AZFS_BDI_CAPABILITIES
+};
+
+static struct inode_operations azfs_dir_iops = {
+ .create = azfs_create,
+ .lookup = simple_lookup,
+ .link = simple_link,
+ .unlink = simple_unlink,
+ .symlink = azfs_symlink,
+ .mkdir = azfs_mkdir,
+ .rmdir = simple_rmdir,
+ .mknod = azfs_mknod,
+ .rename = simple_rename
+};
+
+static const struct file_operations azfs_reg_fops = {
+ .llseek = generic_file_llseek,
+ .aio_read = azfs_aio_read,
+ .aio_write = azfs_aio_write,
+ .open = azfs_open,
+ .mmap = azfs_mmap,
+ .fsync = simple_sync_file,
+};
+
+static struct inode_operations azfs_reg_iops = {
+ .truncate = azfs_truncate,
+ .getattr = azfs_getattr
+};
+
+/**
+ * azfs_new_inode - cook a new inode
+ * @sb: super-block
+ * @dir: parent directory
+ * @mode: file mode
+ * @dev: to be forwarded to init_special_inode()
+ */
+static struct inode*
+azfs_new_inode(struct super_block *sb, struct inode *dir, int mode, dev_t dev)
+{
+ struct azfs_super *super;
+ struct inode *inode;
+
+ inode = new_inode(sb);
+ if (!inode)
+ return NULL;
+
+ inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+
+ inode->i_mode = mode;
+ if (dir) {
+ dir->i_mtime = dir->i_ctime = inode->i_mtime;
+ inode->i_uid = current->fsuid;
+ if (dir->i_mode & S_ISGID) {
+ if (S_ISDIR(mode))
+ inode->i_mode |= S_ISGID;
+ inode->i_gid = dir->i_gid;
+ } else {
+ inode->i_gid = current->fsgid;
+ }
+ } else {
+ super = sb->s_fs_info;
+ inode->i_uid = super->uid;
+ inode->i_gid = super->gid;
+ }
+
+ inode->i_blocks = 0;
+ inode->i_mapping->a_ops = &azfs_aops;
+ inode->i_mapping->backing_dev_info = &azfs_bdi;
+
+ switch (mode & S_IFMT) {
+ case S_IFDIR:
+ inode->i_op = &azfs_dir_iops;
+ inode->i_fop = &simple_dir_operations;
+ inc_nlink(inode);
+ break;
+
+ case S_IFREG:
+ inode->i_op = &azfs_reg_iops;
+ inode->i_fop = &azfs_reg_fops;
+ break;
+
+ case S_IFLNK:
+ inode->i_op = &page_symlink_inode_operations;
+ break;
+
+ default:
+ init_special_inode(inode, mode, dev);
+ break;
+ }
+
+ return inode;
+}
+
+/**
+ * azfs_alloc_inode - alloc_inode() method for super_operations
+ * @sb: see super_operations methods
+ */
+static struct inode*
+azfs_alloc_inode(struct super_block *sb)
+{
+ struct azfs_znode *znode;
+
+ znode = kmem_cache_alloc(azfs_znode_cache, GFP_KERNEL);
+ if (znode) {
+ INIT_LIST_HEAD(&znode->block_list);
+ rwlock_init(&znode->lock);
+
+ inode_init_once(&znode->vfs_inode);
+
+ return &znode->vfs_inode;
+ }
+
+ return NULL;
+}
+
+/**
+ * azfs_destroy_inode - destroy_inode() method for super_operations
+ * @inode: see super_operations methods
+ */
+static void
+azfs_destroy_inode(struct inode *inode)
+{
+ kmem_cache_free(azfs_znode_cache, I2Z(inode));
+}
+
+/**
+ * azfs_delete_inode - delete_inode() method for super_operations
+ * @inode: see super_operations methods
+ */
+static void
+azfs_delete_inode(struct inode *inode)
+{
+ if (S_ISREG(inode->i_mode)) {
+ i_size_write(inode, 0);
+ azfs_truncate(inode);
+ }
+ truncate_inode_pages(&inode->i_data, 0);
+ clear_inode(inode);
+}
+
+/**
+ * azfs_statfs - statfs() method for super_operations
+ * @dentry, @stat: see super_operations methods
+ */
+static int
+azfs_statfs(struct dentry *dentry, struct kstatfs *stat)
+{
+ struct super_block *sb;
+ struct azfs_super *super;
+ struct inode *inode;
+ unsigned long inodes, blocks;
+
+ sb = dentry->d_sb;
+ super = sb->s_fs_info;
+
+ inodes = blocks = 0;
+ mutex_lock(&sb->s_lock);
+ list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
+ inodes++;
+ blocks += inode->i_blocks;
+ }
+ mutex_unlock(&sb->s_lock);
+
+ stat->f_type = AZFS_SUPERBLOCK_MAGIC;
+ stat->f_bsize = super->block_size;
+ stat->f_blocks = super->media_size >> super->block_shift;
+ stat->f_bfree = stat->f_blocks - blocks;
+ stat->f_bavail = stat->f_blocks - blocks;
+ stat->f_files = inodes + blocks;
+ stat->f_ffree = blocks + 1;
+ stat->f_namelen = NAME_MAX;
+
+ return 0;
+}
+
+static struct super_operations azfs_ops = {
+ .alloc_inode = azfs_alloc_inode,
+ .destroy_inode = azfs_destroy_inode,
+ .drop_inode = generic_delete_inode,
+ .delete_inode = azfs_delete_inode,
+ .statfs = azfs_statfs
+};
+
+enum {
+ Opt_blocksize_short,
+ Opt_blocksize_long,
+ Opt_uid,
+ Opt_gid,
+ Opt_err
+};
+
+static match_table_t tokens = {
+ {Opt_blocksize_short, "bs=%u"},
+ {Opt_blocksize_long, "blocksize=%u"},
+ {Opt_uid, "uid=%u"},
+ {Opt_gid, "gid=%u"},
+ {Opt_err, NULL}
+};
+
+/**
+ * azfs_parse_mount_parameters - parse options given to mount with -o
+ * @super: azfs super block extension
+ * @options: comma separated options
+ */
+static int
+azfs_parse_mount_parameters(struct azfs_super *super, char *options)
+{
+ char *option;
+ int token, value;
+ substring_t args[MAX_OPT_ARGS];
+
+ if (!options)
+ return 1;
+
+ while ((option = strsep(&options, ",")) != NULL) {
+ if (!*option)
+ continue;
+
+ token = match_token(option, tokens, args);
+ switch (token) {
+ case Opt_blocksize_short:
+ case Opt_blocksize_long:
+ if (match_int(&args[0], &value))
+ goto syntax_error;
+ super->block_size = value;
+ break;
+
+ case Opt_uid:
+ if (match_int(&args[0], &value))
+ goto syntax_error;
+ super->uid = value;
+ break;
+
+ case Opt_gid:
+ if (match_int(&args[0], &value))
+ goto syntax_error;
+ super->gid = value;
+ break;
+
+ default:
+ goto syntax_error;
+ }
+ }
+
+ return 1;
+
+syntax_error:
+ printk(KERN_ERR "%s: invalid mount option\n",
+ AZFS_FILESYSTEM_NAME);
+
+ return 0;
+}
+
+/**
+ * azfs_fill_super - fill_super routine for get_sb
+ * @sb, @data, @silent: see file_system_type methods
+ */
+static int
+azfs_fill_super(struct super_block *sb, void *data, int silent)
+{
+ struct gendisk *disk;
+ struct azfs_super *super = NULL, *tmp_super;
+ struct azfs_block *block = NULL;
+ struct inode *inode = NULL;
+ void *kaddr;
+ unsigned long pfn;
+ int rc;
+
+ BUG_ON(!sb->s_bdev);
+
+ disk = sb->s_bdev->bd_disk;
+
+ BUG_ON(!disk || !disk->queue);
+
+ if (!disk->fops->direct_access) {
+ printk(KERN_ERR "%s needs a block device with a "
+ "direct_access() method\n",
+ AZFS_FILESYSTEM_NAME);
+ return -ENOSYS;
+ }
+
+ get_device(disk->driverfs_dev);
+
+ sb->s_magic = AZFS_SUPERBLOCK_MAGIC;
+ sb->s_flags = AZFS_SUPERBLOCK_FLAGS;
+ sb->s_op = &azfs_ops;
+ sb->s_maxbytes = get_capacity(disk) * disk->queue->hardsect_size;
+ sb->s_time_gran = 1;
+
+ spin_lock(&super_list.lock);
+ list_for_each_entry(tmp_super, &super_list.head, list)
+ if (tmp_super->blkdev == sb->s_bdev) {
+ super = tmp_super;
+ break;
+ }
+ spin_unlock(&super_list.lock);
+
+ if (super) {
+ if (data && strlen((char*) data))
+ printk(KERN_WARNING "/dev/%s was already mounted with "
+ "%s before, it will be mounted with "
+ "mount options used last time, "
+ "options just given would be ignored\n",
+ disk->disk_name, AZFS_FILESYSTEM_NAME);
+ sb->s_fs_info = super;
+ } else {
+ super = kzalloc(sizeof(struct azfs_super), GFP_KERNEL);
+ if (!super) {
+ rc = -ENOMEM;
+ goto failed;
+ }
+ sb->s_fs_info = super;
+
+ if (!azfs_parse_mount_parameters(super, (char*) data)) {
+ rc = -EINVAL;
+ goto failed;
+ }
+
+ inode = azfs_new_inode(sb, NULL, S_IFDIR | S_IRWXUGO, 0);
+ if (!inode) {
+ rc = -ENOMEM;
+ goto failed;
+ }
+
+ super->root = d_alloc_root(inode);
+ if (!super->root) {
+ rc = -ENOMEM;
+ goto failed;
+ }
+ dget(super->root);
+
+ INIT_LIST_HEAD(&super->list);
+ INIT_LIST_HEAD(&super->block_list);
+ rwlock_init(&super->lock);
+
+ super->media_size = sb->s_maxbytes;
+
+ if (!super->block_size)
+ super->block_size = sb->s_blocksize;
+ super->block_shift = blksize_bits(super->block_size);
+
+ super->sector_size = disk->queue->hardsect_size;
+ super->sector_shift = blksize_bits(super->sector_size);
+
+ super->blkdev = sb->s_bdev;
+
+ block = azfs_block_init(&super->block_list,
+ 0, super->media_size >> super->block_shift);
+ if (!block) {
+ rc = -ENOMEM;
+ goto failed;
+ }
+
+ rc = disk->fops->direct_access(super->blkdev, 0, &kaddr, &pfn);
+ if (rc < 0) {
+ rc = -EFAULT;
+ goto failed;
+ }
+ super->ph_addr = (unsigned long) kaddr;
+
+ super->io_addr = (unsigned long) ioremap_flags(
+ super->ph_addr, super->media_size, _PAGE_NO_CACHE);
+ if (!super->io_addr) {
+ rc = -EFAULT;
+ goto failed;
+ }
+
+ spin_lock(&super_list.lock);
+ list_add(&super->list, &super_list.head);
+ spin_unlock(&super_list.lock);
+ }
+
+ sb->s_root = super->root;
+ disk->driverfs_dev->driver_data = super;
+ disk->driverfs_dev->platform_data = sb;
+
+ if (super->block_size < PAGE_SIZE)
+ printk(KERN_INFO "Block size on %s is smaller then system "
+ "page size: mmap() would not be supported\n",
+ disk->disk_name);
+
+ return 0;
+
+failed:
+ if (super) {
+ sb->s_root = NULL;
+ sb->s_fs_info = NULL;
+ if (block)
+ azfs_block_free(block);
+ if (super->root)
+ dput(super->root);
+ if (inode)
+ iput(inode);
+ disk->driverfs_dev->driver_data = NULL;
+ kfree(super);
+ disk->driverfs_dev->platform_data = NULL;
+ put_device(disk->driverfs_dev);
+ }
+
+ return rc;
+}
+
+/**
+ * azfs_get_sb - get_sb() method for file_system_type
+ * @fs_type, @flags, @dev_name, @data, @mount: see file_system_type methods
+ */
+static int
+azfs_get_sb(struct file_system_type *fs_type, int flags,
+ const char *dev_name, void *data, struct vfsmount *mount)
+{
+ return get_sb_bdev(fs_type, flags,
+ dev_name, data, azfs_fill_super, mount);
+}
+
+/**
+ * azfs_kill_sb - kill_sb() method for file_system_type
+ * @sb: see file_system_type methods
+ */
+static void
+azfs_kill_sb(struct super_block *sb)
+{
+ sb->s_root = NULL;
+ kill_block_super(sb);
+}
+
+static struct file_system_type azfs_fs = {
+ .owner = THIS_MODULE,
+ .name = AZFS_FILESYSTEM_NAME,
+ .get_sb = azfs_get_sb,
+ .kill_sb = azfs_kill_sb,
+ .fs_flags = AZFS_FILESYSTEM_FLAGS
+};
+
+/**
+ * azfs_init
+ */
+static int __init
+azfs_init(void)
+{
+ int rc;
+
+ INIT_LIST_HEAD(&super_list.head);
+ spin_lock_init(&super_list.lock);
+
+ azfs_znode_cache = kmem_cache_create("azfs_znode_cache",
+ sizeof(struct azfs_znode), 0, AZFS_CACHE_FLAGS, NULL);
+ if (!azfs_znode_cache) {
+ printk(KERN_ERR "Could not allocate inode cache for %s\n",
+ AZFS_FILESYSTEM_NAME);
+ rc = -ENOMEM;
+ goto failed;
+ }
+
+ azfs_block_cache = kmem_cache_create("azfs_block_cache",
+ sizeof(struct azfs_block), 0, AZFS_CACHE_FLAGS, NULL);
+ if (!azfs_block_cache) {
+ printk(KERN_ERR "Could not allocate block cache for %s\n",
+ AZFS_FILESYSTEM_NAME);
+ rc = -ENOMEM;
+ goto failed;
+ }
+
+ rc = register_filesystem(&azfs_fs);
+ if (rc != 0) {
+ printk(KERN_ERR "Could not register %s\n",
+ AZFS_FILESYSTEM_NAME);
+ goto failed;
+ }
+
+ return 0;
+
+failed:
+ if (azfs_block_cache)
+ kmem_cache_destroy(azfs_block_cache);
+
+ if (azfs_znode_cache)
+ kmem_cache_destroy(azfs_znode_cache);
+
+ return rc;
+}
+
+/**
+ * azfs_exit
+ */
+static void __exit
+azfs_exit(void)
+{
+ struct azfs_super *super, *tmp_super;
+ struct azfs_block *block, *tmp_block;
+ struct gendisk *disk;
+
+ spin_lock(&super_list.lock);
+ list_for_each_entry_safe(super, tmp_super, &super_list.head, list) {
+ disk = super->blkdev->bd_disk;
+ list_del(&super->list);
+ iounmap((void*) super->io_addr);
+ write_lock(&super->lock);
+ for_each_block_safe(block, tmp_block, &super->block_list)
+ azfs_block_free(block);
+ write_unlock(&super->lock);
+ disk->driverfs_dev->driver_data = NULL;
+ disk->driverfs_dev->platform_data = NULL;
+ kfree(super);
+ put_device(disk->driverfs_dev);
+ }
+ spin_unlock(&super_list.lock);
+
+ unregister_filesystem(&azfs_fs);
+
+ kmem_cache_destroy(azfs_block_cache);
+ kmem_cache_destroy(azfs_znode_cache);
+}
+
+module_init(azfs_init);
+module_exit(azfs_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxim Shchetynin <maxim@de.ibm.com>");
+MODULE_DESCRIPTION("Non-buffered file system for IO devices");
--
1.5.4.3
--
^ permalink raw reply related
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