LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/5] make *_gate_vma accept mm_struct instead of task_struct
From: Stephen Wilson @ 2011-03-09  0:31 UTC (permalink / raw)
  To: x86
  Cc: linux-s390, Andi Kleen, Paul Mundt, linux-sh, Heiko Carstens,
	linux-kernel, linux-mm, Ingo Molnar, Paul Mackerras,
	Alexander Viro, H. Peter Anvin, Martin Schwidefsky, linux390,
	Thomas Gleixner, Michel Lespinasse, linuxppc-dev, Andrew Morton


Morally, the question of whether an address lies in a gate vma should be asked
with respect to an mm, not a particular task.

Practically, dropping the dependency on task_struct will help make current and
future operations on mm's more flexible and convenient.  In particular, it
allows some code paths to avoid the need to hold task_lock.

The only architecture this change impacts in any significant way is x86_64.
The principle change on that architecture is to mirror TIF_IA32 via
a new flag in mm_context_t. 

This is the first of a two part series that implements safe writes to
/proc/pid/mem.  I will be posting the second series to lkml shortly.  These
patches are based on v2.6.38-rc8.  The general approach used here was suggested
to me by Alexander Viro, but any mistakes present in these patches are entirely
my own.


--
steve


Stephen Wilson (5):
      x86: add context tag to mark mm when running a task in 32-bit compatibility mode
      x86: mark associated mm when running a task in 32 bit compatibility mode
      mm: arch: make get_gate_vma take an mm_struct instead of a task_struct
      mm: arch: make in_gate_area take an mm_struct instead of a task_struct
      mm: arch: rename in_gate_area_no_task to in_gate_area_no_mm


 arch/powerpc/kernel/vdso.c         |    6 +++---
 arch/s390/kernel/vdso.c            |    6 +++---
 arch/sh/kernel/vsyscall/vsyscall.c |    6 +++---
 arch/x86/ia32/ia32_aout.c          |    1 +
 arch/x86/include/asm/mmu.h         |    6 ++++++
 arch/x86/kernel/process_64.c       |    8 ++++++++
 arch/x86/mm/init_64.c              |   16 ++++++++--------
 arch/x86/vdso/vdso32-setup.c       |   15 ++++++++-------
 fs/binfmt_elf.c                    |    2 +-
 fs/proc/task_mmu.c                 |    8 +++++---
 include/linux/mm.h                 |   10 +++++-----
 kernel/kallsyms.c                  |    4 ++--
 mm/memory.c                        |    8 ++++----
 mm/mlock.c                         |    4 ++--
 mm/nommu.c                         |    2 +-
 15 files changed, 61 insertions(+), 42 deletions(-)

^ permalink raw reply

* Re: [PATCH] RTC driver(Linux) for PT7C4338 chip.
From: Andrew Morton @ 2011-03-09  0:31 UTC (permalink / raw)
  To: Priyanka Jain; +Cc: a.zummo, linuxppc-dev, rtc-linux, p_gortmaker
In-Reply-To: <1299039150-21063-1-git-send-email-Priyanka.Jain@freescale.com>

On Wed, 2 Mar 2011 09:42:30 +0530
Priyanka Jain <Priyanka.Jain@freescale.com> wrote:

> PT7C4338 chip is being manufactured by Pericom Technology Inc.
> It is a serial real-time clock which provides:
> 1)Low-power clock/calendar.
> 2)Programmable square-wave output.
> It has 56 bytes of nonvolatile RAM.
> 
> Signed-off-by: Priyanka Jain <Priyanka.Jain@freescale.com>
> ---
>  PT7C4338 RTC driver is verified on Freescale P1010RDB. 
>  Please pick this patch for 2.6.39
> 
>  drivers/rtc/Kconfig        |    9 ++
>  drivers/rtc/Makefile       |    1 +
>  drivers/rtc/rtc-pt7c4338.c |  215 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 225 insertions(+), 0 deletions(-)
>  create mode 100644 drivers/rtc/rtc-pt7c4338.c
> 
> diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
> index 10ba12c..6ff0901 100644
> --- a/drivers/rtc/Kconfig
> +++ b/drivers/rtc/Kconfig
> @@ -324,6 +324,15 @@ config RTC_DRV_RX8025
>  	  This driver can also be built as a module. If so, the module
>  	  will be called rtc-rx8025.
>  
> +config RTC_DRV_PT7C4338
> +	tristate "Pericom Technology Inc. PT7C4338 RTC"
> +	help
> +	  If you say yes here you get support for the Pericom Technology
> +	  Inc. PT7C4338 RTC chip.
> +
> +	  This driver can also be built as a module. If so, the module
> +	  will be called rtc-pt7c4338.
> +

This means that the driver is available on all architectures, not just
powerpc.

This is a good thing and a bad thing.  Bad because it makes non-ppc
people possibly build and install a driver which they will never use
(correct?).  And good because it means that more people do compilation
test coverage.

Speaking of which:


From: Andrew Morton <akpm@linux-foundation.org>

include slab.h, remove unused local

drivers/rtc/rtc-pt7c4338.c: In function 'pt7c4338_probe':
drivers/rtc/rtc-pt7c4338.c:159: error: implicit declaration of function 'kzalloc'
drivers/rtc/rtc-pt7c4338.c:159: warning: assignment makes pointer from integer without a cast
drivers/rtc/rtc-pt7c4338.c:176: error: implicit declaration of function 'kfree'
drivers/rtc/rtc-pt7c4338.c:156: warning: unused variable 'adapter'

Cc: Alessandro Zummo <a.zummo@towertech.it>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Kumar Gala <galak@gate.crashing.org>
Cc: Priyanka Jain <Priyanka.Jain@freescale.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
---

 drivers/rtc/rtc-pt7c4338.c |    2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff -puN drivers/rtc/Kconfig~rtc-driver-for-pt7c4338-chip-fix drivers/rtc/Kconfig
diff -puN drivers/rtc/Makefile~rtc-driver-for-pt7c4338-chip-fix drivers/rtc/Makefile
diff -puN drivers/rtc/rtc-pt7c4338.c~rtc-driver-for-pt7c4338-chip-fix drivers/rtc/rtc-pt7c4338.c
--- a/drivers/rtc/rtc-pt7c4338.c~rtc-driver-for-pt7c4338-chip-fix
+++ a/drivers/rtc/rtc-pt7c4338.c
@@ -35,6 +35,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/slab.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/rtc.h>
@@ -153,7 +154,6 @@ static int pt7c4338_probe(struct i2c_cli
 		const struct i2c_device_id *id)
 {
 	struct pt7c4338 *pt7c4338;
-	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
 	int ret;
 
 	pt7c4338 = kzalloc(sizeof(struct pt7c4338), GFP_KERNEL);
_

^ permalink raw reply

* Re: RFC: x86: kill binutils 2.16.x?
From: Kyle Moffett @ 2011-03-08 23:43 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Andrew Morton, linux-kbuild, Kumar Gala,
	Linux Kernel Mailing List, Kyle Moffett, H. Peter Anvin,
	Ingo Molnar, linuxppc-dev, Thomas Gleixner
In-Reply-To: <1299626008.22236.47.camel@pasglop>

On Tue, Mar 8, 2011 at 18:13, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Tue, 2011-03-08 at 16:59 -0500, Kyle Moffett wrote:
>>
>> The problem is not with the kernel compile itself, but with the 2.12
>> "dssall" binutils test. =C2=A0Basically, recent binutils treats e500 as
>> effectively a separate architecture that happens to share *most* of
>> the opcodes with regular PowerPC.
>
> This is bogus. Newer e500 don't have that SPE crap afaik and BookI and
> II of the architecture have been converged. In fact, Scott, don't newer
> FSL chips also support real lwsync ?

When I'm talking about "e500" I'm specifically referring to the SPE
stuff.  The "e500mc" cores are a whole different beast with a regular
FPU, but those have their own Kconfig option: "PPC_E500MC".

Actually, looking at it again, the "PPC_E500MC" depends on "E500", it
should select "PPC_FSL_BOOK3E" instead.  There are probably bugs
lurking here.

There really is fundamentally no good way to build a single system
image that supports both E500 (spe-based) and E500MC (classic FPU).
You can sort-of run classic FPU emulation on the E500, but the
performance is terrifyingly bad.

The naming confusion really is really bad too, IMO.

>> =C2=A0Any opcode which is not understood
>> by the e500 chip is either convert to an equivalent opcode which is
>> understood (IE: lwsync =3D> sync), or failed with an error. =C2=A0This m=
eans
>> that the kernel compile aborts early telling me to upgrade to a newer
>> version of binutils.
>
> This is more bogosity in binutils. lwsync is designed to fallback as
> sync if not supported in -HW-, binutils shouldn't silently swallow it.
>
> Or is it that FSL failed on the original e500 and make lwsync actually
> trap ?

Yeah... for some reason FreeScale made the "lwsync" operation trap on
e500 (again, only talking about "e500" with SPE, not "e500mc").

Unfortunately it's used frequently enough that there's a very
noticeable performance gain (~5% for some programs) by substituting it
in binutils, so that's what happens.


>> This was *critical* for getting an actual Debian distribution
>> bootstrapped on the e500 cores, because so much software assumes
>> PowerPC =3D=3D altivec (ffmpeg), hardcodes 'asm("lwsync")' for memory
>> barriers (80+ packages in Debian), or includes hand-coded
>> floating-point ASM instructions (libffi). =C2=A0Noisy build errors are
>> better than silent runtime failures any day of the week.
>>
>> At the very least that test needs to be turned off if
>> CONFIG_ALTIVEC=3Dn, because the kernel builds and runs fine otherwise.
>
> I think the right thing is to keep that as e500-legacy or something,
> because afaik, newer e500's don't have most of these issues and could be
> treated as "normal" powerpc again.

There is a separate "-me500mc" option for GAS that does the right
thing, but the kernel currently does not seem to use it.

arch/powerpc/Makefile has this:
    cpu-as-$(CONFIG_4xx) +=3D -Wa,-m405
    cpu-as-$(CONFIG_6xx) +=3D -Wa,-maltivec
    cpu-as-$(CONFIG_POWER4) +=3D -Wa,-maltivec
    cpu-as-$(CONFIG_E500) +=3D -Wa,-me500
    cpu-as-$(CONFIG_E200) +=3D -Wa,-me200

As it is, I strongly suspect that the kernel is broken for
CONFIG_E500MC with current development releases of binutils.

The real "solution" is that "e500" needs to be treated as an almost
entirely different architecture from "all other powerpc (including
e500mc)".  Userspace is only ABI-compatible if you use "-msoft-float"
on both sides.

I've been dealing with it for a while now, it really is a fiasco all around=
...

After a month of wrestling with the official Debian "powerpc" port we
gave up and created a new port "powerpcspe" specifically for the
"e500" SPE-based chips.  Then we tripped over 3 relatively major GCC
bugs which had been lurking since e500 support was initially added.

See http://wiki.debian.org/PowerPCSPEPort for a very out-of-date
status on that whole thing.

Cheers,
Kyle Moffett

^ permalink raw reply

* Re: RFC: x86: kill binutils 2.16.x?
From: Benjamin Herrenschmidt @ 2011-03-08 23:13 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Andrew Morton, linux-kbuild, Kumar Gala,
	Linux Kernel Mailing List, Kyle Moffett, H. Peter Anvin,
	Ingo Molnar, linuxppc-dev, Thomas Gleixner
In-Reply-To: <AANLkTikAnb39XhR0hdZAzTKGJ-P1rH+ZxtD+Dea7-364@mail.gmail.com>

On Tue, 2011-03-08 at 16:59 -0500, Kyle Moffett wrote:
> 
> The problem is not with the kernel compile itself, but with the 2.12
> "dssall" binutils test.  Basically, recent binutils treats e500 as
> effectively a separate architecture that happens to share *most* of
> the opcodes with regular PowerPC. 

This is bogus. Newer e500 don't have that SPE crap afaik and BookI and
II of the architecture have been converged. In fact, Scott, don't newer
FSL chips also support real lwsync ?

>  Any opcode which is not understood
> by the e500 chip is either convert to an equivalent opcode which is
> understood (IE: lwsync => sync), or failed with an error.  This means
> that the kernel compile aborts early telling me to upgrade to a newer
> version of binutils.

This is more bogosity in binutils. lwsync is designed to fallback as
sync if not supported in -HW-, binutils shouldn't silently swallow it.

Or is it that FSL failed on the original e500 and make lwsync actually
trap ?

> This was *critical* for getting an actual Debian distribution
> bootstrapped on the e500 cores, because so much software assumes
> PowerPC == altivec (ffmpeg), hardcodes 'asm("lwsync")' for memory
> barriers (80+ packages in Debian), or includes hand-coded
> floating-point ASM instructions (libffi).  Noisy build errors are
> better than silent runtime failures any day of the week.
> 
> At the very least that test needs to be turned off if
> CONFIG_ALTIVEC=n, because the kernel builds and runs fine otherwise.

I think the right thing is to keep that as e500-legacy or something,
because afaik, newer e500's don't have most of these issues and could be
treated as "normal" powerpc again.

Cheers,
Ben.

^ permalink raw reply

* Re: RFC: x86: kill binutils 2.16.x?
From: Scott Wood @ 2011-03-08 21:56 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Kyle Moffett, linux-kbuild, Kumar Gala, Linux Kernel Mailing List,
	Thomas Gleixner, Kyle Moffett, H. Peter Anvin, Andrew Morton,
	linuxppc-dev, Ingo Molnar
In-Reply-To: <1299619716.22236.32.camel@pasglop>

On Wed, 9 Mar 2011 08:28:36 +1100
Benjamin Herrenschmidt <benh@kernel.crashing.org> wrote:

> On Tue, 2011-03-08 at 14:57 -0500, Kyle Moffett wrote:
> > 
> > Specifically the e500 doesn't have a normal PowerPC FPU, it has a
> > custom FPU built using extended integer registers instead, and it
> > happens to borrow the AltiVec opcode range to do it.
> > 
> > When trying to port Debian to the platform we were getting SIGILL's
> > all over the place until binutils got updated to reject all of the
> > unsupported opcodes on this particular platform.  Now of course we get
> > build errors, but that's a lot easier to debug and fix. :-D
> > 
> > Basically, binutils no longer supports "-many" (because too many
> > opcodes conflict), and the test itself would fail anyways (because
> > "dssall" is not valid on "any" PowerPC). 
> 
> Note that this freescale "SPE" fiasco is just that ... a fiasco :-) I
> don't think there's that many cases of opcode overlap outside of it.
> 
> Now regarding the kernel, the best is probably for nasty cases like that
> to use hand coded opcodes (see ppc-opcodes.h) and stick to a more
> "generic" setting for binutils, since it should be possible to build
> kernels that support multiple types of BookE CPUs with different
> floating point units.

Combined kernels between e500v1/2 and e500mc are currently not supported
for other reasons (current kconfig doesn't prohibit it, but it doesn't
work), such as a cache line size difference (a hardcoded L1_CACHE_BYTES is
used in various places for loops), an inability to enable SPE when e500mc
is enabled, etc.

Kumar recently internally said we're not going to bother making it work.
I'm inclined to agree, given you can't even run the same userspace (unless
you don't use hard floating point at all).  It's one thing to not want to
require a separate kernel for each board, but there's a point of
diminishing returns.

-Scott

^ permalink raw reply

* Re: RFC: x86: kill binutils 2.16.x?
From: Kyle Moffett @ 2011-03-08 21:59 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Andrew Morton, linux-kbuild, Kumar Gala,
	Linux Kernel Mailing List, Kyle Moffett, H. Peter Anvin,
	Ingo Molnar, linuxppc-dev, Thomas Gleixner
In-Reply-To: <1299619716.22236.32.camel@pasglop>

On Tue, Mar 8, 2011 at 16:28, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
> On Tue, 2011-03-08 at 14:57 -0500, Kyle Moffett wrote:
>> Specifically the e500 doesn't have a normal PowerPC FPU, it has a
>> custom FPU built using extended integer registers instead, and it
>> happens to borrow the AltiVec opcode range to do it.
>>
>> When trying to port Debian to the platform we were getting SIGILL's
>> all over the place until binutils got updated to reject all of the
>> unsupported opcodes on this particular platform. =C2=A0Now of course we =
get
>> build errors, but that's a lot easier to debug and fix. :-D
>>
>> Basically, binutils no longer supports "-many" (because too many
>> opcodes conflict), and the test itself would fail anyways (because
>> "dssall" is not valid on "any" PowerPC).
>
> Note that this freescale "SPE" fiasco is just that ... a fiasco :-) I
> don't think there's that many cases of opcode overlap outside of it.

I absolutely agree on the "fiasco" part, although I'm pretty sure that
there's a large number of incompatible ARM variants (even 16-bit vs.
32-bit opcodes).  Unfortunately there's a lot of shipped hardware to
be supported and maintained...


> Now regarding the kernel, the best is probably for nasty cases like that
> to use hand coded opcodes (see ppc-opcodes.h) and stick to a more
> "generic" setting for binutils, since it should be possible to build
> kernels that support multiple types of BookE CPUs with different
> floating point units.

The problem is not with the kernel compile itself, but with the 2.12
"dssall" binutils test.  Basically, recent binutils treats e500 as
effectively a separate architecture that happens to share *most* of
the opcodes with regular PowerPC.  Any opcode which is not understood
by the e500 chip is either convert to an equivalent opcode which is
understood (IE: lwsync =3D> sync), or failed with an error.  This means
that the kernel compile aborts early telling me to upgrade to a newer
version of binutils.

This was *critical* for getting an actual Debian distribution
bootstrapped on the e500 cores, because so much software assumes
PowerPC =3D=3D altivec (ffmpeg), hardcodes 'asm("lwsync")' for memory
barriers (80+ packages in Debian), or includes hand-coded
floating-point ASM instructions (libffi).  Noisy build errors are
better than silent runtime failures any day of the week.

At the very least that test needs to be turned off if
CONFIG_ALTIVEC=3Dn, because the kernel builds and runs fine otherwise.

Cheers,
Kyle Moffett

^ permalink raw reply

* Re: RFC: x86: kill binutils 2.16.x?
From: Benjamin Herrenschmidt @ 2011-03-08 21:28 UTC (permalink / raw)
  To: Kyle Moffett
  Cc: Andrew Morton, linux-kbuild, Kumar Gala,
	Linux Kernel Mailing List, Kyle Moffett, H. Peter Anvin,
	Ingo Molnar, linuxppc-dev, Thomas Gleixner
In-Reply-To: <AANLkTik4aTN8+Ob_GVwF17v6pDNGg2DEZJubBazs2e3L@mail.gmail.com>

On Tue, 2011-03-08 at 14:57 -0500, Kyle Moffett wrote:
> 
> Specifically the e500 doesn't have a normal PowerPC FPU, it has a
> custom FPU built using extended integer registers instead, and it
> happens to borrow the AltiVec opcode range to do it.
> 
> When trying to port Debian to the platform we were getting SIGILL's
> all over the place until binutils got updated to reject all of the
> unsupported opcodes on this particular platform.  Now of course we get
> build errors, but that's a lot easier to debug and fix. :-D
> 
> Basically, binutils no longer supports "-many" (because too many
> opcodes conflict), and the test itself would fail anyways (because
> "dssall" is not valid on "any" PowerPC). 

Note that this freescale "SPE" fiasco is just that ... a fiasco :-) I
don't think there's that many cases of opcode overlap outside of it.

Now regarding the kernel, the best is probably for nasty cases like that
to use hand coded opcodes (see ppc-opcodes.h) and stick to a more
"generic" setting for binutils, since it should be possible to build
kernels that support multiple types of BookE CPUs with different
floating point units.

Cheers,
Ben.

^ permalink raw reply

* Re: RFC: x86: kill binutils 2.16.x?
From: Kyle Moffett @ 2011-03-08 19:57 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: linux-kbuild, Kumar Gala, Linux Kernel Mailing List, Kyle Moffett,
	H. Peter Anvin, Thomas Gleixner, linuxppc-dev, Andrew Morton
In-Reply-To: <20110303083035.GB14854@elte.hu>

On Thu, Mar 3, 2011 at 03:30, Ingo Molnar <mingo@elte.hu> wrote:
> This is how specific GAS functionality is tested in arch/powerpc:
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0@if ! /bin/echo dssall | $(AS) -many -o $(TOUT=
) >/dev/null 2>&1 ; then \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0echo -n '*** ${VER=
SION}.${PATCHLEVEL} kernels no longer build ' ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0echo 'correctly wi=
th old versions of binutils.' ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0echo '*** Please u=
pgrade your binutils to 2.12.1 or newer' ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0false ; \
> =C2=A0 =C2=A0 =C2=A0 =C2=A0fi
>
> This would also be a 'constructive' (and safest) way of blacklisting binu=
tils: we'd
> really only exclude binutils that is truly buggy.

Hrm... well... actually...

It's funny that you brought up this particular case.  While I agree
that it's good in general, it's causing problems for me building a
kernel using a recent e500 gcc/binutils (triplet
"powerpc-linux-gnuspe").

Specifically the e500 doesn't have a normal PowerPC FPU, it has a
custom FPU built using extended integer registers instead, and it
happens to borrow the AltiVec opcode range to do it.

When trying to port Debian to the platform we were getting SIGILL's
all over the place until binutils got updated to reject all of the
unsupported opcodes on this particular platform.  Now of course we get
build errors, but that's a lot easier to debug and fix. :-D

Basically, binutils no longer supports "-many" (because too many
opcodes conflict), and the test itself would fail anyways (because
"dssall" is not valid on "any" PowerPC).

So while I think that it is entirely reasonable to add a similar test
for buggy x86 binutils, I'm actually about to send a patch to remove
that particular check from the powerpc Makefile.  Since the "required"
binutils 2.12.1 was released in May 2002 (almost 9 years ago) it's
probably not even worth testing for anymore.

Cheers,
Kyle Moffett

^ permalink raw reply

* Re: Mpc8315erdb openvpn segmentation fault
From: Scott Wood @ 2011-03-08 18:52 UTC (permalink / raw)
  To: Vasanth Ragavendran; +Cc: linuxppc-dev
In-Reply-To: <31094242.post@talk.nabble.com>

On Mon, 7 Mar 2011 20:28:32 -0800
Vasanth Ragavendran <ragavendrapec@yahoo.co.in> wrote:

> 
> Thanks a ton Scott. Actually i was working with the same version of the
> kernel on both the boards.
> it was 2.6.29.6. neither i changed the u-boot. it was the same in both.
> however i recompiled the kernel and i installed on both the boards and it
> worked fine! :) thanks again for responding. however i've another question.
> my filesystem in the board is non-persistent i.e. the files i create are
> erased after i reboot i know the files are getting stored in RAM and i wish
> to make them persistent. what do i need to do for this? should i create a
> separate partition in the flash and load certain files into that partition?
> or how should i make it persistent so that files stay beyond reboot! thanks
> again! eagerly awaiting your response.

Yes, you should create a filesystem (e.g. jffs2) on a flash partition.

-Scott

^ permalink raw reply

* RE: [PATCH][v2] driver/FSL SATA:Fix wrong Device Error Register usage
From: David Laight @ 2011-03-08 11:39 UTC (permalink / raw)
  To: Prabhakar Kushwaha, linux-ide
  Cc: meet2prabhu, Ashish Kalra, jgarzik, linuxppc-dev
In-Reply-To: <1299555095-2967-1-git-send-email-prabhakar@freescale.com>

=20
>  Case when ffs return will never arise.This scenario is=20
> already been discussed
>  on linuxppc-dev@lists.ozlabs.org. Please see below explanation:
>  sata_fsl_error_intr() is called during device error.The=20
> mentioned scenario
>  will never comes. It can be observed via code:-
>         if (cereg) {   --> cereg is set on command error.=20
> Means there is at least 1 device present.

This all relies on the hardware working properly, and
nothing else accidentally clearing the device 'error'
bit mask.

Being slightly defensive when the out of range value
causes an array subscript error seems sensible.

It isn't as though the code size or execution time
matters here.

	David

^ permalink raw reply

* [PATCH 11/18] powerpc/pmac/smp: Properly NAP offlined CPU on G5
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

The current code soft-disables, and then goes to NAP mode which
turns interrupts on. That means that if an interrupt occurs, we
will hit the masked interrupt code path which isn't what we want,
as it will return with EE off, which will either get us out of
NAP mode, or fail to enter it (according to spec).

Instead, let's just rely on the fact that it is safe to take
decrementer interrupts on an offline CPU and leave interrupts
enabled. We can also get rid of the special case in asm for
power4_cpu_offline_powersave() and just use power4_idle().

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/machdep.h    |    1 -
 arch/powerpc/kernel/head_64.S         |    7 +++++++
 arch/powerpc/kernel/idle_power4.S     |   21 ---------------------
 arch/powerpc/platforms/powermac/smp.c |   14 ++++++++------
 4 files changed, 15 insertions(+), 28 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index bcfc0da..578d330 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -266,7 +266,6 @@ struct machdep_calls {
 
 extern void e500_idle(void);
 extern void power4_idle(void);
-extern void power4_cpu_offline_powersave(void);
 extern void ppc6xx_idle(void);
 extern void book3e_idle(void);
 
diff --git a/arch/powerpc/kernel/head_64.S b/arch/powerpc/kernel/head_64.S
index 782f23d..271140b 100644
--- a/arch/powerpc/kernel/head_64.S
+++ b/arch/powerpc/kernel/head_64.S
@@ -536,6 +536,13 @@ _GLOBAL(pmac_secondary_start)
 	add	r13,r13,r4		/* for this processor.		*/
 	mtspr	SPRN_SPRG_PACA,r13	/* Save vaddr of paca in an SPRG*/
 
+	/* Mark interrupts soft and hard disabled (they might be enabled
+	 * in the PACA when doing hotplug)
+	 */
+	li	r0,0
+	stb	r0,PACASOFTIRQEN(r13)
+	stb	r0,PACAHARDIRQEN(r13)
+
 	/* Create a temp kernel stack for use before relocation is on.	*/
 	ld	r1,PACAEMERGSP(r13)
 	subi	r1,r1,STACK_FRAME_OVERHEAD
diff --git a/arch/powerpc/kernel/idle_power4.S b/arch/powerpc/kernel/idle_power4.S
index 5328709..ba31954 100644
--- a/arch/powerpc/kernel/idle_power4.S
+++ b/arch/powerpc/kernel/idle_power4.S
@@ -53,24 +53,3 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 	isync
 	b	1b
 
-_GLOBAL(power4_cpu_offline_powersave)
-	/* Go to NAP now */
-	mfmsr	r7
-	rldicl	r0,r7,48,1
-	rotldi	r0,r0,16
-	mtmsrd	r0,1			/* hard-disable interrupts */
-	li	r0,1
-	li	r6,0
-	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
-	stb	r6,PACASOFTIRQEN(r13)	/* soft-disable irqs */
-BEGIN_FTR_SECTION
-	DSSALL
-	sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-	ori	r7,r7,MSR_EE
-	oris	r7,r7,MSR_POW@h
-	sync
-	isync
-	mtmsrd	r7
-	isync
-	blr
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 53bee66..837989e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -916,18 +916,20 @@ static void pmac_cpu_die(void)
 	preempt_enable();
 
 	/*
-	 * hard-disable interrupts for the non-NAP case, the NAP code
-	 * needs to re-enable interrupts (but soft-disables them)
+	 * Re-enable interrupts. The NAP code needs to enable them
+	 * anyways, do it now so we deal with the case where one already
+	 * happened while soft-disabled.
+	 * We shouldn't get any external interrupts, only decrementer, and the
+	 * decrementer handler is safe for use on offline CPUs
 	 */
-	hard_irq_disable();
+	local_irq_enable();
 
 	while (1) {
 		/* let's not take timer interrupts too often ... */
 		set_dec(0x7fffffff);
 
-		/* should always be true at this point */
-		if (cpu_has_feature(CPU_FTR_CAN_NAP))
-			power4_cpu_offline_powersave();
+		/* Enter NAP mode */
+		power4_idle();
 	}
 }
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 14/18] powerpc/pmac/smp: Fix CPU hotplug crashes on some machines
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

On some machines that use i2c to synchronize the timebases (such
as PowerMac7,2/7,3 G5 machines), hotplug CPU would crash when
putting back a new CPU online due to the underlying i2c bus being
closed.

This uses the newly added bringup_done() callback to move the close
along with other housekeeping calls, and adds a CPU notifier to
re-open the i2c bus around subsequent hotplug operations

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |   71 +++++++++++++++++++++++++-------
 1 files changed, 55 insertions(+), 16 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 837989e..74a43c6 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -840,30 +840,68 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
 
 	/* Setup openpic */
 	mpic_setup_this_cpu();
+}
 
-	if (cpu_nr == 0) {
-#ifdef CONFIG_PPC64
-		extern void g5_phy_disable_cpu1(void);
+#ifdef CONFIG_HOTPLUG_CPU
+static int smp_core99_cpu_notify(struct notifier_block *self,
+				 unsigned long action, void *hcpu)
+{
+	int rc;
 
-		/* Close i2c bus if it was used for tb sync */
+	switch(action) {
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		/* Open i2c bus if it was used for tb sync */
 		if (pmac_tb_clock_chip_host) {
-			pmac_i2c_close(pmac_tb_clock_chip_host);
-			pmac_tb_clock_chip_host	= NULL;
+			rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
+			if (rc) {
+				pr_err("Failed to open i2c bus for time sync\n");
+				return notifier_from_errno(rc);
+			}
 		}
+		break;
+	case CPU_ONLINE:
+	case CPU_UP_CANCELED:
+		/* Close i2c bus if it was used for tb sync */
+		if (pmac_tb_clock_chip_host)
+			pmac_i2c_close(pmac_tb_clock_chip_host);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
 
-		/* If we didn't start the second CPU, we must take
-		 * it off the bus
-		 */
-		if (of_machine_is_compatible("MacRISC4") &&
-		    num_online_cpus() < 2)		
-			g5_phy_disable_cpu1();
-#endif /* CONFIG_PPC64 */
+static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
+	.notifier_call	= smp_core99_cpu_notify,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
 
-		if (ppc_md.progress)
-			ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+static void __init smp_core99_bringup_done(void)
+{
+#ifdef CONFIG_PPC64
+	extern void g5_phy_disable_cpu1(void);
+
+	/* Close i2c bus if it was used for tb sync */
+	if (pmac_tb_clock_chip_host)
+		pmac_i2c_close(pmac_tb_clock_chip_host);
+
+	/* If we didn't start the second CPU, we must take
+	 * it off the bus.
+	 */
+	if (of_machine_is_compatible("MacRISC4") &&
+	    num_online_cpus() < 2) {
+		set_cpu_present(1, false);
+		g5_phy_disable_cpu1();
 	}
-}
+#endif /* CONFIG_PPC64 */
 
+#ifdef CONFIG_HOTPLUG_CPU
+	register_cpu_notifier(&smp_core99_cpu_nb);
+#endif
+	if (ppc_md.progress)
+		ppc_md.progress("smp_core99_bringup_done", 0x349);
+}
 
 #ifdef CONFIG_HOTPLUG_CPU
 
@@ -940,6 +978,7 @@ static void pmac_cpu_die(void)
 struct smp_ops_t core99_smp_ops = {
 	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_core99_probe,
+	.bringup_done	= smp_core99_bringup_done,
 	.kick_cpu	= smp_core99_kick_cpu,
 	.setup_cpu	= smp_core99_setup_cpu,
 	.give_timebase	= smp_core99_give_timebase,
-- 
1.7.1

^ permalink raw reply related

* [PATCH 12/18] powerpc/pmac: Rename cpu_state in therm_pm72 to avoid collision
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

This collides with the cpu_state in our SMP code, use processor_state
instead.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 drivers/macintosh/therm_pm72.c |   60 ++++++++++++++++++++--------------------
 1 files changed, 30 insertions(+), 30 deletions(-)

diff --git a/drivers/macintosh/therm_pm72.c b/drivers/macintosh/therm_pm72.c
index f3a29f2..02b4f13 100644
--- a/drivers/macintosh/therm_pm72.c
+++ b/drivers/macintosh/therm_pm72.c
@@ -153,7 +153,7 @@ static struct i2c_adapter *		u3_0;
 static struct i2c_adapter *		u3_1;
 static struct i2c_adapter *		k2;
 static struct i2c_client *		fcu;
-static struct cpu_pid_state		cpu_state[2];
+static struct cpu_pid_state		processor_state[2];
 static struct basckside_pid_params	backside_params;
 static struct backside_pid_state	backside_state;
 static struct drives_pid_state		drives_state;
@@ -664,8 +664,8 @@ static int read_eeprom(int cpu, struct mpu_data *out)
 
 static void fetch_cpu_pumps_minmax(void)
 {
-	struct cpu_pid_state *state0 = &cpu_state[0];
-	struct cpu_pid_state *state1 = &cpu_state[1];
+	struct cpu_pid_state *state0 = &processor_state[0];
+	struct cpu_pid_state *state1 = &processor_state[1];
 	u16 pump_min = 0, pump_max = 0xffff;
 	u16 tmp[4];
 
@@ -717,17 +717,17 @@ static ssize_t show_##name(struct device *dev, struct device_attribute *attr, ch
 	return sprintf(buf, "%d", data);			\
 }
 
-BUILD_SHOW_FUNC_FIX(cpu0_temperature, cpu_state[0].last_temp)
-BUILD_SHOW_FUNC_FIX(cpu0_voltage, cpu_state[0].voltage)
-BUILD_SHOW_FUNC_FIX(cpu0_current, cpu_state[0].current_a)
-BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, cpu_state[0].rpm)
-BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, cpu_state[0].intake_rpm)
+BUILD_SHOW_FUNC_FIX(cpu0_temperature, processor_state[0].last_temp)
+BUILD_SHOW_FUNC_FIX(cpu0_voltage, processor_state[0].voltage)
+BUILD_SHOW_FUNC_FIX(cpu0_current, processor_state[0].current_a)
+BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, processor_state[0].rpm)
+BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, processor_state[0].intake_rpm)
 
-BUILD_SHOW_FUNC_FIX(cpu1_temperature, cpu_state[1].last_temp)
-BUILD_SHOW_FUNC_FIX(cpu1_voltage, cpu_state[1].voltage)
-BUILD_SHOW_FUNC_FIX(cpu1_current, cpu_state[1].current_a)
-BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, cpu_state[1].rpm)
-BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, cpu_state[1].intake_rpm)
+BUILD_SHOW_FUNC_FIX(cpu1_temperature, processor_state[1].last_temp)
+BUILD_SHOW_FUNC_FIX(cpu1_voltage, processor_state[1].voltage)
+BUILD_SHOW_FUNC_FIX(cpu1_current, processor_state[1].current_a)
+BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, processor_state[1].rpm)
+BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, processor_state[1].intake_rpm)
 
 BUILD_SHOW_FUNC_FIX(backside_temperature, backside_state.last_temp)
 BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
@@ -919,8 +919,8 @@ static void do_cpu_pid(struct cpu_pid_state *state, s32 temp, s32 power)
 
 static void do_monitor_cpu_combined(void)
 {
-	struct cpu_pid_state *state0 = &cpu_state[0];
-	struct cpu_pid_state *state1 = &cpu_state[1];
+	struct cpu_pid_state *state0 = &processor_state[0];
+	struct cpu_pid_state *state1 = &processor_state[1];
 	s32 temp0, power0, temp1, power1;
 	s32 temp_combi, power_combi;
 	int rc, intake, pump;
@@ -1150,7 +1150,7 @@ static void do_monitor_cpu_rack(struct cpu_pid_state *state)
 /*
  * Initialize the state structure for one CPU control loop
  */
-static int init_cpu_state(struct cpu_pid_state *state, int index)
+static int init_processor_state(struct cpu_pid_state *state, int index)
 {
 	int err;
 
@@ -1205,7 +1205,7 @@ static int init_cpu_state(struct cpu_pid_state *state, int index)
 /*
  * Dispose of the state data for one CPU control loop
  */
-static void dispose_cpu_state(struct cpu_pid_state *state)
+static void dispose_processor_state(struct cpu_pid_state *state)
 {
 	if (state->monitor == NULL)
 		return;
@@ -1804,9 +1804,9 @@ static int main_control_loop(void *x)
 		set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
 	/* Initialize ADCs */
-	initialize_adc(&cpu_state[0]);
-	if (cpu_state[1].monitor != NULL)
-		initialize_adc(&cpu_state[1]);
+	initialize_adc(&processor_state[0]);
+	if (processor_state[1].monitor != NULL)
+		initialize_adc(&processor_state[1]);
 
 	fcu_tickle_ticks = FCU_TICKLE_TICKS;
 
@@ -1833,14 +1833,14 @@ static int main_control_loop(void *x)
 		if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
 			do_monitor_cpu_combined();
 		else if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) {
-			do_monitor_cpu_rack(&cpu_state[0]);
-			if (cpu_state[1].monitor != NULL)
-				do_monitor_cpu_rack(&cpu_state[1]);
+			do_monitor_cpu_rack(&processor_state[0]);
+			if (processor_state[1].monitor != NULL)
+				do_monitor_cpu_rack(&processor_state[1]);
 			// better deal with UP
 		} else {
-			do_monitor_cpu_split(&cpu_state[0]);
-			if (cpu_state[1].monitor != NULL)
-				do_monitor_cpu_split(&cpu_state[1]);
+			do_monitor_cpu_split(&processor_state[0]);
+			if (processor_state[1].monitor != NULL)
+				do_monitor_cpu_split(&processor_state[1]);
 			// better deal with UP
 		}
 		/* Then, the rest */
@@ -1885,8 +1885,8 @@ static int main_control_loop(void *x)
  */
 static void dispose_control_loops(void)
 {
-	dispose_cpu_state(&cpu_state[0]);
-	dispose_cpu_state(&cpu_state[1]);
+	dispose_processor_state(&processor_state[0]);
+	dispose_processor_state(&processor_state[1]);
 	dispose_backside_state(&backside_state);
 	dispose_drives_state(&drives_state);
 	dispose_slots_state(&slots_state);
@@ -1928,12 +1928,12 @@ static int create_control_loops(void)
 	/* Create control loops for everything. If any fail, everything
 	 * fails
 	 */
-	if (init_cpu_state(&cpu_state[0], 0))
+	if (init_processor_state(&processor_state[0], 0))
 		goto fail;
 	if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
 		fetch_cpu_pumps_minmax();
 
-	if (cpu_count > 1 && init_cpu_state(&cpu_state[1], 1))
+	if (cpu_count > 1 && init_processor_state(&processor_state[1], 1))
 		goto fail;
 	if (init_backside_state(&backside_state))
 		goto fail;
-- 
1.7.1

^ permalink raw reply related

* [PATCH 17/18] powerpc/smp: Increase vdso_data->processorCount, not just decrease it
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/smp.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index e337073..6023395 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -551,6 +551,10 @@ void __devinit start_secondary(void *unused)
 
 	secondary_cpu_time_init();
 
+#ifdef CONFIG_PPC64
+	if (system_state == SYSTEM_RUNNING)
+		vdso_data->processorCount++;
+#endif
 	ipi_call_lock();
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
-- 
1.7.1

^ permalink raw reply related

* [PATCH 16/18] powerpc/smp: Create idle threads on demand and properly reset them
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Instead of creating idle threads at boot for all possible CPUs, we
create them on demand, like x86 or ARM, and we properly call init_idle
to re-initialize an idle thread when a CPU was unplugged and is now
re-plugged.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/smp.c |  100 +++++++++++++++++++++++++++++++++++----------
 1 files changed, 78 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 7beb001..e337073 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -57,6 +57,25 @@
 #define DBG(fmt...)
 #endif
 
+
+/* Store all idle threads, this can be reused instead of creating
+* a new thread. Also avoids complicated thread destroy functionality
+* for idle threads.
+*/
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
+ * removed after init for !CONFIG_HOTPLUG_CPU.
+ */
+static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
+#define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
+#define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+#else
+static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+#define get_idle_for_cpu(x)      (idle_thread_array[(x)])
+#define set_idle_for_cpu(x, p)   (idle_thread_array[(x)] = (p))
+#endif
+
 struct thread_info *secondary_ti;
 
 DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
@@ -238,23 +257,6 @@ static void __devinit smp_store_cpu_info(int id)
 	per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
 }
 
-static void __init smp_create_idle(unsigned int cpu)
-{
-	struct task_struct *p;
-
-	/* create a process for the processor */
-	p = fork_idle(cpu);
-	if (IS_ERR(p))
-		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-#ifdef CONFIG_PPC64
-	paca[cpu].__current = p;
-	paca[cpu].kstack = (unsigned long) task_thread_info(p)
-		+ THREAD_SIZE - STACK_FRAME_OVERHEAD;
-#endif
-	current_set[cpu] = task_thread_info(p);
-	task_thread_info(p)->cpu = cpu;
-}
-
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned int cpu;
@@ -288,10 +290,6 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 			max_cpus = NR_CPUS;
 	else
 		max_cpus = 1;
-
-	for_each_possible_cpu(cpu)
-		if (cpu != boot_cpuid)
-			smp_create_idle(cpu);
 }
 
 void __devinit smp_prepare_boot_cpu(void)
@@ -355,9 +353,62 @@ void generic_set_cpu_dead(unsigned int cpu)
 }
 #endif
 
+struct create_idle {
+	struct work_struct work;
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
+
+static void __cpuinit do_fork_idle(struct work_struct *work)
+{
+	struct create_idle *c_idle =
+		container_of(work, struct create_idle, work);
+
+	c_idle->idle = fork_idle(c_idle->cpu);
+	complete(&c_idle->done);
+}
+
+static int __cpuinit create_idle(unsigned int cpu)
+{
+	struct thread_info *ti;
+	struct create_idle c_idle = {
+		.cpu	= cpu,
+		.done	= COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+	};
+	INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
+
+	c_idle.idle = get_idle_for_cpu(cpu);
+
+	/* We can't use kernel_thread since we must avoid to
+	 * reschedule the child. We use a workqueue because
+	 * we want to fork from a kernel thread, not whatever
+	 * userspace process happens to be trying to online us.
+	 */
+	if (!c_idle.idle) {
+		schedule_work(&c_idle.work);
+		wait_for_completion(&c_idle.done);
+	} else
+		init_idle(c_idle.idle, cpu);
+	if (IS_ERR(c_idle.idle)) {		
+		pr_err("Failed fork for CPU %u: %li", cpu, PTR_ERR(c_idle.idle));
+		return PTR_ERR(c_idle.idle);
+	}
+	ti = task_thread_info(c_idle.idle);
+
+#ifdef CONFIG_PPC64
+	paca[cpu].__current = c_idle.idle;
+	paca[cpu].kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD;
+#endif
+	ti->cpu = cpu;
+	current_set[cpu] = ti;
+
+	return 0;
+}
+
 int __cpuinit __cpu_up(unsigned int cpu)
 {
-	int c;
+	int rc, c;
 
 	secondary_ti = current_set[cpu];
 
@@ -365,6 +416,11 @@ int __cpuinit __cpu_up(unsigned int cpu)
 	    (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
 		return -EINVAL;
 
+	/* Make sure we have an idle thread */
+	rc = create_idle(cpu);
+	if (rc)
+		return rc;
+
 	/* Make sure callin-map entry is 0 (can be leftover a CPU
 	 * hotplug
 	 */
-- 
1.7.1

^ permalink raw reply related

* [PATCH 18/18] powerpc/pmac/smp: Remove no-longer needed preempt workaround
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

The generic code properly re-initializes the preempt count in the
idle thread now

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |    7 -------
 1 files changed, 0 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index ce5b4f5..a830c5e 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -951,13 +951,6 @@ static void pmac_cpu_die(void)
 	smp_wmb();
 
 	/*
-	 * during the path that leads here preemption is disabled,
-	 * reenable it now so that when coming up preempt count is
-	 * zero correctly
-	 */
-	preempt_enable();
-
-	/*
 	 * Re-enable interrupts. The NAP code needs to enable them
 	 * anyways, do it now so we deal with the case where one already
 	 * happened while soft-disabled.
-- 
1.7.1

^ permalink raw reply related

* [PATCH 10/18] powerpc/pmac/smp: Remove HMT changes for PowerMac offline code
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Those instructions do nothing on non-threaded processors such
as 970's used on those machines.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/smp.c |    4 ----
 1 files changed, 0 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 50e15b4..53bee66 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -928,10 +928,6 @@ static void pmac_cpu_die(void)
 		/* should always be true at this point */
 		if (cpu_has_feature(CPU_FTR_CAN_NAP))
 			power4_cpu_offline_powersave();
-		else {
-			HMT_low();
-			HMT_very_low();
-		}
 	}
 }
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 13/18] powerpc/smp: Add a smp_ops->bringup_up() done callback
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

This allows us to stop abusing smp_ops->setup_cpu() for cleanup
tasks that have to take place after the initial boot time CPU
bringup.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/machdep.h |    1 +
 arch/powerpc/kernel/smp.c          |    4 ++++
 2 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/include/asm/machdep.h b/arch/powerpc/include/asm/machdep.h
index 578d330..e4f0191 100644
--- a/arch/powerpc/include/asm/machdep.h
+++ b/arch/powerpc/include/asm/machdep.h
@@ -35,6 +35,7 @@ struct smp_ops_t {
 	int   (*probe)(void);
 	void  (*kick_cpu)(int nr);
 	void  (*setup_cpu)(int nr);
+	void  (*bringup_done)(void);
 	void  (*take_timebase)(void);
 	void  (*give_timebase)(void);
 	int   (*cpu_disable)(void);
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index f6cc5c1..df37397 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -553,7 +553,11 @@ void __init smp_cpus_done(unsigned int max_cpus)
 
 	free_cpumask_var(old_mask);
 
+	if (smp_ops && smp_ops->bringup_done)
+		smp_ops->bringup_done();
+
 	dump_numa_cpu_topology();
+
 }
 
 int arch_sd_sibling_asym_packing(void)
-- 
1.7.1

^ permalink raw reply related

* [PATCHES] powerpc: Cleanup and fix CPU hotplug
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev

This series contain a number of cleanups and fixes to our CPU hotplug
code, including fixing crashes on G5 machines, properly re-initializing
idle threads etc...

Tested on PowerMac G5 and pSeries machines.

^ permalink raw reply

* [PATCH 15/18] powerpc/smp: Don't expose per-cpu "cpu_state" array
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Instead, keep it static, expose an accessor and use that from
the PowerMac code. Avoids easy namespace collisions and will
make it easier to consolidate with other implementations.

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h        |    2 +-
 arch/powerpc/kernel/smp.c             |    7 ++++++-
 arch/powerpc/platforms/powermac/smp.c |   12 ++++++++----
 3 files changed, 15 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 7e99771..a902a0d 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -45,7 +45,7 @@ extern void migrate_irqs(void);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
-DECLARE_PER_CPU(int, cpu_state);
+void generic_set_cpu_dead(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index df37397..7beb001 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -305,7 +305,7 @@ void __devinit smp_prepare_boot_cpu(void)
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* State of each CPU during hotplug phases */
-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -348,6 +348,11 @@ void generic_mach_cpu_die(void)
 	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
 		cpu_relax();
 }
+
+void generic_set_cpu_dead(unsigned int cpu)
+{
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+}
 #endif
 
 int __cpuinit __cpu_up(unsigned int cpu)
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index 74a43c6..ce5b4f5 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -920,10 +920,12 @@ static int smp_core99_cpu_disable(void)
 
 static void pmac_cpu_die(void)
 {
+	int cpu = smp_processor_id();
+
 	local_irq_disable();
 	idle_task_exit();
-	printk(KERN_DEBUG "CPU%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
+	pr_debug("CPU%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
 	smp_wmb();
 	mb();
 	low_cpu_die();
@@ -933,6 +935,8 @@ static void pmac_cpu_die(void)
 
 static void pmac_cpu_die(void)
 {
+	int cpu = smp_processor_id();
+
 	local_irq_disable();
 	idle_task_exit();
 
@@ -942,8 +946,8 @@ static void pmac_cpu_die(void)
 	 * on core99 platforms for now ...
 	 */
 
-	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
+	printk(KERN_INFO "CPU#%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
 	smp_wmb();
 
 	/*
-- 
1.7.1

^ permalink raw reply related

* [PATCH 02/18] powerpc/smp: soft-replugged CPUs must go back to start_secondary
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Various thing are torn down when a CPU is hot-unplugged. That CPU
is expected to go back to start_secondary when re-plugged to re
initialize everything, such as clock sources, maps, ...

Some implementations just return from cpu_die() callback
in the idle loop when the CPU is "re-plugged". This is not enough.

We fix it using a little asm trampoline which resets the stack
and calls back into start_secondary as if we were all fresh from
boot. The trampoline already existed on ppc64, but we add it for
ppc32

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h                  |    1 +
 arch/powerpc/kernel/head_32.S                   |    9 +++++++++
 arch/powerpc/kernel/smp.c                       |    9 +++++++--
 arch/powerpc/platforms/pseries/offline_states.h |    2 --
 4 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 66e237b..1de0e97 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -36,6 +36,7 @@ extern void cpu_die(void);
 
 extern void smp_send_debugger_break(int cpu);
 extern void smp_message_recv(int);
+extern void start_secondary_resume(void);
 
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
diff --git a/arch/powerpc/kernel/head_32.S b/arch/powerpc/kernel/head_32.S
index 98c4b29..c5c24be 100644
--- a/arch/powerpc/kernel/head_32.S
+++ b/arch/powerpc/kernel/head_32.S
@@ -890,6 +890,15 @@ __secondary_start:
 	mtspr	SPRN_SRR1,r4
 	SYNC
 	RFI
+
+_GLOBAL(start_secondary_resume)
+	/* Reset stack */
+	rlwinm	r1,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+	li	r3,0
+	std	r3,0(r1)		/* Zero the stack frame pointer	*/
+	bl	start_secondary
+	b	.
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 9813605..1c9956c 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -502,7 +502,7 @@ static struct device_node *cpu_to_l2cache(int cpu)
 }
 
 /* Activate a secondary processor. */
-int __devinit start_secondary(void *unused)
+void __devinit start_secondary(void *unused)
 {
 	unsigned int cpu = smp_processor_id();
 	struct device_node *l2_cache;
@@ -558,7 +558,8 @@ int __devinit start_secondary(void *unused)
 	local_irq_enable();
 
 	cpu_idle();
-	return 0;
+
+	BUG();
 }
 
 int setup_profiling_timer(unsigned int multiplier)
@@ -660,5 +661,9 @@ void cpu_die(void)
 {
 	if (ppc_md.cpu_die)
 		ppc_md.cpu_die();
+
+	/* If we return, we re-enter start_secondary */
+	start_secondary_resume();
 }
+
 #endif
diff --git a/arch/powerpc/platforms/pseries/offline_states.h b/arch/powerpc/platforms/pseries/offline_states.h
index 75a6f48..08672d9 100644
--- a/arch/powerpc/platforms/pseries/offline_states.h
+++ b/arch/powerpc/platforms/pseries/offline_states.h
@@ -34,6 +34,4 @@ static inline void set_default_offline_state(int cpu)
 #endif
 
 extern enum cpu_state_vals get_preferred_offline_state(int cpu);
-extern int start_secondary(void);
-extern void start_secondary_resume(void);
 #endif
-- 
1.7.1

^ permalink raw reply related

* [PATCH 07/18] powerpc/pmac/smp: Rename fixup_irqs() to migrate_irqs() and use it on ppc32
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/smp.h |    2 +-
 arch/powerpc/kernel/irq.c      |    3 ++-
 arch/powerpc/kernel/smp.c      |    2 +-
 3 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index 9fe5597..7e99771 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -41,7 +41,7 @@ extern void start_secondary_resume(void);
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
 #ifdef CONFIG_HOTPLUG_CPU
-extern void fixup_irqs(const struct cpumask *map);
+extern void migrate_irqs(void);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
index ce557f6..cab8654 100644
--- a/arch/powerpc/kernel/irq.c
+++ b/arch/powerpc/kernel/irq.c
@@ -303,12 +303,13 @@ u64 arch_irq_stat_cpu(unsigned int cpu)
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-void fixup_irqs(const struct cpumask *map)
+void migrate_irqs(void)
 {
 	struct irq_desc *desc;
 	unsigned int irq;
 	static int warned;
 	cpumask_var_t mask;
+	const struct cpumask *map = cpu_online_mask;
 
 	alloc_cpumask_var(&mask, GFP_KERNEL);
 
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index be7d728..f6cc5c1 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -317,8 +317,8 @@ int generic_cpu_disable(void)
 	set_cpu_online(cpu, false);
 #ifdef CONFIG_PPC64
 	vdso_data->processorCount--;
-	fixup_irqs(cpu_online_mask);
 #endif
+	migrate_irqs();
 	return 0;
 }
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 06/18] powerpc/pmac/smp: Fix 32-bit PowerMac cpu_die
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Use generic cpu_state, call idle_task_exit() properly, and
remove smp_core99_cpu_die() which isn't useful, the generic
function does the job just fine.
---
 arch/powerpc/include/asm/smp.h        |    1 +
 arch/powerpc/platforms/powermac/smp.c |   25 +++++--------------------
 2 files changed, 6 insertions(+), 20 deletions(-)

diff --git a/arch/powerpc/include/asm/smp.h b/arch/powerpc/include/asm/smp.h
index a629b6f..9fe5597 100644
--- a/arch/powerpc/include/asm/smp.h
+++ b/arch/powerpc/include/asm/smp.h
@@ -45,6 +45,7 @@ extern void fixup_irqs(const struct cpumask *map);
 int generic_cpu_disable(void);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
+DECLARE_PER_CPU(int, cpu_state);
 #endif
 
 #ifdef CONFIG_PPC64
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index ebd2b7e..e0ac7bb 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -880,31 +880,17 @@ int smp_core99_cpu_disable(void)
 	return 0;
 }
 
-static int cpu_dead[NR_CPUS];
-
 void pmac32_cpu_die(void)
 {
 	local_irq_disable();
-	cpu_dead[smp_processor_id()] = 1;
+	idle_task_exit();
+	printk(KERN_DEBUG "CPU%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
 	mb();
 	low_cpu_die();
 }
 
-void smp_core99_cpu_die(unsigned int cpu)
-{
-	int timeout;
-
-	timeout = 1000;
-	while (!cpu_dead[cpu]) {
-		if (--timeout == 0) {
-			printk("CPU %u refused to die!\n", cpu);
-			break;
-		}
-		msleep(1);
-	}
-	cpu_dead[cpu] = 0;
-}
-
 #endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
 
 /* Core99 Macs (dual G4s and G5s) */
@@ -918,12 +904,11 @@ struct smp_ops_t core99_smp_ops = {
 #if defined(CONFIG_HOTPLUG_CPU)
 # if defined(CONFIG_PPC32)
 	.cpu_disable	= smp_core99_cpu_disable,
-	.cpu_die	= smp_core99_cpu_die,
 # endif
 # if defined(CONFIG_PPC64)
 	.cpu_disable	= generic_cpu_disable,
-	.cpu_die	= generic_cpu_die,
 # endif
+	.cpu_die	= generic_cpu_die,
 #endif
 };
 
-- 
1.7.1

^ permalink raw reply related

* [PATCH 09/18] powerpc/pmac/smp: Consolidate 32-bit and 64-bit PowerMac cpu_die in one file
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/platforms/powermac/pmac.h  |    1 -
 arch/powerpc/platforms/powermac/setup.c |   56 -----------------------------
 arch/powerpc/platforms/powermac/smp.c   |   58 +++++++++++++++++++++++++++++--
 3 files changed, 55 insertions(+), 60 deletions(-)

diff --git a/arch/powerpc/platforms/powermac/pmac.h b/arch/powerpc/platforms/powermac/pmac.h
index f0bc08f..20468f4 100644
--- a/arch/powerpc/platforms/powermac/pmac.h
+++ b/arch/powerpc/platforms/powermac/pmac.h
@@ -33,7 +33,6 @@ extern void pmac_setup_pci_dma(void);
 extern void pmac_check_ht_link(void);
 
 extern void pmac_setup_smp(void);
-extern void pmac32_cpu_die(void);
 extern void low_cpu_die(void) __attribute__((noreturn));
 
 extern int pmac_nvram_init(void);
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index d5aceb7..aa45281 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -650,51 +650,6 @@ static int pmac_pci_probe_mode(struct pci_bus *bus)
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/* access per cpu vars from generic smp.c */
-DECLARE_PER_CPU(int, cpu_state);
-
-static void pmac64_cpu_die(void)
-{
-	/*
-	 * turn off as much as possible, we'll be
-	 * kicked out as this will only be invoked
-	 * on core99 platforms for now ...
-	 */
-
-	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
-	smp_wmb();
-
-	/*
-	 * during the path that leads here preemption is disabled,
-	 * reenable it now so that when coming up preempt count is
-	 * zero correctly
-	 */
-	preempt_enable();
-
-	/*
-	 * hard-disable interrupts for the non-NAP case, the NAP code
-	 * needs to re-enable interrupts (but soft-disables them)
-	 */
-	hard_irq_disable();
-
-	while (1) {
-		/* let's not take timer interrupts too often ... */
-		set_dec(0x7fffffff);
-
-		/* should always be true at this point */
-		if (cpu_has_feature(CPU_FTR_CAN_NAP))
-			power4_cpu_offline_powersave();
-		else {
-			HMT_low();
-			HMT_very_low();
-		}
-	}
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
 #endif /* CONFIG_PPC64 */
 
 define_machine(powermac) {
@@ -726,15 +681,4 @@ define_machine(powermac) {
 	.pcibios_after_init	= pmac_pcibios_after_init,
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
-#ifdef CONFIG_HOTPLUG_CPU
-#ifdef CONFIG_PPC64
-	.cpu_die		= pmac64_cpu_die,
-#endif
-#ifdef CONFIG_PPC32
-	.cpu_die		= pmac32_cpu_die,
-#endif
-#endif
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
-	.cpu_die		= generic_mach_cpu_die,
-#endif
 };
diff --git a/arch/powerpc/platforms/powermac/smp.c b/arch/powerpc/platforms/powermac/smp.c
index eda4709..50e15b4 100644
--- a/arch/powerpc/platforms/powermac/smp.c
+++ b/arch/powerpc/platforms/powermac/smp.c
@@ -865,7 +865,7 @@ static void __devinit smp_core99_setup_cpu(int cpu_nr)
 }
 
 
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
+#ifdef CONFIG_HOTPLUG_CPU
 
 static int smp_core99_cpu_disable(void)
 {
@@ -878,7 +878,9 @@ static int smp_core99_cpu_disable(void)
 	return 0;
 }
 
-void pmac32_cpu_die(void)
+#ifdef CONFIG_PPC32
+
+static void pmac_cpu_die(void)
 {
 	local_irq_disable();
 	idle_task_exit();
@@ -889,7 +891,52 @@ void pmac32_cpu_die(void)
 	low_cpu_die();
 }
 
-#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
+#else /* CONFIG_PPC32 */
+
+static void pmac_cpu_die(void)
+{
+	local_irq_disable();
+	idle_task_exit();
+
+	/*
+	 * turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ...
+	 */
+
+	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
+	__get_cpu_var(cpu_state) = CPU_DEAD;
+	smp_wmb();
+
+	/*
+	 * during the path that leads here preemption is disabled,
+	 * reenable it now so that when coming up preempt count is
+	 * zero correctly
+	 */
+	preempt_enable();
+
+	/*
+	 * hard-disable interrupts for the non-NAP case, the NAP code
+	 * needs to re-enable interrupts (but soft-disables them)
+	 */
+	hard_irq_disable();
+
+	while (1) {
+		/* let's not take timer interrupts too often ... */
+		set_dec(0x7fffffff);
+
+		/* should always be true at this point */
+		if (cpu_has_feature(CPU_FTR_CAN_NAP))
+			power4_cpu_offline_powersave();
+		else {
+			HMT_low();
+			HMT_very_low();
+		}
+	}
+}
+
+#endif /* else CONFIG_PPC32 */
+#endif /* CONFIG_HOTPLUG_CPU */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_smp_ops = {
@@ -933,5 +980,10 @@ void __init pmac_setup_smp(void)
 		smp_ops = &psurge_smp_ops;
 	}
 #endif /* CONFIG_PPC32 */
+
+#ifdef CONFIG_HOTPLUG_CPU
+	ppc_md.cpu_die = pmac_cpu_die;
+#endif
 }
 
+
-- 
1.7.1

^ permalink raw reply related

* [PATCH 01/18] powerpc: Make decrementer interrupt robust against offlined CPUs
From: Benjamin Herrenschmidt @ 2011-03-08  6:37 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1299566250-10516-1-git-send-email-benh@kernel.crashing.org>

With some implementations, it is possible that a timer interrupt
occurs every few seconds on an offline CPU. In this case, just
re-arm the decrementer and return immediately

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/kernel/time.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 09d31db..ecebc7c 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -577,14 +577,21 @@ void timer_interrupt(struct pt_regs * regs)
 	struct clock_event_device *evt = &decrementer->event;
 	u64 now;
 
+	/* Ensure a positive value is written to the decrementer, or else
+	 * some CPUs will continuue to take decrementer exceptions
+	 */
+	set_dec(DECREMENTER_MAX);
+
+	/* Some implementations of hotplug will get timer interrupts while
+	 * offline, just ignore these
+	 */
+	if (!cpu_online(smp_processor_id()))
+		return;
+
 	trace_timer_interrupt_entry(regs);
 
 	__get_cpu_var(irq_stat).timer_irqs++;
 
-	/* Ensure a positive value is written to the decrementer, or else
-	 * some CPUs will continuue to take decrementer exceptions */
-	set_dec(DECREMENTER_MAX);
-
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
-- 
1.7.1

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox