LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [v4,17/21] powerpc/8xx: set PTE bit 22 off TLBmiss
From: Scott Wood @ 2014-11-07  3:37 UTC (permalink / raw)
  To: LEROY Christophe; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <20140919083609.A92871AB040@localhost.localdomain>

On Fri, Sep 19, 2014 at 10:36:09AM +0200, LEROY Christophe wrote:
> No need to re-set this bit at each TLB miss. Let's set it in the PTE.
> 
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> ---
> Changes in v2:
> - None
> 
> Changes in v3:
> - Removed PPC405 related macro from PPC8xx specific code
> - PTE_NONE_MASK doesn't need PAGE_ACCESSED in Linux 2.6
> 
> Changes in v4:
> - None
> 
>  arch/powerpc/include/asm/pgtable-ppc32.h | 20 ++++++++++++++++++++
>  arch/powerpc/include/asm/pte-8xx.h       |  7 +++++--
>  arch/powerpc/kernel/head_8xx.S           | 10 ++--------
>  3 files changed, 27 insertions(+), 10 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
> index 47edde8..35a9b44 100644
> --- a/arch/powerpc/include/asm/pgtable-ppc32.h
> +++ b/arch/powerpc/include/asm/pgtable-ppc32.h
> @@ -172,6 +172,25 @@ static inline unsigned long pte_update(pte_t *p,
>  #ifdef PTE_ATOMIC_UPDATES
>  	unsigned long old, tmp;
>  
> +#ifdef CONFIG_PPC_8xx
> +	unsigned long tmp2;
> +
> +	__asm__ __volatile__("\
> +1:	lwarx	%0,0,%4\n\
> +	andc	%1,%0,%5\n\
> +	or	%1,%1,%6\n\
> +	/* 0x200 == Extended encoding, bit 22 */ \
> +	/* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \
> +	rlwimi	%1,%1,32-2,0x200\n /* get _PAGE_USER */ \
> +	rlwinm	%3,%1,32-1,0x200\n /* get _PAGE_RW */ \
> +	or	%1,%3,%1\n\
> +	xori	%1,%1,0x200\n"
> +"	stwcx.	%1,0,%4\n\
> +	bne-	1b"

Why do you need this...

> diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
> index d44826e..daa4616 100644
> --- a/arch/powerpc/include/asm/pte-8xx.h
> +++ b/arch/powerpc/include/asm/pte-8xx.h
> @@ -48,19 +48,22 @@
>   */
>  #define _PAGE_RW	0x0400	/* lsb PP bits, inverted in HW */
>  #define _PAGE_USER	0x0800	/* msb PP bits */
> +/* set when neither _PAGE_USER nor _PAGE_RW are set */
> +#define _PAGE_KNLRO	0x0200
>  
>  #define _PMD_PRESENT	0x0001
>  #define _PMD_BAD	0x0ff0
>  #define _PMD_PAGE_MASK	0x000c
>  #define _PMD_PAGE_8M	0x000c
>  
> -#define _PTE_NONE_MASK _PAGE_ACCESSED
> +#define _PTE_NONE_MASK _PAGE_KNLRO
>  
>  /* Until my rework is finished, 8xx still needs atomic PTE updates */
>  #define PTE_ATOMIC_UPDATES	1
>  
>  /* We need to add _PAGE_SHARED to kernel pages */
> -#define _PAGE_KERNEL_RO	(_PAGE_SHARED)
> +#define _PAGE_KERNEL_RO	(_PAGE_SHARED | _PAGE_KNLRO)
> +#define _PAGE_KERNEL_ROX	(_PAGE_EXEC | _PAGE_KNLRO)
>  #define _PAGE_KERNEL_RW	(_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)

...if 0x200 is already being set in the PTE here?

-Scott

^ permalink raw reply

* Re: powerpc/8xx: Remove Kconfig symbol FADS
From: Scott Wood @ 2014-11-07  3:50 UTC (permalink / raw)
  To: Paul Bolle; +Cc: linux-kernel, Paul Mackerras, linuxppc-dev
In-Reply-To: <1411545979.19525.5.camel@x220>

On Wed, Sep 24, 2014 at 10:06:19AM +0200, Paul Bolle wrote:
> Commit 39eb56da2b53 ("pcmcia: Remove m8xx_pcmcia driver") removed the
> only driver that used CONFIG_FADS. Setting the Kconfig symbol FADS is
> pointless since that commit. Remove it.
> 
> Signed-off-by: Paul Bolle <pebolle@tiscali.nl>
> ---
> Done on top of next-20140923. Tested with "git grep" only.
> 
> Another cleanup might be to remove MPC8XXFADS (or "FADS") from the "8xx
> Machine Type" choice. Is there any reason left to pick "FADS" as a
> machine type?

Nothing references MPC8XXFADS, so yes, it can be removed.

-Scott

^ permalink raw reply

* Re: [PATCH v2 0/3] fix a kernel panic on fsl corenet board when CONFIG_CLK_PPC_CORENET is enabled
From: Scott Wood @ 2014-11-07  4:07 UTC (permalink / raw)
  To: Kevin Hao; +Cc: Mike Turquette, Gerhard Sittig, Jingchang Lu, linuxppc-dev
In-Reply-To: <1413699099-25743-1-git-send-email-haokexin@gmail.com>

On Sun, 2014-10-19 at 14:11 +0800, Kevin Hao wrote:
> Hi,
> 
> I have done a boot test on p2014rdb and t4240qds boards. I don't have an access
> to mpc512x board, so only build test for that.
> 
> v2:
>  - Revert the commit da788acb2838 first.
>  - Invoke of_clk_init() from a common place.
> 
> v1
> This tries to fix a kernel panic introduced by commit da788acb2838
> ("clk: ppc-corenet: Fix Section mismatch warning").
> 
> Kevin Hao (3):
>   Revert "clk: ppc-corenet: Fix Section mismatch warning"
>   powerpc: call of_clk_init() from time_init()
>   clk: ppc-corenet: fix section mismatch warning
> 
>  arch/powerpc/kernel/time.c                    |  5 ++++
>  arch/powerpc/platforms/512x/clock-commonclk.c | 11 ++++---
>  drivers/clk/clk-ppc-corenet.c                 | 43 ++++-----------------------
>  3 files changed, 16 insertions(+), 43 deletions(-)
> 

Acked-by: Scott Wood <scottwood@freescale.com>

Whose tree should this go through?

-Scott

^ permalink raw reply

* Re: [PATCH v3 1/4] dt/bindings: Introduce the FSL QorIQ DPAA BMan
From: Emil Medve @ 2014-11-07  7:31 UTC (permalink / raw)
  To: Scott Wood
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	Geoff.Thorpe, corbet, linux-doc, linuxppc-dev, robh+dt, galak,
	grant.likely
In-Reply-To: <1415310579.23458.402.camel@snotra.buserror.net>

Hello Scott,


On 11/06/2014 03:49 PM, Scott Wood wrote:
> On Wed, 2014-11-05 at 09:18 -0600, Emil Medve wrote:
>> +Devices connected to a BMan instance via Direct Connect Portals (DCP) must link
>> +to the respective BMan instance
>> +
>> +- fsl,bman
>> +	Usage:		Required
>> +	Value type:	<prop-encoded-array>
>> +	Description:	List of phandle and DCP index pairs, to the BMan instance
>> +			to which this device is connected via the DCP
> 
> Does software need the DCP index (though for QMan there do seem to be a
> few registers associated with each DCP)?  Where can I find that info in
> the manual?

The DCP index helps describe the topology of the devices connected to
the B/QMan. One might be tempted to use some address to reference said
DCP, unfortunately the pertinent registers/bits for said DCP(s) are not
into a compact region. Look at the CCSR memory map for B/QMan

In the QMan case things are marginally better. For each hardware portal
there are a handful of (vaguely named *DCx*, *DCPx* or *DCP*) registers
(configuration, performance monitoring and debugging). However, still
registers and bits spread here and there

In the BMan case things are a bit worse as the registers names are less
friendly and still spread around

Do you need specific names/offsets?


Cheers,

^ permalink raw reply

* Re: [PATCH v3 1/4] dt/bindings: Introduce the FSL QorIQ DPAA BMan
From: Scott Wood @ 2014-11-07  7:34 UTC (permalink / raw)
  To: Emil Medve
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	Geoff.Thorpe, corbet, linux-doc, linuxppc-dev, robh+dt, galak,
	grant.likely
In-Reply-To: <545C754C.9080700@Freescale.com>

On Fri, 2014-11-07 at 01:31 -0600, Emil Medve wrote:
> Hello Scott,
> 
> 
> On 11/06/2014 03:49 PM, Scott Wood wrote:
> > On Wed, 2014-11-05 at 09:18 -0600, Emil Medve wrote:
> >> +Devices connected to a BMan instance via Direct Connect Portals (DCP) must link
> >> +to the respective BMan instance
> >> +
> >> +- fsl,bman
> >> +	Usage:		Required
> >> +	Value type:	<prop-encoded-array>
> >> +	Description:	List of phandle and DCP index pairs, to the BMan instance
> >> +			to which this device is connected via the DCP
> > 
> > Does software need the DCP index (though for QMan there do seem to be a
> > few registers associated with each DCP)?  Where can I find that info in
> > the manual?
> 
> The DCP index helps describe the topology of the devices connected to
> the B/QMan. One might be tempted to use some address to reference said
> DCP, unfortunately the pertinent registers/bits for said DCP(s) are not
> into a compact region. Look at the CCSR memory map for B/QMan
> 
> In the QMan case things are marginally better. For each hardware portal
> there are a handful of (vaguely named *DCx*, *DCPx* or *DCP*) registers
> (configuration, performance monitoring and debugging). However, still
> registers and bits spread here and there
> 
> In the BMan case things are a bit worse as the registers names are less
> friendly and still spread around
> 
> Do you need specific names/offsets?

My question about the manual wasn't rhetorical -- I tried to find this
information and couldn't.

-Scott

^ permalink raw reply

* Re: [v4,17/21] powerpc/8xx: set PTE bit 22 off TLBmiss
From: leroy christophe @ 2014-11-07  8:00 UTC (permalink / raw)
  To: Scott Wood; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <20141107033745.GA23796@home.buserror.net>


Le 07/11/2014 04:37, Scott Wood a écrit :
> On Fri, Sep 19, 2014 at 10:36:09AM +0200, LEROY Christophe wrote:
>> No need to re-set this bit at each TLB miss. Let's set it in the PTE.
>>
>> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>> ---
>> Changes in v2:
>> - None
>>
>> Changes in v3:
>> - Removed PPC405 related macro from PPC8xx specific code
>> - PTE_NONE_MASK doesn't need PAGE_ACCESSED in Linux 2.6
>>
>> Changes in v4:
>> - None
>>
>>   arch/powerpc/include/asm/pgtable-ppc32.h | 20 ++++++++++++++++++++
>>   arch/powerpc/include/asm/pte-8xx.h       |  7 +++++--
>>   arch/powerpc/kernel/head_8xx.S           | 10 ++--------
>>   3 files changed, 27 insertions(+), 10 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
>> index 47edde8..35a9b44 100644
>> --- a/arch/powerpc/include/asm/pgtable-ppc32.h
>> +++ b/arch/powerpc/include/asm/pgtable-ppc32.h
>> @@ -172,6 +172,25 @@ static inline unsigned long pte_update(pte_t *p,
>>   #ifdef PTE_ATOMIC_UPDATES
>>   	unsigned long old, tmp;
>>   
>> +#ifdef CONFIG_PPC_8xx
>> +	unsigned long tmp2;
>> +
>> +	__asm__ __volatile__("\
>> +1:	lwarx	%0,0,%4\n\
>> +	andc	%1,%0,%5\n\
>> +	or	%1,%1,%6\n\
>> +	/* 0x200 == Extended encoding, bit 22 */ \
>> +	/* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \
>> +	rlwimi	%1,%1,32-2,0x200\n /* get _PAGE_USER */ \
>> +	rlwinm	%3,%1,32-1,0x200\n /* get _PAGE_RW */ \
>> +	or	%1,%3,%1\n\
>> +	xori	%1,%1,0x200\n"
>> +"	stwcx.	%1,0,%4\n\
>> +	bne-	1b"
> Why do you need this...
>
>> diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
>> index d44826e..daa4616 100644
>> --- a/arch/powerpc/include/asm/pte-8xx.h
>> +++ b/arch/powerpc/include/asm/pte-8xx.h
>> @@ -48,19 +48,22 @@
>>    */
>>   #define _PAGE_RW	0x0400	/* lsb PP bits, inverted in HW */
>>   #define _PAGE_USER	0x0800	/* msb PP bits */
>> +/* set when neither _PAGE_USER nor _PAGE_RW are set */
>> +#define _PAGE_KNLRO	0x0200
>>   
>>   #define _PMD_PRESENT	0x0001
>>   #define _PMD_BAD	0x0ff0
>>   #define _PMD_PAGE_MASK	0x000c
>>   #define _PMD_PAGE_8M	0x000c
>>   
>> -#define _PTE_NONE_MASK _PAGE_ACCESSED
>> +#define _PTE_NONE_MASK _PAGE_KNLRO
>>   
>>   /* Until my rework is finished, 8xx still needs atomic PTE updates */
>>   #define PTE_ATOMIC_UPDATES	1
>>   
>>   /* We need to add _PAGE_SHARED to kernel pages */
>> -#define _PAGE_KERNEL_RO	(_PAGE_SHARED)
>> +#define _PAGE_KERNEL_RO	(_PAGE_SHARED | _PAGE_KNLRO)
>> +#define _PAGE_KERNEL_ROX	(_PAGE_EXEC | _PAGE_KNLRO)
>>   #define _PAGE_KERNEL_RW	(_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
> ...if 0x200 is already being set in the PTE here?
>
If I understand well the way it works, those defines are used for 
setting the PTE the first time.
Then, pte_update() is used to modify the pte settings on an existing pte

0x200 must be set when and only when the page is a RO kernel page. If 
later on pte_update() is called for instance to set the page to RW, the 
0x200 has to be removed. Same, if pte_update() is called to remove 
_PAGE_RW (ptep_set_wrprotect() does this), 0x200 must be set back.

Christophe

^ permalink raw reply

* Re: [PATCH v3 1/4] dt/bindings: Introduce the FSL QorIQ DPAA BMan
From: Emil Medve @ 2014-11-07  8:14 UTC (permalink / raw)
  To: Scott Wood
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	Geoff.Thorpe, corbet, linux-doc, linuxppc-dev, robh+dt, galak,
	grant.likely
In-Reply-To: <1415345665.23458.428.camel@snotra.buserror.net>

Hello Scott,


On 11/07/2014 01:34 AM, Scott Wood wrote:
> On Fri, 2014-11-07 at 01:31 -0600, Emil Medve wrote:
>> Hello Scott,
>>
>>
>> On 11/06/2014 03:49 PM, Scott Wood wrote:
>>> On Wed, 2014-11-05 at 09:18 -0600, Emil Medve wrote:
>>>> +Devices connected to a BMan instance via Direct Connect Portals (DCP) must link
>>>> +to the respective BMan instance
>>>> +
>>>> +- fsl,bman
>>>> +	Usage:		Required
>>>> +	Value type:	<prop-encoded-array>
>>>> +	Description:	List of phandle and DCP index pairs, to the BMan instance
>>>> +			to which this device is connected via the DCP
>>>
>>> Does software need the DCP index (though for QMan there do seem to be a
>>> few registers associated with each DCP)?  Where can I find that info in
>>> the manual?
>>
>> The DCP index helps describe the topology of the devices connected to
>> the B/QMan. One might be tempted to use some address to reference said
>> DCP, unfortunately the pertinent registers/bits for said DCP(s) are not
>> into a compact region. Look at the CCSR memory map for B/QMan
>>
>> In the QMan case things are marginally better. For each hardware portal
>> there are a handful of (vaguely named *DCx*, *DCPx* or *DCP*) registers
>> (configuration, performance monitoring and debugging). However, still
>> registers and bits spread here and there
>>
>> In the BMan case things are a bit worse as the registers names are less
>> friendly and still spread around
>>
>> Do you need specific names/offsets?
> 
> My question about the manual wasn't rhetorical -- I tried to find this
> information and couldn't.

I get that. As I said, the registers/bits are spread around in the CCSR
space of each block and not named excessively friendly. As such I hinted
for some search patterns to make it easier to find them. In order to
progress the review I'm willing to prepare a list. Just let me know


Cheers,

^ permalink raw reply

* Re: [PATCH v3 1/4] dt/bindings: Introduce the FSL QorIQ DPAA BMan
From: Scott Wood @ 2014-11-07  8:19 UTC (permalink / raw)
  To: Emil Medve
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	Geoff.Thorpe, corbet, linux-doc, linuxppc-dev, robh+dt, galak,
	grant.likely
In-Reply-To: <545C7F77.90200@Freescale.com>

On Fri, 2014-11-07 at 02:14 -0600, Emil Medve wrote:
> Hello Scott,
> 
> 
> On 11/07/2014 01:34 AM, Scott Wood wrote:
> > On Fri, 2014-11-07 at 01:31 -0600, Emil Medve wrote:
> >> Hello Scott,
> >>
> >>
> >> On 11/06/2014 03:49 PM, Scott Wood wrote:
> >>> On Wed, 2014-11-05 at 09:18 -0600, Emil Medve wrote:
> >>>> +Devices connected to a BMan instance via Direct Connect Portals (DCP) must link
> >>>> +to the respective BMan instance
> >>>> +
> >>>> +- fsl,bman
> >>>> +	Usage:		Required
> >>>> +	Value type:	<prop-encoded-array>
> >>>> +	Description:	List of phandle and DCP index pairs, to the BMan instance
> >>>> +			to which this device is connected via the DCP
> >>>
> >>> Does software need the DCP index (though for QMan there do seem to be a
> >>> few registers associated with each DCP)?  Where can I find that info in
> >>> the manual?
> >>
> >> The DCP index helps describe the topology of the devices connected to
> >> the B/QMan. One might be tempted to use some address to reference said
> >> DCP, unfortunately the pertinent registers/bits for said DCP(s) are not
> >> into a compact region. Look at the CCSR memory map for B/QMan
> >>
> >> In the QMan case things are marginally better. For each hardware portal
> >> there are a handful of (vaguely named *DCx*, *DCPx* or *DCP*) registers
> >> (configuration, performance monitoring and debugging). However, still
> >> registers and bits spread here and there
> >>
> >> In the BMan case things are a bit worse as the registers names are less
> >> friendly and still spread around
> >>
> >> Do you need specific names/offsets?
> > 
> > My question about the manual wasn't rhetorical -- I tried to find this
> > information and couldn't.
> 
> I get that. As I said, the registers/bits are spread around in the CCSR
> space of each block and not named excessively friendly. As such I hinted
> for some search patterns to make it easier to find them. In order to
> progress the review I'm willing to prepare a list. Just let me know

Could you point me to the section of the manual where this information
is -- friendly or otherwise?  I saw the QMan direct connect portal
registers.  I didn't see how to tell which <i> in DCPi_xxx goes with
which device.

-Scott

^ permalink raw reply

* Re: powerpc/8xx: Remove Kconfig symbol FADS
From: Paul Bolle @ 2014-11-07  8:48 UTC (permalink / raw)
  To: Scott Wood; +Cc: linux-kernel, Paul Mackerras, linuxppc-dev
In-Reply-To: <20141107035008.GA25204@home.buserror.net>

On Thu, 2014-11-06 at 21:50 -0600, Scott Wood wrote:
> On Wed, Sep 24, 2014 at 10:06:19AM +0200, Paul Bolle wrote: 
> > Another cleanup might be to remove MPC8XXFADS (or "FADS") from the "8xx
> > Machine Type" choice. Is there any reason left to pick "FADS" as a
> > machine type?
> 
> Nothing references MPC8XXFADS, so yes, it can be removed.

I'll try to look into this. For the (verbose) reasons below I'll do that
in a separate patch, if I ever get that far. What follows is mostly a
note to self.

MPC8XXFADS is indeed not referenced anywhere. But it's one of the
entries in the "8xx Machine Type" choice. And it's common for choice
blocks the have a "none of the above" entry. Ie, an entry that allows to
configure nothing. There's a chance MPC8XXFADS is currently used for
that role. (This is easier to determine for people that - unlike me -
know what all the symbols in this choice mean. To me they 're basically
random strings.)

Actually, there's an obscure "optional" Kconfig keyword that appears to
be added to take care of this use case. It's currently used exactly
twice in the tree, in smaller architectures: once in arch/avr32/ and
once in arch/sh/. This implies this "optional" keyword is used very
little. I'll have to look carefully to see whether it works as
advertised.


Paul Bolle

^ permalink raw reply

* Re: [PATCH v3 1/4] dt/bindings: Introduce the FSL QorIQ DPAA BMan
From: Emil Medve @ 2014-11-07  9:38 UTC (permalink / raw)
  To: Scott Wood
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	Geoff.Thorpe, corbet, linux-doc, linuxppc-dev, robh+dt, galak,
	grant.likely
In-Reply-To: <1415348363.23458.432.camel@snotra.buserror.net>

Hello Scott,


On 11/07/2014 02:19 AM, Scott Wood wrote:
> On Fri, 2014-11-07 at 02:14 -0600, Emil Medve wrote:
>> Hello Scott,
>>
>>
>> On 11/07/2014 01:34 AM, Scott Wood wrote:
>>> On Fri, 2014-11-07 at 01:31 -0600, Emil Medve wrote:
>>>> Hello Scott,
>>>>
>>>>
>>>> On 11/06/2014 03:49 PM, Scott Wood wrote:
>>>>> On Wed, 2014-11-05 at 09:18 -0600, Emil Medve wrote:
>>>>>> +Devices connected to a BMan instance via Direct Connect Portals (DCP) must link
>>>>>> +to the respective BMan instance
>>>>>> +
>>>>>> +- fsl,bman
>>>>>> +	Usage:		Required
>>>>>> +	Value type:	<prop-encoded-array>
>>>>>> +	Description:	List of phandle and DCP index pairs, to the BMan instance
>>>>>> +			to which this device is connected via the DCP
>>>>>
>>>>> Does software need the DCP index (though for QMan there do seem to be a
>>>>> few registers associated with each DCP)?  Where can I find that info in
>>>>> the manual?
>>>>
>>>> The DCP index helps describe the topology of the devices connected to
>>>> the B/QMan. One might be tempted to use some address to reference said
>>>> DCP, unfortunately the pertinent registers/bits for said DCP(s) are not
>>>> into a compact region. Look at the CCSR memory map for B/QMan
>>>>
>>>> In the QMan case things are marginally better. For each hardware portal
>>>> there are a handful of (vaguely named *DCx*, *DCPx* or *DCP*) registers
>>>> (configuration, performance monitoring and debugging). However, still
>>>> registers and bits spread here and there
>>>>
>>>> In the BMan case things are a bit worse as the registers names are less
>>>> friendly and still spread around
>>>>
>>>> Do you need specific names/offsets?
>>>
>>> My question about the manual wasn't rhetorical -- I tried to find this
>>> information and couldn't.
>>
>> I get that. As I said, the registers/bits are spread around in the CCSR
>> space of each block and not named excessively friendly. As such I hinted
>> for some search patterns to make it easier to find them. In order to
>> progress the review I'm willing to prepare a list. Just let me know
> 
> Could you point me to the section of the manual where this information
> is -- friendly or otherwise?  I saw the QMan direct connect portal
> registers.  I didn't see how to tell which <i> in DCPi_xxx goes with
> which device.

For QMan look into section '6.3.10 Direct Connect Portals (DCPs)'. The
BMan DCP assignment is the same


Cheers,

^ permalink raw reply

* Re: [PATCH v3 1/4] dt/bindings: Introduce the FSL QorIQ DPAA BMan
From: Scott Wood @ 2014-11-07 16:49 UTC (permalink / raw)
  To: Emil Medve
  Cc: mark.rutland, devicetree, pawel.moll, ijc+devicetree,
	Geoff.Thorpe, corbet, linux-doc, linuxppc-dev, robh+dt, galak,
	grant.likely
In-Reply-To: <545C9302.50703@Freescale.com>

On Fri, 2014-11-07 at 03:38 -0600, Emil Medve wrote:
> Hello Scott,
> 
> 
> On 11/07/2014 02:19 AM, Scott Wood wrote:
> > On Fri, 2014-11-07 at 02:14 -0600, Emil Medve wrote:
> >> Hello Scott,
> >>
> >>
> >> On 11/07/2014 01:34 AM, Scott Wood wrote:
> >>> On Fri, 2014-11-07 at 01:31 -0600, Emil Medve wrote:
> >>>> Hello Scott,
> >>>>
> >>>>
> >>>> On 11/06/2014 03:49 PM, Scott Wood wrote:
> >>>>> On Wed, 2014-11-05 at 09:18 -0600, Emil Medve wrote:
> >>>>>> +Devices connected to a BMan instance via Direct Connect Portals (DCP) must link
> >>>>>> +to the respective BMan instance
> >>>>>> +
> >>>>>> +- fsl,bman
> >>>>>> +	Usage:		Required
> >>>>>> +	Value type:	<prop-encoded-array>
> >>>>>> +	Description:	List of phandle and DCP index pairs, to the BMan instance
> >>>>>> +			to which this device is connected via the DCP
> >>>>>
> >>>>> Does software need the DCP index (though for QMan there do seem to be a
> >>>>> few registers associated with each DCP)?  Where can I find that info in
> >>>>> the manual?
> >>>>
> >>>> The DCP index helps describe the topology of the devices connected to
> >>>> the B/QMan. One might be tempted to use some address to reference said
> >>>> DCP, unfortunately the pertinent registers/bits for said DCP(s) are not
> >>>> into a compact region. Look at the CCSR memory map for B/QMan
> >>>>
> >>>> In the QMan case things are marginally better. For each hardware portal
> >>>> there are a handful of (vaguely named *DCx*, *DCPx* or *DCP*) registers
> >>>> (configuration, performance monitoring and debugging). However, still
> >>>> registers and bits spread here and there
> >>>>
> >>>> In the BMan case things are a bit worse as the registers names are less
> >>>> friendly and still spread around
> >>>>
> >>>> Do you need specific names/offsets?
> >>>
> >>> My question about the manual wasn't rhetorical -- I tried to find this
> >>> information and couldn't.
> >>
> >> I get that. As I said, the registers/bits are spread around in the CCSR
> >> space of each block and not named excessively friendly. As such I hinted
> >> for some search patterns to make it easier to find them. In order to
> >> progress the review I'm willing to prepare a list. Just let me know
> > 
> > Could you point me to the section of the manual where this information
> > is -- friendly or otherwise?  I saw the QMan direct connect portal
> > registers.  I didn't see how to tell which <i> in DCPi_xxx goes with
> > which device.
> 
> For QMan look into section '6.3.10 Direct Connect Portals (DCPs)'. The
> BMan DCP assignment is the same

Thanks, I'm not sure how I missed that.

-Scott

^ permalink raw reply

* Re: [PATCH net-next] PPC: bpf_jit_comp: add SKF_AD_HATYPE instruction
From: David Miller @ 2014-11-07 19:50 UTC (permalink / raw)
  To: kda; +Cc: felix, netdev, dborkman, alexei.starovoitov, linuxppc-dev
In-Reply-To: <1415253755-4001-1-git-send-email-kda@linux-powerpc.org>

From: Denis Kirjanov <kda@linux-powerpc.org>
Date: Thu,  6 Nov 2014 09:02:35 +0300

> Add BPF extension SKF_AD_HATYPE to ppc JIT to check
> the hw type of the interface
> 
> JIT off:
> [   69.106783] test_bpf: #20 LD_HATYPE 48 48 PASS
> JIT on:
> [   64.721757] test_bpf: #20 LD_HATYPE 7 6 PASS
> 
> CC: Alexei Starovoitov<alexei.starovoitov@gmail.com>
> CC: Daniel Borkmann<dborkman@redhat.com>
> CC: Philippe Bergheaud<felix@linux.vnet.ibm.com>
> Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>

Can I get some reviews please?

Thanks.

^ permalink raw reply

* Re: [v4,17/21] powerpc/8xx: set PTE bit 22 off TLBmiss
From: Scott Wood @ 2014-11-08  0:08 UTC (permalink / raw)
  To: leroy christophe; +Cc: Paul Mackerras, linuxppc-dev, linux-kernel
In-Reply-To: <545C7C2E.3060109@c-s.fr>

On Fri, 2014-11-07 at 09:00 +0100, leroy christophe wrote:
> Le 07/11/2014 04:37, Scott Wood a écrit :
> > On Fri, Sep 19, 2014 at 10:36:09AM +0200, LEROY Christophe wrote:
> >> No need to re-set this bit at each TLB miss. Let's set it in the PTE.
> >>
> >> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> >> ---
> >> Changes in v2:
> >> - None
> >>
> >> Changes in v3:
> >> - Removed PPC405 related macro from PPC8xx specific code
> >> - PTE_NONE_MASK doesn't need PAGE_ACCESSED in Linux 2.6
> >>
> >> Changes in v4:
> >> - None
> >>
> >>   arch/powerpc/include/asm/pgtable-ppc32.h | 20 ++++++++++++++++++++
> >>   arch/powerpc/include/asm/pte-8xx.h       |  7 +++++--
> >>   arch/powerpc/kernel/head_8xx.S           | 10 ++--------
> >>   3 files changed, 27 insertions(+), 10 deletions(-)
> >>
> >> diff --git a/arch/powerpc/include/asm/pgtable-ppc32.h b/arch/powerpc/include/asm/pgtable-ppc32.h
> >> index 47edde8..35a9b44 100644
> >> --- a/arch/powerpc/include/asm/pgtable-ppc32.h
> >> +++ b/arch/powerpc/include/asm/pgtable-ppc32.h
> >> @@ -172,6 +172,25 @@ static inline unsigned long pte_update(pte_t *p,
> >>   #ifdef PTE_ATOMIC_UPDATES
> >>   	unsigned long old, tmp;
> >>   
> >> +#ifdef CONFIG_PPC_8xx
> >> +	unsigned long tmp2;
> >> +
> >> +	__asm__ __volatile__("\
> >> +1:	lwarx	%0,0,%4\n\
> >> +	andc	%1,%0,%5\n\
> >> +	or	%1,%1,%6\n\
> >> +	/* 0x200 == Extended encoding, bit 22 */ \
> >> +	/* Bit 22 has to be 1 if neither _PAGE_USER nor _PAGE_RW are set */ \
> >> +	rlwimi	%1,%1,32-2,0x200\n /* get _PAGE_USER */ \
> >> +	rlwinm	%3,%1,32-1,0x200\n /* get _PAGE_RW */ \
> >> +	or	%1,%3,%1\n\
> >> +	xori	%1,%1,0x200\n"
> >> +"	stwcx.	%1,0,%4\n\
> >> +	bne-	1b"
> > Why do you need this...
> >
> >> diff --git a/arch/powerpc/include/asm/pte-8xx.h b/arch/powerpc/include/asm/pte-8xx.h
> >> index d44826e..daa4616 100644
> >> --- a/arch/powerpc/include/asm/pte-8xx.h
> >> +++ b/arch/powerpc/include/asm/pte-8xx.h
> >> @@ -48,19 +48,22 @@
> >>    */
> >>   #define _PAGE_RW	0x0400	/* lsb PP bits, inverted in HW */
> >>   #define _PAGE_USER	0x0800	/* msb PP bits */
> >> +/* set when neither _PAGE_USER nor _PAGE_RW are set */
> >> +#define _PAGE_KNLRO	0x0200
> >>   
> >>   #define _PMD_PRESENT	0x0001
> >>   #define _PMD_BAD	0x0ff0
> >>   #define _PMD_PAGE_MASK	0x000c
> >>   #define _PMD_PAGE_8M	0x000c
> >>   
> >> -#define _PTE_NONE_MASK _PAGE_ACCESSED
> >> +#define _PTE_NONE_MASK _PAGE_KNLRO
> >>   
> >>   /* Until my rework is finished, 8xx still needs atomic PTE updates */
> >>   #define PTE_ATOMIC_UPDATES	1
> >>   
> >>   /* We need to add _PAGE_SHARED to kernel pages */
> >> -#define _PAGE_KERNEL_RO	(_PAGE_SHARED)
> >> +#define _PAGE_KERNEL_RO	(_PAGE_SHARED | _PAGE_KNLRO)
> >> +#define _PAGE_KERNEL_ROX	(_PAGE_EXEC | _PAGE_KNLRO)
> >>   #define _PAGE_KERNEL_RW	(_PAGE_DIRTY | _PAGE_RW | _PAGE_HWWRITE)
> > ...if 0x200 is already being set in the PTE here?
> >
> If I understand well the way it works, those defines are used for 
> setting the PTE the first time.
> Then, pte_update() is used to modify the pte settings on an existing pte
> 
> 0x200 must be set when and only when the page is a RO kernel page. If 
> later on pte_update() is called for instance to set the page to RW, the 
> 0x200 has to be removed. Same, if pte_update() is called to remove 
> _PAGE_RW (ptep_set_wrprotect() does this), 0x200 must be set back.

OK, so the _PAGE_KERNEL_RO(X) stuff is because initially setting the PTE
doesn't go through pte_update().

I'll apply this, though it'd be cleaner to just have 8xx versions of the
relevant PTE accessor functions to maintain the PTE the way the hardware
wants (this would also eliminate the _PAGE_RW inversion that's still in
the TLB miss handler).

-Scott

^ permalink raw reply

* Re: powerpc/8xx: Remove Kconfig symbol FADS
From: Scott Wood @ 2014-11-08  0:22 UTC (permalink / raw)
  To: Paul Bolle; +Cc: linux-kernel, Paul Mackerras, linuxppc-dev
In-Reply-To: <1415350123.4390.43.camel@x220>

On Fri, 2014-11-07 at 09:48 +0100, Paul Bolle wrote:
> On Thu, 2014-11-06 at 21:50 -0600, Scott Wood wrote:
> > On Wed, Sep 24, 2014 at 10:06:19AM +0200, Paul Bolle wrote: 
> > > Another cleanup might be to remove MPC8XXFADS (or "FADS") from the "8xx
> > > Machine Type" choice. Is there any reason left to pick "FADS" as a
> > > machine type?
> > 
> > Nothing references MPC8XXFADS, so yes, it can be removed.
> 
> I'll try to look into this. For the (verbose) reasons below I'll do that
> in a separate patch, if I ever get that far. What follows is mostly a
> note to self.

Yes, make it a separate patch -- I've already got this patch queued up.

> MPC8XXFADS is indeed not referenced anywhere. But it's one of the
> entries in the "8xx Machine Type" choice. And it's common for choice
> blocks the have a "none of the above" entry. Ie, an entry that allows to
> configure nothing. There's a chance MPC8XXFADS is currently used for
> that role. (This is easier to determine for people that - unlike me -
> know what all the symbols in this choice mean. To me they 're basically
> random strings.)

It's not a "none of the above" option.  It's a board type that was
supported in arch/ppc, and only some remnants made it over to
arch/powerpc.  If you don't pick a machine type that results in a
define_machine() struct (with a probe function that matches the device
tree), the kernel will not boot.

-Scott

^ permalink raw reply

* Re: [PATCH net-next] PPC: bpf_jit_comp: add SKF_AD_HATYPE instruction
From: Alexei Starovoitov @ 2014-11-08 17:59 UTC (permalink / raw)
  To: Denis Kirjanov
  Cc: Philippe Bergheaud, netdev@vger.kernel.org, Daniel Borkmann,
	linuxppc-dev
In-Reply-To: <1415253755-4001-1-git-send-email-kda@linux-powerpc.org>

On Wed, Nov 5, 2014 at 10:02 PM, Denis Kirjanov <kda@linux-powerpc.org> wrote:
> Add BPF extension SKF_AD_HATYPE to ppc JIT to check
> the hw type of the interface
>
> JIT off:
> [   69.106783] test_bpf: #20 LD_HATYPE 48 48 PASS
> JIT on:
> [   64.721757] test_bpf: #20 LD_HATYPE 7 6 PASS
>
> CC: Alexei Starovoitov<alexei.starovoitov@gmail.com>
> CC: Daniel Borkmann<dborkman@redhat.com>
> CC: Philippe Bergheaud<felix@linux.vnet.ibm.com>
> Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>
> ---
>  arch/powerpc/net/bpf_jit_comp.c | 16 ++++++++++++++++
>  1 file changed, 16 insertions(+)
>
> diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
> index d110e28..8bf4fc2 100644
> --- a/arch/powerpc/net/bpf_jit_comp.c
> +++ b/arch/powerpc/net/bpf_jit_comp.c
> @@ -412,6 +412,22 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
>                         PPC_ANDI(r_A, r_A, PKT_TYPE_MAX);
>                         PPC_SRWI(r_A, r_A, 5);
>                         break;
> +               case BPF_ANC | SKF_AD_HATYPE:
> +                       BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2);
> +                       PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
> +                                                               dev));
> +                       PPC_CMPDI(r_scratch1, 0);
> +                       if (ctx->pc_ret0 != -1) {
> +                               PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
> +                       } else {
> +                               /* Exit, returning 0; first pass hits here. */
> +                               PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);

please use canonical formatting ctx->idx * 4 + 12

> +                               PPC_LI(r_ret, 0);
> +                               PPC_JMP(exit_addr);
> +                       }
> +                       PPC_LHZ_OFFS(r_A, r_scratch1,
> +                                    offsetof(struct net_device, type));

the whole thing looks like copy paste from 'case ifindex'.
Would be nice to handle them together to reduce
duplicated code, sine only last load is different.

Also in commit log please do _both_ runs with JIT on.
You should see a difference before/after applying this patch.

^ permalink raw reply

* [RFC Part4 v1 11/17] PCI, MSI: Rename __read_msi_msg() as __pci_read_msi_msg()
From: Jiang Liu @ 2014-11-09 15:10 UTC (permalink / raw)
  To: Bjorn Helgaas, Benjamin Herrenschmidt, Thomas Gleixner,
	Ingo Molnar, H. Peter Anvin, Rafael J. Wysocki, Randy Dunlap,
	Yinghai Lu, Borislav Petkov, Grant Likely, Marc Zyngier,
	Yingjoe Chen, Paul Mackerras, Michael Ellerman,
	Konrad Rzeszutek Wilk, x86, Matthias Brugger, Alexander Gordeev,
	Anton Blanchard, Jiang Liu, Yijing Wang
  Cc: Tony Luck, Greg Kroah-Hartman, Joerg Roedel, linux-kernel,
	linux-acpi, linux-pci, xen-devel, Andrew Morton, linuxppc-dev,
	linux-arm-kernel
In-Reply-To: <1415545839-28263-1-git-send-email-jiang.liu@linux.intel.com>

Rename __read_msi_msg() as __pci_read_msi_msg() and kill unused
read_msi_msg(). It's a preparation to separate generic MSI code
from PCI core.

Signed-off-by: Jiang Liu <jiang.liu@linux.intel.com>
---
 arch/powerpc/platforms/pseries/msi.c |    2 +-
 arch/x86/pci/xen.c                   |    2 +-
 drivers/pci/msi.c                    |    9 +--------
 include/linux/msi.h                  |    3 +--
 4 files changed, 4 insertions(+), 12 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index 8ab5add4ac82..90f756d0f58f 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -476,7 +476,7 @@ again:
 		irq_set_msi_desc(virq, entry);
 
 		/* Read config space back so we can restore after reset */
-		__read_msi_msg(entry, &msg);
+		__pci_read_msi_msg(entry, &msg);
 		entry->msg = msg;
 	}
 
diff --git a/arch/x86/pci/xen.c b/arch/x86/pci/xen.c
index 093f5f4272d3..a48ca2f8b93e 100644
--- a/arch/x86/pci/xen.c
+++ b/arch/x86/pci/xen.c
@@ -229,7 +229,7 @@ static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 		return 1;
 
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		__read_msi_msg(msidesc, &msg);
+		__pci_read_msi_msg(msidesc, &msg);
 		pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
 			((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
 		if (msg.data != XEN_PIRQ_MSI_DATA ||
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index e1814f4be4b9..6011dfb475a1 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -243,7 +243,7 @@ void default_restore_msi_irqs(struct pci_dev *dev)
 		default_restore_msi_irq(dev, entry->irq);
 }
 
-void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
+void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
 	BUG_ON(entry->dev->current_state != PCI_D0);
 
@@ -273,13 +273,6 @@ void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 	}
 }
 
-void read_msi_msg(unsigned int irq, struct msi_msg *msg)
-{
-	struct msi_desc *entry = irq_get_msi_desc(irq);
-
-	__read_msi_msg(entry, msg);
-}
-
 void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg)
 {
 	if (entry->dev->current_state != PCI_D0) {
diff --git a/include/linux/msi.h b/include/linux/msi.h
index 19502186a64d..4b0d070ff481 100644
--- a/include/linux/msi.h
+++ b/include/linux/msi.h
@@ -61,9 +61,8 @@ void msi_domain_deactivate(struct irq_domain *domain,
 
 #ifdef CONFIG_PCI_MSI
 /* Helper functions */
-void __read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
+void __pci_read_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
 void __write_msi_msg(struct msi_desc *entry, struct msi_msg *msg);
-void read_msi_msg(unsigned int irq, struct msi_msg *msg);
 void write_msi_msg(unsigned int irq, struct msi_msg *msg);
 
 /*
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH v2] hwmon: (ibmpowernv) Use platform 'id_table' to probe the device
From: Michael Ellerman @ 2014-11-09 23:04 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: benh, michaele, linux-kernel, lm-sensors, Neelesh Gupta,
	linuxppc-dev, jdelvare
In-Reply-To: <20141105142149.GA23212@roeck-us.net>

On Wed, 2014-11-05 at 06:21 -0800, Guenter Roeck wrote:
> On Wed, Nov 05, 2014 at 04:45:14PM +0530, Neelesh Gupta wrote:
> > The current driver probe() function assumes the sensor device to be
> > alwary present and gets executed every time if the driver is loaded,
> > but the appropriate hardware could not be present.
> > 
> > So, move the platform device creation as part of platform init code
> > and use the 'id_table' to check if the device present or not.
> > 
> > Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
> 
> Looks good. We'll need an ack from one of the powerpc maintainers to proceed.

Looks OK to me.

Acked-by: Michael Ellerman <mpe@ellerman.id.au>

cheers

^ permalink raw reply

* [PATCH v6 08/48] kernel: Move pm_power_off to common code
From: Guenter Roeck @ 2014-11-10  1:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: linux-mips, linux-ia64, linux-sh, linux, sparclinux, linux-s390,
	linux-am33-list, linux-c6x-dev, linux-hexagon, x86, xen-devel,
	Guenter Roeck, linux-xtensa, user-mode-linux-devel, linux-pm,
	adi-buildroot-devel, linux-m68k, user-mode-linux-user,
	linux-metag, linux-arm-kernel, linux-parisc, linux-cris-kernel,
	linux-alpha, linux390, linuxppc-dev
In-Reply-To: <1415583785-6980-1-git-send-email-linux@roeck-us.net>

pm_power_off is defined for all architectures. Move it to common code.

Have all architectures call do_kernel_power_off instead of pm_power_off.
Some architectures point pm_power_off to machine_power_off. For those,
call do_kernel_power_off from machine_power_off instead.

Acked-by: David Vrabel <david.vrabel@citrix.com>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Acked-by: Hirokazu Takata <takata@linux-m32r.org>
Acked-by: James Hogan <james.hogan@imgtec.com>
Acked-by: Jesper Nilsson <jesper.nilsson@axis.com>
Acked-by: Max Filippov <jcmvbkbc@gmail.com>
Acked-by: Rafael J. Wysocki <rjw@rjwysocki.net>
Acked-by: Richard Weinberger <richard@nod.at>
Acked-by: Xuetao Guan <gxt@mprc.pku.edu.cn>
Acked-by: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
v6:
- No change.
v5:
- Rebase to v3.18-rc3
- Update powerpc code to reflect merged power-off handler changes
v4:
- No change
v3:
- Replace poweroff in all newly introduced variables and in text
  with power_off or power-off as appropriate
v2:
- do_kernel_poweroff -> do_kernel_power_off
- have_kernel_poweroff -> have_kernel_power_off

 arch/alpha/kernel/process.c        |  9 +++------
 arch/arc/kernel/reset.c            |  5 +----
 arch/arm/kernel/process.c          |  5 +----
 arch/arm64/kernel/process.c        |  5 +----
 arch/avr32/kernel/process.c        |  6 +-----
 arch/blackfin/kernel/process.c     |  3 ---
 arch/blackfin/kernel/reboot.c      |  2 ++
 arch/c6x/kernel/process.c          |  9 +--------
 arch/cris/kernel/process.c         |  4 +---
 arch/frv/kernel/process.c          |  5 ++---
 arch/hexagon/kernel/reset.c        |  5 ++---
 arch/ia64/kernel/process.c         |  5 +----
 arch/m32r/kernel/process.c         |  8 ++++----
 arch/m68k/kernel/process.c         |  6 +-----
 arch/metag/kernel/process.c        |  6 +-----
 arch/microblaze/kernel/process.c   |  3 ---
 arch/microblaze/kernel/reset.c     |  1 +
 arch/mips/kernel/reset.c           |  6 +-----
 arch/mn10300/kernel/process.c      |  8 ++------
 arch/openrisc/kernel/process.c     |  8 +++++---
 arch/parisc/kernel/process.c       |  8 ++++----
 arch/powerpc/kernel/setup-common.c |  6 +-----
 arch/powerpc/xmon/xmon.c           |  3 +--
 arch/s390/kernel/setup.c           |  8 ++------
 arch/score/kernel/process.c        |  8 ++++----
 arch/sh/kernel/reboot.c            |  6 +-----
 arch/sparc/kernel/process_32.c     | 10 ++--------
 arch/sparc/kernel/reboot.c         |  8 ++------
 arch/tile/kernel/reboot.c          |  7 +++----
 arch/um/kernel/reboot.c            |  2 --
 arch/unicore32/kernel/process.c    |  9 +--------
 arch/x86/kernel/reboot.c           | 11 +++--------
 arch/x86/xen/enlighten.c           |  3 +--
 arch/xtensa/kernel/process.c       |  4 ----
 drivers/parisc/power.c             |  3 +--
 kernel/power/power_off_handler.c   |  9 +++++++++
 kernel/reboot.c                    |  4 ++--
 37 files changed, 68 insertions(+), 150 deletions(-)

diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index 1941a07..81c43f8 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -24,6 +24,7 @@
 #include <linux/vt.h>
 #include <linux/mman.h>
 #include <linux/elfcore.h>
+#include <linux/pm.h>
 #include <linux/reboot.h>
 #include <linux/tty.h>
 #include <linux/console.h>
@@ -40,12 +41,6 @@
 #include "proto.h"
 #include "pci_impl.h"
 
-/*
- * Power off function, if any
- */
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL(pm_power_off);
-
 #ifdef CONFIG_ALPHA_WTINT
 /*
  * Sleep the CPU.
@@ -184,6 +179,8 @@ machine_halt(void)
 void
 machine_power_off(void)
 {
+	do_kernel_power_off();
+
 	common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
 }
 
diff --git a/arch/arc/kernel/reset.c b/arch/arc/kernel/reset.c
index 2768fa1..0758d9d 100644
--- a/arch/arc/kernel/reset.c
+++ b/arch/arc/kernel/reset.c
@@ -26,9 +26,6 @@ void machine_restart(char *__unused)
 
 void machine_power_off(void)
 {
-	/* FIXME ::  power off ??? */
+	do_kernel_power_off();
 	machine_halt();
 }
-
-void (*pm_power_off) (void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index fe972a2..aa3f656 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -117,8 +117,6 @@ void soft_restart(unsigned long addr)
 /*
  * Function pointers to optional machine specific functions
  */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
 
 void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
 
@@ -205,8 +203,7 @@ void machine_power_off(void)
 	local_irq_disable();
 	smp_send_stop();
 
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 }
 
 /*
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index fde9923..6f623a0 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -68,8 +68,6 @@ void soft_restart(unsigned long addr)
 /*
  * Function pointers to optional machine specific functions
  */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL_GPL(pm_power_off);
 
 void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
 
@@ -129,8 +127,7 @@ void machine_power_off(void)
 {
 	local_irq_disable();
 	smp_send_stop();
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 }
 
 /*
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c
index 42a53e74..529c1f6 100644
--- a/arch/avr32/kernel/process.c
+++ b/arch/avr32/kernel/process.c
@@ -23,9 +23,6 @@
 
 #include <mach/pm.h>
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 /*
  * This file handles the architecture-dependent parts of process handling..
  */
@@ -48,8 +45,7 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 }
 
 void machine_restart(char *cmd)
diff --git a/arch/blackfin/kernel/process.c b/arch/blackfin/kernel/process.c
index 4aa5545..812dd83 100644
--- a/arch/blackfin/kernel/process.c
+++ b/arch/blackfin/kernel/process.c
@@ -39,9 +39,6 @@ int nr_l1stack_tasks;
 void *l1_stack_base;
 unsigned long l1_stack_len;
 
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
 /*
  * The idle loop on BFIN
  */
diff --git a/arch/blackfin/kernel/reboot.c b/arch/blackfin/kernel/reboot.c
index c4f50a3..387d610 100644
--- a/arch/blackfin/kernel/reboot.c
+++ b/arch/blackfin/kernel/reboot.c
@@ -7,6 +7,7 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <asm/bfin-global.h>
 #include <asm/reboot.h>
 #include <asm/bfrom.h>
@@ -106,6 +107,7 @@ void machine_halt(void)
 __attribute__((weak))
 void native_machine_power_off(void)
 {
+	do_kernel_power_off();
 	idle_with_irq_disabled();
 }
 
diff --git a/arch/c6x/kernel/process.c b/arch/c6x/kernel/process.c
index 57d2ea8..edf7e5a 100644
--- a/arch/c6x/kernel/process.c
+++ b/arch/c6x/kernel/process.c
@@ -27,12 +27,6 @@ void	(*c6x_halt)(void);
 extern asmlinkage void ret_from_fork(void);
 extern asmlinkage void ret_from_kernel_thread(void);
 
-/*
- * power off function, if any
- */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 void arch_cpu_idle(void)
 {
 	unsigned long tmp;
@@ -73,8 +67,7 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 	halt_loop();
 }
 
diff --git a/arch/cris/kernel/process.c b/arch/cris/kernel/process.c
index b78498e..9ebd76b 100644
--- a/arch/cris/kernel/process.c
+++ b/arch/cris/kernel/process.c
@@ -31,9 +31,6 @@
 
 extern void default_idle(void);
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 void arch_cpu_idle(void)
 {
 	default_idle();
@@ -60,6 +57,7 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
+	do_kernel_power_off();
 }
 
 /*
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c
index 5d40aeb77..502dabb 100644
--- a/arch/frv/kernel/process.c
+++ b/arch/frv/kernel/process.c
@@ -42,9 +42,6 @@ asmlinkage void ret_from_kernel_thread(void);
 
 #include <asm/pgalloc.h>
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 static void core_sleep_idle(void)
 {
 #ifdef LED_DEBUG_SLEEP
@@ -107,6 +104,8 @@ void machine_power_off(void)
 	gdbstub_exit(0);
 #endif
 
+	do_kernel_power_off();
+
 	for (;;);
 }
 
diff --git a/arch/hexagon/kernel/reset.c b/arch/hexagon/kernel/reset.c
index 76483c1..6f607b6 100644
--- a/arch/hexagon/kernel/reset.c
+++ b/arch/hexagon/kernel/reset.c
@@ -16,11 +16,13 @@
  * 02110-1301, USA.
  */
 
+#include <linux/pm.h>
 #include <linux/smp.h>
 #include <asm/hexagon_vm.h>
 
 void machine_power_off(void)
 {
+	do_kernel_power_off();
 	smp_send_stop();
 	__vmstop();
 }
@@ -32,6 +34,3 @@ void machine_halt(void)
 void machine_restart(char *cmd)
 {
 }
-
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
index b515149..88121a2 100644
--- a/arch/ia64/kernel/process.c
+++ b/arch/ia64/kernel/process.c
@@ -57,8 +57,6 @@ void (*ia64_mark_idle)(int);
 
 unsigned long boot_option_idle_override = IDLE_NO_OVERRIDE;
 EXPORT_SYMBOL(boot_option_idle_override);
-void (*pm_power_off) (void);
-EXPORT_SYMBOL(pm_power_off);
 
 void
 ia64_do_show_stack (struct unw_frame_info *info, void *arg)
@@ -675,8 +673,7 @@ machine_halt (void)
 void
 machine_power_off (void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 	machine_halt();
 }
 
diff --git a/arch/m32r/kernel/process.c b/arch/m32r/kernel/process.c
index e69221d..65a037e 100644
--- a/arch/m32r/kernel/process.c
+++ b/arch/m32r/kernel/process.c
@@ -23,6 +23,7 @@
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 #include <linux/ptrace.h>
 #include <linux/unistd.h>
 #include <linux/hardirq.h>
@@ -44,9 +45,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 	return tsk->thread.lr;
 }
 
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
 void machine_restart(char *__unused)
 {
 #if defined(CONFIG_PLAT_MAPPI3)
@@ -67,7 +65,9 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	/* M32R_FIXME */
+	do_kernel_power_off();
+	for (;;)
+		;
 }
 
 void show_regs(struct pt_regs * regs)
diff --git a/arch/m68k/kernel/process.c b/arch/m68k/kernel/process.c
index afe3d6e..bbc0a63 100644
--- a/arch/m68k/kernel/process.c
+++ b/arch/m68k/kernel/process.c
@@ -78,14 +78,10 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 	for (;;);
 }
 
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL(pm_power_off);
-
 void show_regs(struct pt_regs * regs)
 {
 	printk("\n");
diff --git a/arch/metag/kernel/process.c b/arch/metag/kernel/process.c
index 483dff9..8d95773 100644
--- a/arch/metag/kernel/process.c
+++ b/arch/metag/kernel/process.c
@@ -67,9 +67,6 @@ void arch_cpu_idle_dead(void)
 }
 #endif
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 void (*soc_restart)(char *cmd);
 void (*soc_halt)(void);
 
@@ -90,8 +87,7 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 	smp_send_stop();
 	hard_processor_halt(HALT_OK);
 }
diff --git a/arch/microblaze/kernel/process.c b/arch/microblaze/kernel/process.c
index b2dd371..0ebca36 100644
--- a/arch/microblaze/kernel/process.c
+++ b/arch/microblaze/kernel/process.c
@@ -44,9 +44,6 @@ void show_regs(struct pt_regs *regs)
 				regs->msr, regs->ear, regs->esr, regs->fsr);
 }
 
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
 void flush_thread(void)
 {
 }
diff --git a/arch/microblaze/kernel/reset.c b/arch/microblaze/kernel/reset.c
index fbe58c6..2c6b32c 100644
--- a/arch/microblaze/kernel/reset.c
+++ b/arch/microblaze/kernel/reset.c
@@ -103,6 +103,7 @@ void machine_halt(void)
 void machine_power_off(void)
 {
 	pr_notice("Machine power off...\n");
+	do_kernel_power_off();
 	while (1)
 		;
 }
diff --git a/arch/mips/kernel/reset.c b/arch/mips/kernel/reset.c
index 07fc524..09e74d2 100644
--- a/arch/mips/kernel/reset.c
+++ b/arch/mips/kernel/reset.c
@@ -21,9 +21,6 @@
  */
 void (*_machine_restart)(char *command);
 void (*_machine_halt)(void);
-void (*pm_power_off)(void);
-
-EXPORT_SYMBOL(pm_power_off);
 
 void machine_restart(char *command)
 {
@@ -39,6 +36,5 @@ void machine_halt(void)
 
 void machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 }
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c
index 3707da5..c78b2eb 100644
--- a/arch/mn10300/kernel/process.c
+++ b/arch/mn10300/kernel/process.c
@@ -20,6 +20,7 @@
 #include <linux/user.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
+#include <linux/pm.h>
 #include <linux/reboot.h>
 #include <linux/percpu.h>
 #include <linux/err.h>
@@ -45,12 +46,6 @@ unsigned long thread_saved_pc(struct task_struct *tsk)
 }
 
 /*
- * power off function, if any
- */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-/*
  * On SMP it's slightly faster (but much more power-consuming!)
  * to poll the ->work.need_resched flag instead of waiting for the
  * cross-CPU IPI to arrive. Use this option with caution.
@@ -93,6 +88,7 @@ void machine_power_off(void)
 #ifdef CONFIG_KERNEL_DEBUGGER
 	gdbstub_exit(0);
 #endif
+	do_kernel_power_off();
 }
 
 void show_regs(struct pt_regs *regs)
diff --git a/arch/openrisc/kernel/process.c b/arch/openrisc/kernel/process.c
index 386af25..494afd2 100644
--- a/arch/openrisc/kernel/process.c
+++ b/arch/openrisc/kernel/process.c
@@ -25,6 +25,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/mm.h>
+#include <linux/pm.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
@@ -51,7 +52,7 @@
  */
 struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, };
 
-void machine_restart(void)
+void machine_restart(char *cmd)
 {
 	printk(KERN_INFO "*** MACHINE RESTART ***\n");
 	__asm__("l.nop 1");
@@ -72,11 +73,12 @@ void machine_halt(void)
 void machine_power_off(void)
 {
 	printk(KERN_INFO "*** MACHINE POWER OFF ***\n");
+
+	do_kernel_power_off();
+
 	__asm__("l.nop 1");
 }
 
-void (*pm_power_off) (void) = machine_power_off;
-
 /*
  * When a process does an "exec", machine state like FPU and debug
  * registers need to be reset.  This is a hook function for that.
diff --git a/arch/parisc/kernel/process.c b/arch/parisc/kernel/process.c
index 0bbbf0d..3f5d14a 100644
--- a/arch/parisc/kernel/process.c
+++ b/arch/parisc/kernel/process.c
@@ -41,6 +41,7 @@
 #include <linux/fs.h>
 #include <linux/module.h>
 #include <linux/personality.h>
+#include <linux/pm.h>
 #include <linux/ptrace.h>
 #include <linux/sched.h>
 #include <linux/slab.h>
@@ -133,7 +134,9 @@ void machine_power_off(void)
 	pdc_soft_power_button(0);
 	
 	pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
-		
+
+	do_kernel_power_off();
+
 	/* It seems we have no way to power the system off via
 	 * software. The user has to press the button himself. */
 
@@ -141,9 +144,6 @@ void machine_power_off(void)
 	       "Please power this system off now.");
 }
 
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL(pm_power_off);
-
 /*
  * Free current thread data structures etc..
  */
diff --git a/arch/powerpc/kernel/setup-common.c b/arch/powerpc/kernel/setup-common.c
index 44c8d03..a2efce7 100644
--- a/arch/powerpc/kernel/setup-common.c
+++ b/arch/powerpc/kernel/setup-common.c
@@ -139,8 +139,7 @@ void machine_restart(char *cmd)
 void machine_power_off(void)
 {
 	machine_shutdown();
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 #ifdef CONFIG_SMP
 	smp_send_stop();
 #endif
@@ -151,9 +150,6 @@ void machine_power_off(void)
 /* Used by the G5 thermal driver */
 EXPORT_SYMBOL_GPL(machine_power_off);
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL_GPL(pm_power_off);
-
 void machine_halt(void)
 {
 	machine_shutdown();
diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index 506d256..8780178 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -981,8 +981,7 @@ static void bootcmds(void)
 	else if (cmd == 'h')
 		ppc_md.halt();
 	else if (cmd == 'p')
-		if (pm_power_off)
-			pm_power_off();
+		do_kernel_power_off();
 }
 
 static int cpu_cmd(void)
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index e80d9ff..267e025 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -263,13 +263,9 @@ void machine_power_off(void)
 		 */
 		console_unblank();
 	_machine_power_off();
-}
 
-/*
- * Dummy power off function.
- */
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL_GPL(pm_power_off);
+	do_kernel_power_off();
+}
 
 static int __init early_parse_mem(char *p)
 {
diff --git a/arch/score/kernel/process.c b/arch/score/kernel/process.c
index a1519ad3..b76ea67 100644
--- a/arch/score/kernel/process.c
+++ b/arch/score/kernel/process.c
@@ -29,9 +29,6 @@
 #include <linux/pm.h>
 #include <linux/rcupdate.h>
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 /* If or when software machine-restart is implemented, add code here. */
 void machine_restart(char *command) {}
 
@@ -39,7 +36,10 @@ void machine_restart(char *command) {}
 void machine_halt(void) {}
 
 /* If or when software machine-power-off is implemented, add code here. */
-void machine_power_off(void) {}
+void machine_power_off(void)
+{
+	do_kernel_power_off();
+}
 
 void ret_from_fork(void);
 void ret_from_kernel_thread(void);
diff --git a/arch/sh/kernel/reboot.c b/arch/sh/kernel/reboot.c
index 04afe5b..065de12 100644
--- a/arch/sh/kernel/reboot.c
+++ b/arch/sh/kernel/reboot.c
@@ -11,9 +11,6 @@
 #include <asm/tlbflush.h>
 #include <asm/traps.h>
 
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 #ifdef CONFIG_SUPERH32
 static void watchdog_trigger_immediate(void)
 {
@@ -51,8 +48,7 @@ static void native_machine_shutdown(void)
 
 static void native_machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 }
 
 static void native_machine_halt(void)
diff --git a/arch/sparc/kernel/process_32.c b/arch/sparc/kernel/process_32.c
index 50e7b62..cb8148a 100644
--- a/arch/sparc/kernel/process_32.c
+++ b/arch/sparc/kernel/process_32.c
@@ -48,14 +48,6 @@
  */
 void (*sparc_idle)(void);
 
-/* 
- * Power-off handler instantiation for pm.h compliance
- * This is done via auxio, but could be used as a fallback
- * handler when auxio is not present-- unused for now...
- */
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL(pm_power_off);
-
 /*
  * sysctl - toggle power-off restriction for serial console 
  * systems in machine_power_off()
@@ -112,6 +104,8 @@ void machine_power_off(void)
 		sbus_writeb(power_register, auxio_power_register);
 	}
 
+	do_kernel_power_off();
+
 	machine_halt();
 }
 
diff --git a/arch/sparc/kernel/reboot.c b/arch/sparc/kernel/reboot.c
index eba7d91..3c0bb03 100644
--- a/arch/sparc/kernel/reboot.c
+++ b/arch/sparc/kernel/reboot.c
@@ -16,17 +16,13 @@
  */
 int scons_pwroff = 1;
 
-/* This isn't actually used, it exists merely to satisfy the
- * reference in kernel/sys.c
- */
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL(pm_power_off);
-
 void machine_power_off(void)
 {
 	if (strcmp(of_console_device->type, "serial") || scons_pwroff)
 		prom_halt_power_off();
 
+	do_kernel_power_off();
+
 	prom_halt();
 }
 
diff --git a/arch/tile/kernel/reboot.c b/arch/tile/kernel/reboot.c
index 6c5d2c0..8ff4a7f 100644
--- a/arch/tile/kernel/reboot.c
+++ b/arch/tile/kernel/reboot.c
@@ -36,6 +36,9 @@ void machine_power_off(void)
 {
 	arch_local_irq_disable_all();
 	smp_send_stop();
+
+	do_kernel_power_off();
+
 	hv_power_off();
 }
 
@@ -45,7 +48,3 @@ void machine_restart(char *cmd)
 	smp_send_stop();
 	hv_restart((HV_VirtAddr) "vmlinux", (HV_VirtAddr) cmd);
 }
-
-/* No interesting distinction to be made here. */
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c
index ced8903..a82ef28 100644
--- a/arch/um/kernel/reboot.c
+++ b/arch/um/kernel/reboot.c
@@ -11,8 +11,6 @@
 #include <os.h>
 #include <skas.h>
 
-void (*pm_power_off)(void);
-
 static void kill_off_processes(void)
 {
 	if (proc_mm)
diff --git a/arch/unicore32/kernel/process.c b/arch/unicore32/kernel/process.c
index b008e99..9490dd5 100644
--- a/arch/unicore32/kernel/process.c
+++ b/arch/unicore32/kernel/process.c
@@ -56,16 +56,9 @@ void machine_halt(void)
 	gpio_set_value(GPO_SOFT_OFF, 0);
 }
 
-/*
- * Function pointers to optional machine specific functions
- */
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
 void machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 	machine_halt();
 }
 
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 17962e6..5c09e28 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -30,12 +30,6 @@
 #include <asm/x86_init.h>
 #include <asm/efi.h>
 
-/*
- * Power off function, if any
- */
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
 static const struct desc_ptr no_idt = {};
 
 /*
@@ -647,11 +641,12 @@ static void native_machine_halt(void)
 
 static void native_machine_power_off(void)
 {
-	if (pm_power_off) {
+	if (have_kernel_power_off()) {
 		if (!reboot_force)
 			machine_shutdown();
-		pm_power_off();
+		do_kernel_power_off();
 	}
+
 	/* A fallback in case there is no PM info available */
 	tboot_shutdown(TB_SHUTDOWN_HALT);
 }
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index fac5e4f..bc08998 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -1320,8 +1320,7 @@ static void xen_machine_halt(void)
 
 static void xen_machine_power_off(void)
 {
-	if (pm_power_off)
-		pm_power_off();
+	do_kernel_power_off();
 	xen_reboot(SHUTDOWN_poweroff);
 }
 
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c
index 1c85323..c487296 100644
--- a/arch/xtensa/kernel/process.c
+++ b/arch/xtensa/kernel/process.c
@@ -49,10 +49,6 @@ extern void ret_from_kernel_thread(void);
 
 struct task_struct *current_set[NR_CPUS] = {&init_task, };
 
-void (*pm_power_off)(void) = NULL;
-EXPORT_SYMBOL(pm_power_off);
-
-
 #if XTENSA_HAVE_COPROCESSORS
 
 void coprocessor_release_all(struct thread_info *ti)
diff --git a/drivers/parisc/power.c b/drivers/parisc/power.c
index ef31b77..f10cf92 100644
--- a/drivers/parisc/power.c
+++ b/drivers/parisc/power.c
@@ -95,8 +95,7 @@ static void process_shutdown(void)
 		/* send kill signal */
 		if (kill_cad_pid(SIGINT, 1)) {
 			/* just in case killing init process failed */
-			if (pm_power_off)
-				pm_power_off();
+			kernel_power_off();
 		}
 	}
 }
diff --git a/kernel/power/power_off_handler.c b/kernel/power/power_off_handler.c
index c19e72b..d80a337 100644
--- a/kernel/power/power_off_handler.c
+++ b/kernel/power/power_off_handler.c
@@ -23,6 +23,12 @@
 #include <linux/types.h>
 
 /*
+ * If set, calling this function will power off the system immediately.
+ */
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+/*
  * List of handlers for kernel code which wants to be called
  * to power off the system.
  */
@@ -291,6 +297,9 @@ void do_kernel_power_off(void)
 	 * that risk.
 	 */
 
+	if (pm_power_off)
+		pm_power_off();
+
 	p = rcu_dereference_raw(power_off_handler_list);
 	while (p) {
 		next_p = rcu_dereference_raw(p->next);
diff --git a/kernel/reboot.c b/kernel/reboot.c
index 5925f5a..d87d921 100644
--- a/kernel/reboot.c
+++ b/kernel/reboot.c
@@ -306,9 +306,9 @@ SYSCALL_DEFINE4(reboot, int, magic1, int, magic2, unsigned int, cmd,
 		return ret;
 
 	/* Instead of trying to make the power_off code look like
-	 * halt when pm_power_off is not set do it the easy way.
+	 * halt when no power-off handler exists do it the easy way.
 	 */
-	if ((cmd == LINUX_REBOOT_CMD_POWER_OFF) && !pm_power_off)
+	if (cmd == LINUX_REBOOT_CMD_POWER_OFF && !have_kernel_power_off())
 		cmd = LINUX_REBOOT_CMD_HALT;
 
 	mutex_lock(&reboot_mutex);
-- 
1.9.1

^ permalink raw reply related

* [PATCH v6 41/48] powerpc: Register with kernel power-off handler
From: Guenter Roeck @ 2014-11-10  1:42 UTC (permalink / raw)
  To: linux-kernel
  Cc: cbe-oss-dev, Arnd Bergmann, linux-pm, Geoff Levand,
	Alexander Graf, Paul Mackerras, Alistair Popple, Scott Wood,
	Anatolij Gustschin, linuxppc-dev, Guenter Roeck
In-Reply-To: <1415583785-6980-1-git-send-email-linux@roeck-us.net>

Register with kernel power-off handler instead of setting pm_power_off
directly.

If there is an indication that there can be more than one power-off handler,
use register_power_off_handler, otherwise use register_power_off_handler_simple
to register the power-off handler.

If the power-off handler only resets or stops the system, select the fallback
priority to indicate that the power-off handler is one of last resort.
If the power-off handler powers off the system, select the default priority,
unless the power-off handler installation code suggests that there can be
more than one power-off handler and the new handler is only installed
conditionally. In this case, install the handler with low priority.

Cc: Alexander Graf <agraf@suse.de>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Guenter Roeck <linux@roeck-us.net>
---
v6:
- This patch: No change.
  Global: Replaced priority defines with enum.
v5:
- New patch

 arch/powerpc/platforms/44x/ppc476.c              |  3 ++-
 arch/powerpc/platforms/52xx/efika.c              |  3 ++-
 arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c   | 30 ++++++++++++++++--------
 arch/powerpc/platforms/85xx/corenet_generic.c    |  3 ++-
 arch/powerpc/platforms/85xx/sgy_cts1000.c        | 16 +++++++++++--
 arch/powerpc/platforms/cell/celleb_setup.c       |  6 +++--
 arch/powerpc/platforms/cell/qpace_setup.c        |  3 ++-
 arch/powerpc/platforms/cell/setup.c              |  3 ++-
 arch/powerpc/platforms/chrp/setup.c              |  3 ++-
 arch/powerpc/platforms/embedded6xx/gamecube.c    |  3 ++-
 arch/powerpc/platforms/embedded6xx/linkstation.c |  3 ++-
 arch/powerpc/platforms/embedded6xx/wii.c         |  3 ++-
 arch/powerpc/platforms/maple/setup.c             |  6 +++--
 arch/powerpc/platforms/powermac/setup.c          |  3 ++-
 arch/powerpc/platforms/powernv/setup.c           |  6 +++--
 arch/powerpc/platforms/ps3/setup.c               |  3 ++-
 arch/powerpc/platforms/pseries/setup.c           |  3 ++-
 arch/powerpc/sysdev/fsl_soc.c                    |  6 ++---
 18 files changed, 73 insertions(+), 33 deletions(-)

diff --git a/arch/powerpc/platforms/44x/ppc476.c b/arch/powerpc/platforms/44x/ppc476.c
index c11ce65..590d31f 100644
--- a/arch/powerpc/platforms/44x/ppc476.c
+++ b/arch/powerpc/platforms/44x/ppc476.c
@@ -94,7 +94,8 @@ static int avr_probe(struct i2c_client *client,
 {
 	avr_i2c_client = client;
 	ppc_md.restart = avr_reset_system;
-	pm_power_off = avr_power_off_system;
+	register_power_off_handler_simple(avr_power_off_system,
+					  POWER_OFF_PRIORITY_DEFAULT);
 	return 0;
 }
 
diff --git a/arch/powerpc/platforms/52xx/efika.c b/arch/powerpc/platforms/52xx/efika.c
index 6af651e..321a7a7 100644
--- a/arch/powerpc/platforms/52xx/efika.c
+++ b/arch/powerpc/platforms/52xx/efika.c
@@ -212,7 +212,8 @@ static int __init efika_probe(void)
 	DMA_MODE_READ = 0x44;
 	DMA_MODE_WRITE = 0x48;
 
-	pm_power_off = rtas_power_off;
+	register_power_off_handler_simple(rtas_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
index 15e8021..1bf6b0e 100644
--- a/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
+++ b/arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/kthread.h>
 #include <linux/reboot.h>
@@ -86,7 +87,7 @@ static ssize_t show_status(struct device *d,
 }
 static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
 
-static void mcu_power_off(void)
+static void mcu_power_off(struct power_off_handler_block *this)
 {
 	struct mcu *mcu = glob_mcu;
 
@@ -97,6 +98,11 @@ static void mcu_power_off(void)
 	mutex_unlock(&mcu->lock);
 }
 
+static struct power_off_handler_block mcu_power_off_hb = {
+	.handler = mcu_power_off,
+	.priority = POWER_OFF_PRIORITY_LOW,
+};
+
 static void mcu_gpio_set(struct gpio_chip *gc, unsigned int gpio, int val)
 {
 	struct mcu *mcu = container_of(gc, struct mcu, gc);
@@ -167,13 +173,15 @@ static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
 	if (ret)
 		goto err;
 
-	/* XXX: this is potentially racy, but there is no lock for pm_power_off */
-	if (!pm_power_off) {
-		glob_mcu = mcu;
-		pm_power_off = mcu_power_off;
-		dev_info(&client->dev, "will provide power-off service\n");
+	glob_mcu = mcu;
+	ret = register_power_off_handler(&mcu_power_off_hb);
+	if (ret) {
+		dev_err(&client->dev, "Failed to register power-off handler\n");
+		goto err_handler;
 	}
 
+	dev_info(&client->dev, "will provide power-off service\n");
+
 	if (device_create_file(&client->dev, &dev_attr_status))
 		dev_err(&client->dev,
 			"couldn't create device file for status\n");
@@ -182,6 +190,10 @@ static int mcu_probe(struct i2c_client *client, const struct i2c_device_id *id)
 				      "mcu-i2c-shdn");
 
 	return 0;
+
+err_handler:
+	mcu_gpiochip_remove(mcu);
+	glob_mcu = NULL;
 err:
 	kfree(mcu);
 	return ret;
@@ -196,10 +208,8 @@ static int mcu_remove(struct i2c_client *client)
 
 	device_remove_file(&client->dev, &dev_attr_status);
 
-	if (glob_mcu == mcu) {
-		pm_power_off = NULL;
-		glob_mcu = NULL;
-	}
+	unregister_power_off_handler(&mcu_power_off_hb);
+	glob_mcu = NULL;
 
 	ret = mcu_gpiochip_remove(mcu);
 	if (ret)
diff --git a/arch/powerpc/platforms/85xx/corenet_generic.c b/arch/powerpc/platforms/85xx/corenet_generic.c
index 1f309cc..f0c4b51 100644
--- a/arch/powerpc/platforms/85xx/corenet_generic.c
+++ b/arch/powerpc/platforms/85xx/corenet_generic.c
@@ -170,7 +170,8 @@ static int __init corenet_generic_probe(void)
 
 			ppc_md.get_irq = ehv_pic_get_irq;
 			ppc_md.restart = fsl_hv_restart;
-			pm_power_off = fsl_hv_halt;
+			register_power_off_handler_simple(fsl_hv_halt,
+						POWER_OFF_PRIORITY_DEFAULT);
 			ppc_md.halt = fsl_hv_halt;
 #ifdef CONFIG_SMP
 			/*
diff --git a/arch/powerpc/platforms/85xx/sgy_cts1000.c b/arch/powerpc/platforms/85xx/sgy_cts1000.c
index e149c9e..d849e8f 100644
--- a/arch/powerpc/platforms/85xx/sgy_cts1000.c
+++ b/arch/powerpc/platforms/85xx/sgy_cts1000.c
@@ -16,6 +16,7 @@
 #include <linux/module.h>
 #include <linux/of_gpio.h>
 #include <linux/of_irq.h>
+#include <linux/pm.h>
 #include <linux/workqueue.h>
 #include <linux/reboot.h>
 #include <linux/interrupt.h>
@@ -59,6 +60,16 @@ static void gpio_halt_cb(void)
 	gpio_set_value(gpio, trigger);
 }
 
+static void gpio_power_off_cb(struct power_off_handler_block *this)
+{
+	gpio_halt_cb();
+}
+
+static struct power_off_handler_block gpio_power_off_hb = {
+	.handler = gpio_power_off_cb,
+	.priority = POWER_OFF_PRIORITY_DEFAULT,
+};
+
 /* This IRQ means someone pressed the power button and it is waiting for us
  * to handle the shutdown/poweroff. */
 static irqreturn_t gpio_halt_irq(int irq, void *__data)
@@ -120,7 +131,8 @@ static int gpio_halt_probe(struct platform_device *pdev)
 
 	/* Register our halt function */
 	ppc_md.halt = gpio_halt_cb;
-	pm_power_off = gpio_halt_cb;
+	if (register_power_off_handler(&gpio_power_off_hb))
+		pr_warn("gpio-halt: Failed to register power-off handler\n");
 
 	printk(KERN_INFO "gpio-halt: registered GPIO %d (%d trigger, %d"
 	       " irq).\n", gpio, trigger, irq);
@@ -137,7 +149,7 @@ static int gpio_halt_remove(struct platform_device *pdev)
 		free_irq(irq, halt_node);
 
 		ppc_md.halt = NULL;
-		pm_power_off = NULL;
+		unregister_power_off_handler(&gpio_power_off_hb);
 
 		gpio_free(gpio);
 
diff --git a/arch/powerpc/platforms/cell/celleb_setup.c b/arch/powerpc/platforms/cell/celleb_setup.c
index 90be8ec..e301b1a 100644
--- a/arch/powerpc/platforms/cell/celleb_setup.c
+++ b/arch/powerpc/platforms/cell/celleb_setup.c
@@ -142,7 +142,8 @@ static int __init celleb_probe_beat(void)
 	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS
 		| FW_FEATURE_BEAT | FW_FEATURE_LPAR;
 	hpte_init_beat_v3();
-	pm_power_off = beat_power_off;
+	register_power_off_handler_simple(beat_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
@@ -191,7 +192,8 @@ static int __init celleb_probe_native(void)
 
 	powerpc_firmware_features |= FW_FEATURE_CELLEB_ALWAYS;
 	hpte_init_native();
-	pm_power_off = rtas_power_off;
+	register_power_off_handler_simple(rtas_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/cell/qpace_setup.c b/arch/powerpc/platforms/cell/qpace_setup.c
index d328140..223d40a 100644
--- a/arch/powerpc/platforms/cell/qpace_setup.c
+++ b/arch/powerpc/platforms/cell/qpace_setup.c
@@ -127,7 +127,8 @@ static int __init qpace_probe(void)
 		return 0;
 
 	hpte_init_native();
-	pm_power_off = rtas_power_off;
+	register_power_off_handler_simple(rtas_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/cell/setup.c b/arch/powerpc/platforms/cell/setup.c
index d62aa98..ea5460c 100644
--- a/arch/powerpc/platforms/cell/setup.c
+++ b/arch/powerpc/platforms/cell/setup.c
@@ -259,7 +259,8 @@ static int __init cell_probe(void)
 		return 0;
 
 	hpte_init_native();
-	pm_power_off = rtas_power_off;
+	register_power_off_handler_simple(rtas_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/chrp/setup.c b/arch/powerpc/platforms/chrp/setup.c
index 860a59e..0c0288e 100644
--- a/arch/powerpc/platforms/chrp/setup.c
+++ b/arch/powerpc/platforms/chrp/setup.c
@@ -585,7 +585,8 @@ static int __init chrp_probe(void)
 	DMA_MODE_READ = 0x44;
 	DMA_MODE_WRITE = 0x48;
 
-	pm_power_off = rtas_power_off;
+	register_power_off_handler_simple(rtas_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/embedded6xx/gamecube.c b/arch/powerpc/platforms/embedded6xx/gamecube.c
index fe0ed6e..af40f0f 100644
--- a/arch/powerpc/platforms/embedded6xx/gamecube.c
+++ b/arch/powerpc/platforms/embedded6xx/gamecube.c
@@ -67,7 +67,8 @@ static int __init gamecube_probe(void)
 	if (!of_flat_dt_is_compatible(dt_root, "nintendo,gamecube"))
 		return 0;
 
-	pm_power_off = gamecube_power_off;
+	register_power_off_handler_simple(gamecube_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/embedded6xx/linkstation.c b/arch/powerpc/platforms/embedded6xx/linkstation.c
index 540eeb5..0c4dcf8 100644
--- a/arch/powerpc/platforms/embedded6xx/linkstation.c
+++ b/arch/powerpc/platforms/embedded6xx/linkstation.c
@@ -148,7 +148,8 @@ static int __init linkstation_probe(void)
 	if (!of_flat_dt_is_compatible(root, "linkstation"))
 		return 0;
 
-	pm_power_off = linkstation_power_off;
+	register_power_off_handler_simple(linkstation_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/embedded6xx/wii.c b/arch/powerpc/platforms/embedded6xx/wii.c
index 352592d..eea8824 100644
--- a/arch/powerpc/platforms/embedded6xx/wii.c
+++ b/arch/powerpc/platforms/embedded6xx/wii.c
@@ -211,7 +211,8 @@ static int __init wii_probe(void)
 	if (!of_flat_dt_is_compatible(dt_root, "nintendo,wii"))
 		return 0;
 
-	pm_power_off = wii_power_off;
+	register_power_off_handler_simple(wii_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/maple/setup.c b/arch/powerpc/platforms/maple/setup.c
index 56b85cd..73c3988 100644
--- a/arch/powerpc/platforms/maple/setup.c
+++ b/arch/powerpc/platforms/maple/setup.c
@@ -169,7 +169,8 @@ static void __init maple_use_rtas_reboot_and_halt_if_present(void)
 	if (rtas_service_present("system-reboot") &&
 	    rtas_service_present("power-off")) {
 		ppc_md.restart = rtas_restart;
-		pm_power_off = rtas_power_off;
+		register_power_off_handler_simple(rtas_power_off,
+						  POWER_OFF_PRIORITY_DEFAULT);
 		ppc_md.halt = rtas_halt;
 	}
 }
@@ -312,7 +313,8 @@ static int __init maple_probe(void)
 	alloc_dart_table();
 
 	hpte_init_native();
-	pm_power_off = maple_power_off;
+	register_power_off_handler_simple(maple_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/powermac/setup.c b/arch/powerpc/platforms/powermac/setup.c
index 713d36d..6496ae4 100644
--- a/arch/powerpc/platforms/powermac/setup.c
+++ b/arch/powerpc/platforms/powermac/setup.c
@@ -632,7 +632,8 @@ static int __init pmac_probe(void)
 	smu_cmdbuf_abs = memblock_alloc_base(4096, 4096, 0x80000000UL);
 #endif /* CONFIG_PMAC_SMU */
 
-	pm_power_off = pmac_power_off;
+	register_power_off_handler_simple(pmac_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	return 1;
 }
diff --git a/arch/powerpc/platforms/powernv/setup.c b/arch/powerpc/platforms/powernv/setup.c
index 941831d..a03c41b 100644
--- a/arch/powerpc/platforms/powernv/setup.c
+++ b/arch/powerpc/platforms/powernv/setup.c
@@ -268,7 +268,8 @@ static void __init pnv_setup_machdep_opal(void)
 	ppc_md.get_rtc_time = opal_get_rtc_time;
 	ppc_md.set_rtc_time = opal_set_rtc_time;
 	ppc_md.restart = pnv_restart;
-	pm_power_off = pnv_power_off;
+	register_power_off_handler_simple(pnv_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 	ppc_md.halt = pnv_halt;
 	ppc_md.machine_check_exception = opal_machine_check;
 	ppc_md.mce_check_early_recovery = opal_mce_check_early_recovery;
@@ -285,7 +286,8 @@ static void __init pnv_setup_machdep_rtas(void)
 		ppc_md.set_rtc_time = rtas_set_rtc_time;
 	}
 	ppc_md.restart = rtas_restart;
-	pm_power_off = rtas_power_off;
+	register_power_off_handler_simple(rtas_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 	ppc_md.halt = rtas_halt;
 }
 #endif /* CONFIG_PPC_POWERNV_RTAS */
diff --git a/arch/powerpc/platforms/ps3/setup.c b/arch/powerpc/platforms/ps3/setup.c
index 009a200..77e0dea 100644
--- a/arch/powerpc/platforms/ps3/setup.c
+++ b/arch/powerpc/platforms/ps3/setup.c
@@ -248,7 +248,8 @@ static int __init ps3_probe(void)
 	ps3_mm_init();
 	ps3_mm_vas_create(&htab_size);
 	ps3_hpte_init(htab_size);
-	pm_power_off = ps3_power_off;
+	register_power_off_handler_simple(ps3_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	DBG(" <- %s:%d\n", __func__, __LINE__);
 	return 1;
diff --git a/arch/powerpc/platforms/pseries/setup.c b/arch/powerpc/platforms/pseries/setup.c
index db0fc0c..b3c85bb 100644
--- a/arch/powerpc/platforms/pseries/setup.c
+++ b/arch/powerpc/platforms/pseries/setup.c
@@ -769,7 +769,8 @@ static int __init pSeries_probe(void)
 	else
 		hpte_init_native();
 
-	pm_power_off = pseries_power_off;
+	register_power_off_handler_simple(pseries_power_off,
+					  POWER_OFF_PRIORITY_DEFAULT);
 
 	pr_debug("Machine is%s LPAR !\n",
 	         (powerpc_firmware_features & FW_FEATURE_LPAR) ? "" : " not");
diff --git a/arch/powerpc/sysdev/fsl_soc.c b/arch/powerpc/sysdev/fsl_soc.c
index 1e04568..eeb075f 100644
--- a/arch/powerpc/sysdev/fsl_soc.c
+++ b/arch/powerpc/sysdev/fsl_soc.c
@@ -238,9 +238,9 @@ void fsl_hv_restart(char *cmd)
 /*
  * Halt the current partition
  *
- * This function should be assigned to the pm_power_off and ppc_md.halt
- * function pointers, to shut down the partition when we're running under
- * the Freescale hypervisor.
+ * This function should be registered as power-off handler and be assigned
+ * to the ppc_md.halt function pointer, to shut down the partition when
+ * we're running under the Freescale hypervisor.
  */
 void fsl_hv_halt(void)
 {
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH 0/2] Add IPMI support for powernv powerpc machines
From: Jeremy Kerr @ 2014-11-10  3:26 UTC (permalink / raw)
  To: minyard, openipmi-developer, linuxppc-dev
In-Reply-To: <545B826F.7050501@acm.org>

Hi Corey,

Thanks for the review.

>> IPMI folks: the IPMI driver could do with a little review, as it's
>> not a conventional BT/KCS/SMI SI, in that the low-level send/recv
>> interface will handle the entire message at once.
> 
> Handling the entire message at once should be fine, as that's what
> this driver level is designed to do for the message handler.  That
> part all looks correct.  The code itself looks good, but I have a
> couple of high-level comments.
> 
> The driver at this level can receive more than one message to handle
> at a time, so it needs some sort of queue.  This is to allow multiple
> users and to allow the message handler to send its own commands while
> other commands are going on.  You might argue that the queuing should
> be done in ipmi_msghandler, and you would probably be right.

Ah, that's what I'd been assuming was being done - I missed the
xmit_list in the si_intf code. It'd be great if this could be in the
generic msghandler code, otherwise I'd just be duplicating the si_intf
logic.

> I'll look at doing that.  If that is the case, then your NULL check
> for current message should probably be a BUG_ON().

OK, I'll update this when the msghandler bit is implemented.

> Do you need to handle any BMC flags?  Particularly incoming events?

Not at this stage - we may in future though.

Cheers,


Jeremy

^ permalink raw reply

* Re: [PATCH] cpufreq: qoriq: Make the driver usable on all QorIQ platforms
From: Viresh Kumar @ 2014-11-10  4:56 UTC (permalink / raw)
  To: Yuantian Tang
  Cc: linuxppc-dev@ozlabs.org, Rafael J. Wysocki,
	Linux Kernel Mailing List, linux-pm@vger.kernel.org
In-Reply-To: <c94b68be09dd4bfaa8a80d9877362fb5@DM2PR03MB574.namprd03.prod.outlook.com>

On 27 October 2014 09:09, Yuantian Tang <Yuantian.Tang@freescale.com> wrote:
> Do we have a conclusion yet?

No. You can keep your initial duplication of Kconfig entries for the time being.

^ permalink raw reply

* Re: [PATCH 0/2] Add IPMI support for powernv powerpc machines
From: Benjamin Herrenschmidt @ 2014-11-10  5:41 UTC (permalink / raw)
  To: Jeremy Kerr; +Cc: openipmi-developer, linuxppc-dev, minyard
In-Reply-To: <5460307C.9060502@ozlabs.org>

On Mon, 2014-11-10 at 11:26 +0800, Jeremy Kerr wrote:
> Hi Corey,
> 
> Thanks for the review.
> 
> >> IPMI folks: the IPMI driver could do with a little review, as it's
> >> not a conventional BT/KCS/SMI SI, in that the low-level send/recv
> >> interface will handle the entire message at once.
> > 
> > Handling the entire message at once should be fine, as that's what
> > this driver level is designed to do for the message handler.  That
> > part all looks correct.  The code itself looks good, but I have a
> > couple of high-level comments.
> > 
> > The driver at this level can receive more than one message to handle
> > at a time, so it needs some sort of queue.  This is to allow multiple
> > users and to allow the message handler to send its own commands while
> > other commands are going on.  You might argue that the queuing should
> > be done in ipmi_msghandler, and you would probably be right.
> 
> Ah, that's what I'd been assuming was being done - I missed the
> xmit_list in the si_intf code. It'd be great if this could be in the
> generic msghandler code, otherwise I'd just be duplicating the si_intf
> logic.

Our OPAL interface can only do one at a time ? Because our underlying FW
driver already has a queue ..

> > I'll look at doing that.  If that is the case, then your NULL check
> > for current message should probably be a BUG_ON().
> 
> OK, I'll update this when the msghandler bit is implemented.
> 
> > Do you need to handle any BMC flags?  Particularly incoming events?
> 
> Not at this stage - we may in future though.
> 
> Cheers,
> 
> 
> Jeremy
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* Re: [PATCH 0/2] Add IPMI support for powernv powerpc machines
From: Alistair Popple @ 2014-11-10  6:01 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: openipmi-developer, Jeremy Kerr, minyard
In-Reply-To: <1415598090.5769.15.camel@kernel.crashing.org>

Ben,

> 
> Our OPAL interface can only do one at a time ? Because our underlying FW
> driver already has a queue ..

The OPAL interface supports sending more than one message at a time using the 
underlying FW queue as you suggest. However in theory the interface doesn't 
make any response order guarantees, but in practice they should be ordered as 
our BMC doesn't send out-of-order responses.

Regards,

Alistair

> > > I'll look at doing that.  If that is the case, then your NULL check
> > > for current message should probably be a BUG_ON().
> > 
> > OK, I'll update this when the msghandler bit is implemented.
> > 
> > > Do you need to handle any BMC flags?  Particularly incoming events?
> > 
> > Not at this stage - we may in future though.
> > 
> > Cheers,
> > 
> > 
> > Jeremy
> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@lists.ozlabs.org
> > https://lists.ozlabs.org/listinfo/linuxppc-dev
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev

^ permalink raw reply

* [PATCH] i2c: Driver to expose PowerNV platform i2c busses
From: Neelesh Gupta @ 2014-11-10  6:05 UTC (permalink / raw)
  To: linuxppc-dev, linux-i2c

The patch exposes the available i2c busses on the PowerNV platform
to the kernel and implements the bus driver to support i2c and
smbus commands.
The driver uses the platform device infrastructure to probe the busses
on the platform and registers them with the i2c driver framework.

Signed-off-by: Neelesh Gupta <neelegup@linux.vnet.ibm.com>
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
 arch/powerpc/include/asm/opal.h                |   21 ++
 arch/powerpc/platforms/powernv/opal-wrappers.S |    1 
 arch/powerpc/platforms/powernv/opal.c          |   48 +++-
 drivers/i2c/busses/Kconfig                     |   11 +
 drivers/i2c/busses/Makefile                    |    1 
 drivers/i2c/busses/i2c-opal.c                  |  276 ++++++++++++++++++++++++
 6 files changed, 349 insertions(+), 9 deletions(-)
 create mode 100644 drivers/i2c/busses/i2c-opal.c

diff --git a/arch/powerpc/include/asm/opal.h b/arch/powerpc/include/asm/opal.h
index 9124b0e..7e94577 100644
--- a/arch/powerpc/include/asm/opal.h
+++ b/arch/powerpc/include/asm/opal.h
@@ -154,6 +154,7 @@ struct opal_sg_list {
 #define OPAL_HANDLE_HMI				98
 #define OPAL_REGISTER_DUMP_REGION		101
 #define OPAL_UNREGISTER_DUMP_REGION		102
+#define OPAL_I2C_REQUEST			109
 
 #ifndef __ASSEMBLY__
 
@@ -801,6 +802,24 @@ typedef struct oppanel_line {
 	uint64_t 	line_len;
 } oppanel_line_t;
 
+/* OPAL I2C request */
+struct opal_i2c_request {
+	uint8_t	type;
+#define OPAL_I2C_RAW_READ	0
+#define OPAL_I2C_RAW_WRITE	1
+#define OPAL_I2C_SM_READ	2
+#define OPAL_I2C_SM_WRITE	3
+	uint8_t flags;
+#define OPAL_I2C_ADDR_10	0x01	/* Not supported yet */
+	uint8_t	subaddr_sz;		/* Max 4 */
+	uint8_t reserved;
+	__be16 addr;			/* 7 or 10 bit address */
+	__be16 reserved2;
+	__be32 subaddr;		/* Sub-address if any */
+	__be32 size;			/* Data size */
+	__be64 buffer_ra;		/* Buffer real address */
+};
+
 /* /sys/firmware/opal */
 extern struct kobject *opal_kobj;
 
@@ -963,6 +982,8 @@ int64_t opal_handle_hmi(void);
 int64_t opal_register_dump_region(uint32_t id, uint64_t start, uint64_t end);
 int64_t opal_unregister_dump_region(uint32_t id);
 int64_t opal_pci_set_phb_cxl_mode(uint64_t phb_id, uint64_t mode, uint64_t pe_number);
+int64_t opal_i2c_request(uint64_t async_token, uint32_t bus_id,
+			 struct opal_i2c_request *oreq);
 
 /* Internal functions */
 extern int early_init_dt_scan_opal(unsigned long node, const char *uname,
diff --git a/arch/powerpc/platforms/powernv/opal-wrappers.S b/arch/powerpc/platforms/powernv/opal-wrappers.S
index e9e2450..b84224b 100644
--- a/arch/powerpc/platforms/powernv/opal-wrappers.S
+++ b/arch/powerpc/platforms/powernv/opal-wrappers.S
@@ -250,3 +250,4 @@ OPAL_CALL(opal_handle_hmi,			OPAL_HANDLE_HMI);
 OPAL_CALL(opal_register_dump_region,		OPAL_REGISTER_DUMP_REGION);
 OPAL_CALL(opal_unregister_dump_region,		OPAL_UNREGISTER_DUMP_REGION);
 OPAL_CALL(opal_pci_set_phb_cxl_mode,		OPAL_PCI_SET_PHB_CXL_MODE);
+OPAL_CALL(opal_i2c_request,			OPAL_I2C_REQUEST);
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c
index d019b08..217630b 100644
--- a/arch/powerpc/platforms/powernv/opal.c
+++ b/arch/powerpc/platforms/powernv/opal.c
@@ -644,17 +644,10 @@ static void __init opal_dump_region_init(void)
 		pr_warn("DUMP: Failed to register kernel log buffer. "
 			"rc = %d\n", rc);
 }
-static int __init opal_init(void)
+
+static void opal_console_create_devs(void)
 {
 	struct device_node *np, *consoles;
-	const __be32 *irqs;
-	int rc, i, irqlen;
-
-	opal_node = of_find_node_by_path("/ibm,opal");
-	if (!opal_node) {
-		pr_warn("opal: Node not found\n");
-		return -ENODEV;
-	}
 
 	/* Register OPAL consoles if any ports */
 	if (firmware_has_feature(FW_FEATURE_OPALv2))
@@ -670,6 +663,21 @@ static int __init opal_init(void)
 		of_node_put(consoles);
 	}
 
+}
+
+static void opal_i2c_create_devs(void)
+{
+	struct device_node *np;
+
+	for_each_compatible_node(np, NULL, "ibm,power8-i2c-port")
+		of_platform_device_create(np, NULL, NULL);
+}
+
+static void opal_request_interrupts(void)
+{
+	const __be32 *irqs;
+	int rc, i, irqlen;
+
 	/* Find all OPAL interrupts and request them */
 	irqs = of_get_property(opal_node, "opal-interrupts", &irqlen);
 	pr_debug("opal: Found %d interrupts reserved for OPAL\n",
@@ -689,6 +697,26 @@ static int __init opal_init(void)
 				   " (0x%x)\n", rc, irq, hwirq);
 		opal_irqs[i] = irq;
 	}
+}
+
+static int __init opal_init(void)
+{
+	int rc;
+
+	opal_node = of_find_node_by_path("/ibm,opal");
+	if (!opal_node) {
+		pr_warn("opal: Node not found\n");
+		return -ENODEV;
+	}
+
+	/* Create console platform devices */
+	opal_console_create_devs();
+
+	/* Create i2c platform devices */
+	opal_i2c_create_devs();
+
+	/* Register OPAL interrupts */
+	opal_request_interrupts();
 
 	/* Create "opal" kobject under /sys/firmware */
 	rc = opal_sysfs_init();
@@ -805,3 +833,5 @@ void opal_free_sg_list(struct opal_sg_list *sg)
 			sg = NULL;
 	}
 }
+
+EXPORT_SYMBOL_GPL(opal_i2c_request);
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index 917c358..71ad6e1 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -1044,4 +1044,15 @@ config SCx200_ACB
 	  This support is also available as a module.  If so, the module
 	  will be called scx200_acb.
 
+config I2C_OPAL
+	tristate "IBM OPAL I2C driver"
+	depends on PPC_POWERNV
+	default y
+	help
+	  This exposes the PowerNV platform i2c busses to the linux i2c layer,
+	  the driver is based on the OPAL interfaces.
+
+	  This driver can also be built as a module. If so, the module will be
+	  called as i2c-opal.
+
 endmenu
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index 78d56c5..350aa86 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -102,5 +102,6 @@ obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o
 obj-$(CONFIG_I2C_SIBYTE)	+= i2c-sibyte.o
 obj-$(CONFIG_SCx200_ACB)	+= scx200_acb.o
+obj-$(CONFIG_I2C_OPAL)		+= i2c-opal.o
 
 ccflags-$(CONFIG_I2C_DEBUG_BUS) := -DDEBUG
diff --git a/drivers/i2c/busses/i2c-opal.c b/drivers/i2c/busses/i2c-opal.c
new file mode 100644
index 0000000..3261716
--- /dev/null
+++ b/drivers/i2c/busses/i2c-opal.c
@@ -0,0 +1,276 @@
+/*
+ * IBM OPAL I2C driver
+ * Copyright (C) 2014 IBM
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/mm.h>
+#include <asm/opal.h>
+#include <asm/firmware.h>
+
+static int i2c_opal_send_request(u32 bus_id, struct opal_i2c_request *req)
+{
+	struct opal_msg msg;
+	int token, rc;
+
+	token = opal_async_get_token_interruptible();
+	if (token < 0) {
+		if (token != -ERESTARTSYS)
+			pr_err("Failed to get the async token\n");
+
+		return token;
+	}
+
+	rc = opal_i2c_request(token, bus_id, req);
+	if (rc != OPAL_ASYNC_COMPLETION) {
+		rc = -EIO;
+		goto exit;
+	}
+
+	rc = opal_async_wait_response(token, &msg);
+	if (rc) {
+		rc = -EIO;
+		goto exit;
+	}
+
+	rc = be64_to_cpu(msg.params[1]);
+	if (rc != OPAL_SUCCESS) {
+		rc = -EIO;
+		goto exit;
+	}
+
+exit:
+	opal_async_release_token(token);
+	return rc;
+}
+
+static int i2c_opal_master_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+				int num)
+{
+	unsigned long opal_id = (unsigned long)adap->algo_data;
+	struct opal_i2c_request req;
+	int rc, i;
+
+	/* We only support fairly simple combinations here of one
+	 * or two messages
+	 */
+	memset(&req, 0, sizeof(req));
+	switch (num) {
+	case 0:
+		return 0;
+	case 1:
+		req.type = (msgs[0].flags & I2C_M_RD) ?
+			OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
+		req.addr = cpu_to_be16(msgs[0].addr);
+		req.size = cpu_to_be32(msgs[0].len);
+		req.buffer_ra = cpu_to_be64(__pa(msgs[0].buf));
+		break;
+	case 2:
+		/* For two messages, we basically support only simple
+		 * smbus transactions of a write plus a read. We might
+		 * want to allow also two writes but we'd have to bounce
+		 * the data into a single buffer.
+		 */
+		if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD))
+			return -EIO;
+		if (msgs[0].len > 4)
+			return -EIO;
+		if (msgs[0].addr != msgs[1].addr)
+			return -EIO;
+		req.type = OPAL_I2C_SM_READ;
+		req.addr = cpu_to_be16(msgs[0].addr);
+		req.subaddr_sz = msgs[0].len;
+		for (i = 0; i < msgs[0].len; i++)
+			req.subaddr = (req.subaddr << 8) | msgs[0].buf[i];
+		req.subaddr = cpu_to_be32(req.subaddr);
+		req.size = cpu_to_be32(msgs[1].len);
+		req.buffer_ra = cpu_to_be64(__pa(msgs[1].buf));
+		break;
+	default:
+		return -EIO;
+	}
+
+	rc = i2c_opal_send_request(opal_id, &req);
+	if (rc)
+		return rc;
+
+	return num;
+}
+
+static int i2c_opal_smbus_xfer(struct i2c_adapter *adap, u16 addr,
+			       unsigned short flags, char read_write,
+			       u8 command, int size, union i2c_smbus_data *data)
+{
+	unsigned long opal_id = (unsigned long)adap->algo_data;
+	struct opal_i2c_request req;
+	u8 local[2];
+	int rc;
+
+	memset(&req, 0, sizeof(req));
+
+	req.addr = cpu_to_be16(addr);
+	switch (size) {
+	case I2C_SMBUS_BYTE:
+		req.buffer_ra = cpu_to_be64(__pa(&data->byte));
+		req.size = cpu_to_be32(1);
+		/* Fall through */
+	case I2C_SMBUS_QUICK:
+		req.type = (read_write == I2C_SMBUS_READ) ?
+			OPAL_I2C_RAW_READ : OPAL_I2C_RAW_WRITE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		req.buffer_ra = cpu_to_be64(__pa(&data->byte));
+		req.size = cpu_to_be32(1);
+		req.subaddr = cpu_to_be32(command);
+		req.subaddr_sz = 1;
+		req.type = (read_write == I2C_SMBUS_READ) ?
+			OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		if (!read_write) {
+			local[0] = data->word & 0xff;
+			local[1] = (data->word >> 8) & 0xff;
+		}
+		req.buffer_ra = cpu_to_be64(__pa(local));
+		req.size = cpu_to_be32(2);
+		req.subaddr = cpu_to_be32(command);
+		req.subaddr_sz = 1;
+		req.type = (read_write == I2C_SMBUS_READ) ?
+			OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
+		break;
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+		req.buffer_ra = cpu_to_be64(__pa(&data->block[1]));
+		req.size = cpu_to_be32(data->block[0]);
+		req.subaddr = cpu_to_be32(command);
+		req.subaddr_sz = 1;
+		req.type = (read_write == I2C_SMBUS_READ) ?
+			OPAL_I2C_SM_READ : OPAL_I2C_SM_WRITE;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	rc = i2c_opal_send_request(opal_id, &req);
+	if (!rc && read_write && size == I2C_SMBUS_WORD_DATA) {
+		data->word = ((u16)local[1]) << 8;
+		data->word |= local[0];
+	}
+
+	return rc;
+}
+
+static u32 i2c_opal_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	       I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	       I2C_FUNC_SMBUS_I2C_BLOCK;
+}
+
+static const struct i2c_algorithm i2c_opal_algo = {
+	.master_xfer	= i2c_opal_master_xfer,
+	.smbus_xfer	= i2c_opal_smbus_xfer,
+	.functionality	= i2c_opal_func,
+};
+
+static int i2c_opal_probe(struct platform_device *pdev)
+{
+	struct i2c_adapter	*adapter;
+	const char		*pname;
+	u32			opal_id;
+	int			rc;
+
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+	rc = of_property_read_u32(pdev->dev.of_node, "ibm,opal-id", &opal_id);
+	if (rc) {
+		dev_err(&pdev->dev, "Missing ibm,opal-id property !\n");
+		return -EIO;
+	}
+	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (!adapter)
+		return -ENOMEM;
+	adapter->algo = &i2c_opal_algo;
+	adapter->algo_data = (void *)(unsigned long)opal_id;
+	adapter->dev.parent = &pdev->dev;
+	adapter->dev.of_node = of_node_get(pdev->dev.of_node);
+	pname = of_get_property(pdev->dev.of_node, "port-name", NULL);
+	if (pname)
+		strlcpy(adapter->name, pname, sizeof(adapter->name));
+	else
+		strlcpy(adapter->name, "opal", sizeof(adapter->name));
+
+	platform_set_drvdata(pdev, adapter);
+	rc = i2c_add_adapter(adapter);
+	if (rc)
+		dev_err(&pdev->dev, "Failed to register the i2c adapter\n");
+
+	return rc;
+}
+
+static int i2c_opal_remove(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+
+	i2c_del_adapter(adapter);
+
+	kfree(adapter);
+
+	return 0;
+}
+
+static const struct of_device_id i2c_opal_of_match[] = {
+	{
+		.compatible = "ibm,power8-i2c-port",
+	},
+	{ }
+};
+MODULE_DEVICE_TABLE(of, i2c_opal_of_match);
+
+static struct platform_driver i2c_opal_driver = {
+	.probe	= i2c_opal_probe,
+	.remove	= i2c_opal_remove,
+	.driver	= {
+		.name		= "i2c-opal",
+		.owner		= THIS_MODULE,
+		.of_match_table	= i2c_opal_of_match,
+	},
+};
+
+static int __init i2c_opal_init(void)
+{
+	if (!firmware_has_feature(FW_FEATURE_OPAL))
+		return -ENODEV;
+
+	return platform_driver_register(&i2c_opal_driver);
+}
+
+static void __exit i2c_opal_exit(void)
+{
+	return platform_driver_unregister(&i2c_opal_driver);
+}
+
+MODULE_AUTHOR("Neelesh Gupta <neelegup@linux.vnet.ibm.com>");
+MODULE_DESCRIPTION("IBM OPAL I2C driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_opal_init);
+module_exit(i2c_opal_exit);

^ permalink raw reply related

* [PATCH v2 net-next] PPC: bpf_jit_comp: add SKF_AD_HATYPE instruction
From: Denis Kirjanov @ 2014-11-10  5:59 UTC (permalink / raw)
  To: netdev
  Cc: Philippe Bergheaud, linuxppc-dev, Denis Kirjanov, Daniel Borkmann,
	Alexei Starovoitov

Add BPF extension SKF_AD_HATYPE to ppc JIT to check
the hw type of the interface

Before:
[   57.723666] test_bpf: #20 LD_HATYPE
[   57.723675] BPF filter opcode 0020 (@0) unsupported
[   57.724168] 48 48 PASS

After:
[  103.053184] test_bpf: #20 LD_HATYPE 7 6 PASS

CC: Alexei Starovoitov<alexei.starovoitov@gmail.com>
CC: Daniel Borkmann<dborkman@redhat.com>
CC: Philippe Bergheaud<felix@linux.vnet.ibm.com>
Signed-off-by: Denis Kirjanov <kda@linux-powerpc.org>

v2: address Alexei's comments
---
 arch/powerpc/net/bpf_jit_comp.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/net/bpf_jit_comp.c b/arch/powerpc/net/bpf_jit_comp.c
index d110e28..d3fa80d 100644
--- a/arch/powerpc/net/bpf_jit_comp.c
+++ b/arch/powerpc/net/bpf_jit_comp.c
@@ -361,6 +361,11 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 							    protocol));
 			break;
 		case BPF_ANC | SKF_AD_IFINDEX:
+		case BPF_ANC | SKF_AD_HATYPE:
+			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+						ifindex) != 4);
+			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
+						type) != 2);
 			PPC_LD_OFFS(r_scratch1, r_skb, offsetof(struct sk_buff,
 								dev));
 			PPC_CMPDI(r_scratch1, 0);
@@ -368,14 +373,18 @@ static int bpf_jit_build_body(struct bpf_prog *fp, u32 *image,
 				PPC_BCC(COND_EQ, addrs[ctx->pc_ret0]);
 			} else {
 				/* Exit, returning 0; first pass hits here. */
-				PPC_BCC_SHORT(COND_NE, (ctx->idx*4)+12);
+				PPC_BCC_SHORT(COND_NE, ctx->idx * 4 + 12);
 				PPC_LI(r_ret, 0);
 				PPC_JMP(exit_addr);
 			}
-			BUILD_BUG_ON(FIELD_SIZEOF(struct net_device,
-						  ifindex) != 4);
-			PPC_LWZ_OFFS(r_A, r_scratch1,
+			if (code == (BPF_ANC | SKF_AD_IFINDEX)) {
+				PPC_LWZ_OFFS(r_A, r_scratch1,
 				     offsetof(struct net_device, ifindex));
+			} else {
+				PPC_LHZ_OFFS(r_A, r_scratch1,
+				     offsetof(struct net_device, type));
+			}
+
 			break;
 		case BPF_ANC | SKF_AD_MARK:
 			BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4);
-- 
2.1.0

^ 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