LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH 2/6] powerpc: Define CPU_FTR_HAS_PPR
From: Michael Neuling @ 2012-11-23  4:01 UTC (permalink / raw)
  To: Haren Myneni; +Cc: anton, paulus, linuxppc-dev
In-Reply-To: <1351666334.32304.13.camel@hbabu-laptop>

Heaven Myneni <haren@linux.vnet.ibm.com> wrote:

> [PATCH 2/6] powerpc: Define CPU_FTR_HAS_PPR
> 
> CPU_FTR_HAS_PPR is defined for POWER7.
> 
> Signed-off-by: Haren Myneni <haren@us.ibm.com>
> ---
>  arch/powerpc/include/asm/cputable.h |    6 ++++--
>  1 files changed, 4 insertions(+), 2 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
> index 21a0687..12e3a1d 100644
> --- a/arch/powerpc/include/asm/cputable.h
> +++ b/arch/powerpc/include/asm/cputable.h
> @@ -171,6 +171,7 @@ extern const char *powerpc_base_platform;
>  #define CPU_FTR_POPCNTD			LONG_ASM_CONST(0x0800000000000000)
>  #define CPU_FTR_ICSWX			LONG_ASM_CONST(0x1000000000000000)
>  #define CPU_FTR_VMX_COPY		LONG_ASM_CONST(0x2000000000000000)
> +#define	CPU_FTR_HAS_PPR			LONG_ASM_CONST(0x4000000000000000)
>  
>  #ifndef __ASSEMBLY__
>  
> @@ -400,7 +401,8 @@ extern const char *powerpc_base_platform;
>  	    CPU_FTR_PURR | CPU_FTR_SPURR | CPU_FTR_REAL_LE | \
>  	    CPU_FTR_DSCR | CPU_FTR_SAO  | CPU_FTR_ASYM_SMT | \
>  	    CPU_FTR_STCX_CHECKS_ADDRESS | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD | \
> -	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | CPU_FTR_VMX_COPY)
> +	    CPU_FTR_ICSWX | CPU_FTR_CFAR | CPU_FTR_HVMODE | \
> +	    CPU_FTR_VMX_COPY | CPU_FTR_HAS_PPR)
>  #define CPU_FTRS_CELL	(CPU_FTR_USE_TB | CPU_FTR_LWSYNC | \
>  	    CPU_FTR_PPCAS_ARCH_V2 | CPU_FTR_CTRL | \
>  	    CPU_FTR_ALTIVEC_COMP | CPU_FTR_MMCRA | CPU_FTR_SMT | \
> @@ -422,7 +424,7 @@ extern const char *powerpc_base_platform;
>  	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
>  	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 |	\
>  	    CPU_FTRS_POWER7 | CPU_FTRS_CELL | CPU_FTRS_PA6T |		\
> -	    CPU_FTR_VSX)
> +	    CPU_FTR_VSX | CPU_FTR_HAS_PPR)

FYI, there is no need to add this to POSSIBLE, since you are adding it
to POWER7 anyway.

Mikey

^ permalink raw reply

* Re: [PATCH 5/6] powerpc: Macros for saving/restore PPR
From: Michael Neuling @ 2012-11-23  3:39 UTC (permalink / raw)
  To: Haren Myneni; +Cc: anton, paulus, linuxppc-dev
In-Reply-To: <1351666574.32304.18.camel@hbabu-laptop>

Haren Myneni <haren@linux.vnet.ibm.com> wrote:

> [PATCH 5/6] powerpc: Macros for saving/restore PPR
> 
> Several macros are defined for saving and restore user defined PPR value.
> 
> Signed-off-by: Haren Myneni <haren@us.ibm.com>
> ---
>  arch/powerpc/include/asm/exception-64s.h |   29 +++++++++++++++++++++++++++++
>  arch/powerpc/include/asm/ppc_asm.h       |   25 +++++++++++++++++++++++++
>  arch/powerpc/include/asm/reg.h           |    1 +
>  3 files changed, 55 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
> index bfd3f1f..880ef7d 100644
> --- a/arch/powerpc/include/asm/exception-64s.h
> +++ b/arch/powerpc/include/asm/exception-64s.h
> @@ -62,6 +62,35 @@
>  #define EXC_HV	H
>  #define EXC_STD
>  
> +/*
> + * PPR save/restore macros used in exceptions_64s.S  
> + * Used for P7 or later processors
> + */
> +#define SAVE_PPR(area, ra, rb)						\
> +BEGIN_FTR_SECTION_NESTED(940)						\
> +	ld	ra,PACACURRENT(r13);					\
> +	ld	rb,area+EX_PPR(r13);	/* Read PPR from paca */	\
> +	std	rb,TASKTHREADPPR(ra);					\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,940)
> +
> +#define RESTORE_PPR_PACA(area, ra)					\
> +BEGIN_FTR_SECTION_NESTED(941)						\
> +	ld	ra,area+EX_PPR(r13);					\
> +	mtspr	SPRN_PPR,ra;						\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,941)
> +

Can you add some documentation here on why we should use the different
versions.

I'm trying to read the next patch and it's not clear to my why some have
HMT_MEDIUM_NO_PPR and other times HMT_MEDIUM and others
HTM_MEDIUM_HAS_PPR.

Looks like HTM_MEDIUM_NO_PPR sets the priority to medium on systems
where we can't save/restore the PPR, hence it can be called earlier in
the exception handler before we have free GPRs.  HTM_MEDIUM_HAS_PPR
saves the priority on systems where it can, and then sets the priority
to medium.

Maybe we should change the names 
  HTM_MEDIUM_NO_PPR  => HTM_MEDIUM_PPR_DISCARD   and
  HTM_MEDIUM_HAS_PPR => HTM_MEDIUM_PPR_SAVE
But now I'm heading into bike shedding territory... plus I think I
suggested the names you have currently, so I'm feeling a bit dumb now
:-)

Mikey

> +#define HMT_MEDIUM_NO_PPR						\
> +BEGIN_FTR_SECTION_NESTED(942)						\
> +	HMT_MEDIUM;							\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,0,942)  /*non P7*/		
> +
> +#define HMT_MEDIUM_HAS_PPR(area, ra)					\
> +BEGIN_FTR_SECTION_NESTED(943)						\
> +	mfspr	ra,SPRN_PPR;						\
> +	std	ra,area+EX_PPR(r13);					\
> +	HMT_MEDIUM;							\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,943) 
> +
>  #define __EXCEPTION_PROLOG_1(area, extra, vec)				\
>  	GET_PACA(r13);							\
>  	std	r9,area+EX_R9(r13);	/* save r9 - r12 */		\


> diff --git a/arch/powerpc/include/asm/ppc_asm.h b/arch/powerpc/include/asm/ppc_asm.h
> index 376e36d..52649cc 100644
> --- a/arch/powerpc/include/asm/ppc_asm.h
> +++ b/arch/powerpc/include/asm/ppc_asm.h
> @@ -389,6 +389,31 @@ END_FTR_SECTION_IFCLR(CPU_FTR_601)
>  	FTR_SECTION_ELSE_NESTED(848);	\
>  	mtocrf (FXM), RS;		\
>  	ALT_FTR_SECTION_END_NESTED_IFCLR(CPU_FTR_NOEXECUTE, 848)
> +
> +/*
> + * PPR restore macros used in entry_64.S
> + * Used for P7 or later processors
> + */
> +#define HMT_MEDIUM_LOW_HAS_PPR						\
> +BEGIN_FTR_SECTION_NESTED(944)						\
> +	HMT_MEDIUM_LOW;							\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,944)
> +
> +#define SET_DEFAULT_THREAD_PPR(ra, rb)					\
> +BEGIN_FTR_SECTION_NESTED(945)						\
> +	lis	ra,0xc;		/* default ppr=3 */			\
> +	ld	rb,PACACURRENT(r13);					\
> +	sldi	ra,ra,32;	/* 11- 13 bits are used for ppr */	\
> +	std	ra,TASKTHREADPPR(rb);					\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,945)
> +
> +#define RESTORE_PPR(ra, rb)						\
> +BEGIN_FTR_SECTION_NESTED(946)						\
> +	ld	ra,PACACURRENT(r13);					\
> +	ld	rb,TASKTHREADPPR(ra);					\
> +	mtspr	SPRN_PPR,rb;	/* Restore PPR */			\
> +END_FTR_SECTION_NESTED(CPU_FTR_HAS_PPR,CPU_FTR_HAS_PPR,946)
> +
>  #endif
>  
>  /*
> diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
> index d24c141..1723be3 100644
> --- a/arch/powerpc/include/asm/reg.h
> +++ b/arch/powerpc/include/asm/reg.h
> @@ -287,6 +287,7 @@
>  #define SPRN_DBAT6U	0x23C	/* Data BAT 6 Upper Register */
>  #define SPRN_DBAT7L	0x23F	/* Data BAT 7 Lower Register */
>  #define SPRN_DBAT7U	0x23E	/* Data BAT 7 Upper Register */
> +#define SPRN_PPR	0x380	/* SMT Thread status Register */
>  
>  #define SPRN_DEC	0x016		/* Decrement Register */
>  #define SPRN_DER	0x095		/* Debug Enable Regsiter */
> -- 
> 1.7.1
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* Re: [PATCH 4/6] powerpc: Define ppr in thread_struct
From: Michael Neuling @ 2012-11-23  3:21 UTC (permalink / raw)
  To: Haren Myneni; +Cc: anton, paulus, linuxppc-dev
In-Reply-To: <1351666515.32304.17.camel@hbabu-laptop>

Haren Myneni <haren@linux.vnet.ibm.com> wrote:

> [PATCH 4/6] powerpc: Define ppr in thread_struct
> 
> ppr in thread_struct is used to save PPR and restore it before process exits
> from kernel.
> 
> This patch sets the default priority to 3 when tasks are created such
> that users can use 4 for higher priority tasks.
> 
> Signed-off-by: Haren Myneni <haren@us.ibm.com>
> ---
>  arch/powerpc/include/asm/processor.h |    6 ++++++
>  arch/powerpc/kernel/asm-offsets.c    |    1 +
>  arch/powerpc/kernel/process.c        |    2 ++
>  3 files changed, 9 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h
> index 8750204..7db5df4 100644
> --- a/arch/powerpc/include/asm/processor.h
> +++ b/arch/powerpc/include/asm/processor.h
> @@ -245,6 +245,7 @@ struct thread_struct {
>  #ifdef CONFIG_PPC64
>  	unsigned long	dscr;
>  	int		dscr_inherit;
> +	unsigned long	ppr;
>  #endif
>  };
>  
> @@ -270,6 +271,10 @@ struct thread_struct {
>  	SPEFSCR_INIT \
>  }
>  #else
> +/* Default SMT priority is 3. Use 11- 13bits to save priority. */
> +/* .ppr is used to save/restore only on P7 or later processors */
> +#define INIT_PPR (3ull << 50)

Can you split this into two macros so that we can use the '3' elsewhere.

Like in patch 5, you do this:

+	lis	ra,0xc;		/* default ppr=3 */			\

where you could reuse the '3' so that we don't have to change it in two
places later.

Mikey

> +
>  #define INIT_THREAD  { \
>  	.ksp = INIT_SP, \
>  	.ksp_limit = INIT_SP_LIMIT, \
> @@ -278,6 +283,7 @@ struct thread_struct {
>  	.fpr = {{0}}, \
>  	.fpscr = { .val = 0, }, \
>  	.fpexc_mode = 0, \
> +	.ppr = INIT_PPR, \
>  }
>  #endif
>  
> diff --git a/arch/powerpc/kernel/asm-offsets.c b/arch/powerpc/kernel/asm-offsets.c
> index 7523539..41f65ec 100644
> --- a/arch/powerpc/kernel/asm-offsets.c
> +++ b/arch/powerpc/kernel/asm-offsets.c
> @@ -77,6 +77,7 @@ int main(void)
>  	DEFINE(NMI_MASK, NMI_MASK);
>  	DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
>  	DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit));
> +	DEFINE(TASKTHREADPPR, offsetof(struct task_struct, thread.ppr));
>  #else
>  	DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
>  #endif /* CONFIG_PPC64 */
> diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c
> index ba48233..2563acc 100644
> --- a/arch/powerpc/kernel/process.c
> +++ b/arch/powerpc/kernel/process.c
> @@ -814,6 +814,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
>  		p->thread.dscr_inherit = current->thread.dscr_inherit;
>  		p->thread.dscr = current->thread.dscr;
>  	}
> +	if (cpu_has_feature(CPU_FTR_HAS_PPR))
> +		p->thread.ppr = INIT_PPR;
>  #endif
>  	/*
>  	 * The PPC64 ABI makes use of a TOC to contain function 
> -- 
> 1.7.1
> 
> 
> 
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
> 

^ permalink raw reply

* [PATCH] powerpc/pseries: Fix kernel crash caused by NULL PE
From: Alexey Kardashevskiy @ 2012-11-23  2:51 UTC (permalink / raw)
  To: Benjamin Herrenschmidt
  Cc: Alexey Kardashevskiy, David Gibson, linuxppc-dev, Gavin Shan,
	linux-kernel

From: Gavin Shan <shangw@linux.vnet.ibm.com>

While hooking MSI interrupts, the corresponding device tree node
of the PE that the PCI device has been put into should be checked.
However, those PCI devices (e.g. VirtIO based PCI devices) that
don't have EEH capability shouldn't have the associated PE. So we
shouldn't try to get the PE's device tree node. Otherwise, it
would cause kernel crash.

Actually, it was introduced by commit 66523d9f ("powerpc/eeh: Trace
error based on PE from beginning").

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/platforms/pseries/msi.c |   11 +++++++++--
 1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index d19f497..9284e42 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -218,9 +218,16 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 	if (!dn)
 		return NULL;
 
-	/* Get the top level device in the PE */
+	/*
+	 * Get the top level device in the PE, but some PCI devices
+	 * without EEH capability (e.g. VirtIO based PCI devices)
+	 * don't have the associated PE. So we should not get the
+	 * top level device from PE for those PCI devices.
+	 */
 	edev = of_node_to_eeh_dev(dn);
-	edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+	if (edev->pe)
+		edev = list_first_entry(&edev->pe->edevs,
+				struct eeh_dev, list);
 	dn = eeh_dev_to_of_node(edev);
 	if (!dn)
 		return NULL;
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH] powerpc/pseries: Fix kernel crash caused by NULL PE
From: Alexey Kardashevskiy @ 2012-11-23  2:50 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, linux-kernel, David Gibson

[-- Attachment #1: Type: text/plain, Size: 1561 bytes --]

While hooking MSI interrupts, the corresponding device tree node
of the PE that the PCI device has been put into should be checked.
However, those PCI devices (e.g. VirtIO based PCI devices) that
don't have EEH capability shouldn't have the associated PE. So we
shouldn't try to get the PE's device tree node. Otherwise, it
would cause kernel crash.

Actually, it was introduced by commit 66523d9f ("powerpc/eeh: Trace
error based on PE from beginning").

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
  arch/powerpc/platforms/pseries/msi.c |   11 +++++++++--
  1 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/platforms/pseries/msi.c 
b/arch/powerpc/platforms/pseries/msi.c
index d19f497..9284e42 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -218,9 +218,16 @@ static struct device_node *find_pe_dn(struct pci_dev 
*dev, int *total)
  	if (!dn)
  		return NULL;
  -	/* Get the top level device in the PE */
+	/*
+	 * Get the top level device in the PE, but some PCI devices
+	 * without EEH capability (e.g. VirtIO based PCI devices)
+	 * don't have the associated PE. So we should not get the
+	 * top level device from PE for those PCI devices.
+	 */
  	edev = of_node_to_eeh_dev(dn);
-	edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+	if (edev->pe)
+		edev = list_first_entry(&edev->pe->edevs,
+				struct eeh_dev, list);
  	dn = eeh_dev_to_of_node(edev);
  	if (!dn)
  		return NULL;
-- 
1.7.5.4


[-- Attachment #2: Attached Message Part --]
[-- Type: text/plain, Size: 0 bytes --]



^ permalink raw reply related

* [Fwd: [PATCH] From: Gavin Shan <shangw@linux.vnet.ibm.com>]
From: Benjamin Herrenschmidt @ 2012-11-23  2:22 UTC (permalink / raw)
  To: linuxppc-dev

[-- Attachment #1: Type: text/plain, Size: 1 bytes --]



[-- Attachment #2: Forwarded message — [PATCH] From: Gavin Shan <shangw@linux.vnet.ibm.com> --]
[-- Type: message/rfc822, Size: 2869 bytes --]

From: Alexey Kardashevskiy <aik@ozlabs.ru>
To: David Gibson <david@gibson.dropbear.id.au>
Cc: Alexey Kardashevskiy <aik@ozlabs.ru>, Benjamin Herrenschmidt <benh@kernel.crashing.org>, Gavin Shan <shangw@linux.vnet.ibm.com>
Subject: [PATCH] From: Gavin Shan <shangw@linux.vnet.ibm.com>
Date: Thu, 22 Nov 2012 17:56:28 +1100
Message-ID: <1353567388-32739-1-git-send-email-aik@ozlabs.ru>

pseries msi: fixed crash on PCI devices without EEH capability

Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
---
 arch/powerpc/platforms/pseries/msi.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/platforms/pseries/msi.c b/arch/powerpc/platforms/pseries/msi.c
index d19f497..e5b0847 100644
--- a/arch/powerpc/platforms/pseries/msi.c
+++ b/arch/powerpc/platforms/pseries/msi.c
@@ -220,7 +220,8 @@ static struct device_node *find_pe_dn(struct pci_dev *dev, int *total)
 
 	/* Get the top level device in the PE */
 	edev = of_node_to_eeh_dev(dn);
-	edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
+	if (edev->pe)
+		edev = list_first_entry(&edev->pe->edevs, struct eeh_dev, list);
 	dn = eeh_dev_to_of_node(edev);
 	if (!dn)
 		return NULL;
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH] vfio powerpc: enabled and supported on powernv platform
From: Alexey Kardashevskiy @ 2012-11-23  2:02 UTC (permalink / raw)
  To: Alex Williamson
  Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Mackerras,
	Sethi Varun-B16395, linuxppc-dev@lists.ozlabs.org, David Gibson
In-Reply-To: <C5ECD7A89D1DC44195F34B25E172658D294605@039-SN2MPN1-013.039d.mgd.msft.net>

On 22/11/12 22:56, Sethi Varun-B16395 wrote:
>
>
>> -----Original Message-----
>> From: linux-kernel-owner@vger.kernel.org [mailto:linux-kernel-
>> owner@vger.kernel.org] On Behalf Of Alex Williamson
>> Sent: Tuesday, November 20, 2012 11:50 PM
>> To: Alexey Kardashevskiy
>> Cc: Benjamin Herrenschmidt; Paul Mackerras; linuxppc-
>> dev@lists.ozlabs.org; linux-kernel@vger.kernel.org; kvm@vger.kernel.org;
>> David Gibson
>> Subject: Re: [PATCH] vfio powerpc: enabled and supported on powernv
>> platform
>>
>> On Tue, 2012-11-20 at 11:48 +1100, Alexey Kardashevskiy wrote:
>>> VFIO implements platform independent stuff such as a PCI driver, BAR
>>> access (via read/write on a file descriptor or direct mapping when
>>> possible) and IRQ signaling.
>>> The platform dependent part includes IOMMU initialization and
>>> handling.
>>>
>>> This patch initializes IOMMU groups based on the IOMMU configuration
>>> discovered during the PCI scan, only POWERNV platform is supported at
>>> the moment.
>>>
>>> Also the patch implements an VFIO-IOMMU driver which manages DMA
>>> mapping/unmapping requests coming from the client (now QEMU). It also
>>> returns a DMA window information to let the guest initialize the
>>> device tree for a guest OS properly. Although this driver has been
>>> tested only on POWERNV, it should work on any platform supporting TCE
>>> tables.
>>>
>>> To enable VFIO on POWER, enable SPAPR_TCE_IOMMU config option.
>>>
>>> Cc: David Gibson <david@gibson.dropbear.id.au>
>>> Signed-off-by: Alexey Kardashevskiy <aik@ozlabs.ru>
>>> ---
>>>   arch/powerpc/include/asm/iommu.h     |    6 +
>>>   arch/powerpc/kernel/iommu.c          |  140 +++++++++++++++++++
>>>   arch/powerpc/platforms/powernv/pci.c |  135 +++++++++++++++++++
>>>   drivers/iommu/Kconfig                |    8 ++
>>>   drivers/vfio/Kconfig                 |    6 +
>>>   drivers/vfio/Makefile                |    1 +
>>>   drivers/vfio/vfio_iommu_spapr_tce.c  |  247
>> ++++++++++++++++++++++++++++++++++
>>>   include/linux/vfio.h                 |   20 +++
>>>   8 files changed, 563 insertions(+)
>>>   create mode 100644 drivers/vfio/vfio_iommu_spapr_tce.c
>>>
>>> diff --git a/arch/powerpc/include/asm/iommu.h
>>> b/arch/powerpc/include/asm/iommu.h
>>> index cbfe678..5ba66cb 100644
>>> --- a/arch/powerpc/include/asm/iommu.h
>>> +++ b/arch/powerpc/include/asm/iommu.h
>>> @@ -64,30 +64,33 @@ struct iommu_pool {  }
>>> ____cacheline_aligned_in_smp;
>>>
>>>   struct iommu_table {
>>>   	unsigned long  it_busno;     /* Bus number this table belongs to */
>>>   	unsigned long  it_size;      /* Size of iommu table in entries */
>>>   	unsigned long  it_offset;    /* Offset into global table */
>>>   	unsigned long  it_base;      /* mapped address of tce table */
>>>   	unsigned long  it_index;     /* which iommu table this is */
>>>   	unsigned long  it_type;      /* type: PCI or Virtual Bus */
>>>   	unsigned long  it_blocksize; /* Entries in each block (cacheline)
>> */
>>>   	unsigned long  poolsize;
>>>   	unsigned long  nr_pools;
>>>   	struct iommu_pool large_pool;
>>>   	struct iommu_pool pools[IOMMU_NR_POOLS];
>>>   	unsigned long *it_map;       /* A simple allocation bitmap for now
>> */
>>> +#ifdef CONFIG_IOMMU_API
>>> +	struct iommu_group *it_group;
>>> +#endif
>>>   };
>>>
>>>   struct scatterlist;
>>>
>>>   static inline void set_iommu_table_base(struct device *dev, void
>>> *base)  {
>>>   	dev->archdata.dma_data.iommu_table_base = base;  }
>>>
>>>   static inline void *get_iommu_table_base(struct device *dev)  {
>>>   	return dev->archdata.dma_data.iommu_table_base;
>>>   }
>>>
>>>   /* Frees table for an individual device node */ @@ -135,17 +138,20 @@
>>> static inline void pci_iommu_init(void) { }  extern void
>>> alloc_dart_table(void);  #if defined(CONFIG_PPC64) &&
>>> defined(CONFIG_PM)  static inline void iommu_save(void)  {
>>>   	if (ppc_md.iommu_save)
>>>   		ppc_md.iommu_save();
>>>   }
>>>
>>>   static inline void iommu_restore(void)  {
>>>   	if (ppc_md.iommu_restore)
>>>   		ppc_md.iommu_restore();
>>>   }
>>>   #endif
>>>
>>> +extern long iommu_put_tces(struct iommu_table *tbl, unsigned long
>> entry, uint64_t tce,
>>> +		enum dma_data_direction direction, unsigned long pages);
>>> +
>>>   #endif /* __KERNEL__ */
>>>   #endif /* _ASM_IOMMU_H */
>>> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
>>> index ff5a6ce..94f614b 100644
>>> --- a/arch/powerpc/kernel/iommu.c
>>> +++ b/arch/powerpc/kernel/iommu.c
>>> @@ -32,30 +32,31 @@
>>>   #include <linux/dma-mapping.h>
>>>   #include <linux/bitmap.h>
>>>   #include <linux/iommu-helper.h>
>>>   #include <linux/crash_dump.h>
>>>   #include <linux/hash.h>
>>>   #include <linux/fault-inject.h>
>>>   #include <linux/pci.h>
>>>   #include <asm/io.h>
>>>   #include <asm/prom.h>
>>>   #include <asm/iommu.h>
>>>   #include <asm/pci-bridge.h>
>>>   #include <asm/machdep.h>
>>>   #include <asm/kdump.h>
>>>   #include <asm/fadump.h>
>>>   #include <asm/vio.h>
>>> +#include <asm/tce.h>
>>>
>>>   #define DBG(...)
>>>
>>>   static int novmerge;
>>>
>>>   static void __iommu_free(struct iommu_table *, dma_addr_t, unsigned
>>> int);
>>>
>>>   static int __init setup_iommu(char *str)  {
>>>   	if (!strcmp(str, "novmerge"))
>>>   		novmerge = 1;
>>>   	else if (!strcmp(str, "vmerge"))
>>>   		novmerge = 0;
>>>   	return 1;
>>>   }
>>> @@ -844,15 +845,154 @@ void *iommu_alloc_coherent(struct device *dev,
>>> struct iommu_table *tbl,  }
>>>
>>>   void iommu_free_coherent(struct iommu_table *tbl, size_t size,
>>>   			 void *vaddr, dma_addr_t dma_handle)  {
>>>   	if (tbl) {
>>>   		unsigned int nio_pages;
>>>
>>>   		size = PAGE_ALIGN(size);
>>>   		nio_pages = size >> IOMMU_PAGE_SHIFT;
>>>   		iommu_free(tbl, dma_handle, nio_pages);
>>>   		size = PAGE_ALIGN(size);
>>>   		free_pages((unsigned long)vaddr, get_order(size));
>>>   	}
>>>   }
>>> +
>>> +#ifdef CONFIG_IOMMU_API
>>> +/*
>>> + * SPAPR TCE API
>>> + */
>>> +static struct page *free_tce(struct iommu_table *tbl, unsigned long
>>> +entry) {
>>> +	struct page *page = NULL;
>>
>> NULL initialization doesn't appear to be necessary
>>
>>> +	unsigned long oldtce;
>>> +
>>> +	oldtce = ppc_md.tce_get(tbl, entry);
>>> +
>>> +	if (!(oldtce & (TCE_PCI_WRITE | TCE_PCI_READ)))
>>> +		return NULL;
>>> +
>>> +	page = pfn_to_page(oldtce >> PAGE_SHIFT);
>>> +
>>> +	WARN_ON(!page);
>>> +	if (page && (oldtce & TCE_PCI_WRITE))
>>> +		SetPageDirty(page);
>>> +	ppc_md.tce_free(tbl, entry, 1);
>>> +
>>> +	return page;
>>> +}
>>> +
>>> +static int put_tce(struct iommu_table *tbl, unsigned long entry,
>>> +		uint64_t tce, enum dma_data_direction direction) {
>>> +	int ret;
>>> +	struct page *page = NULL;
>>> +	unsigned long kva, offset;
>>> +
>>> +	/* Map new TCE */
>>> +	offset = (tce & IOMMU_PAGE_MASK) - (tce & PAGE_MASK);
>>> +	ret = get_user_pages_fast(tce & PAGE_MASK, 1,
>>> +			direction != DMA_TO_DEVICE, &page);
>>> +	if (ret < 1) {
>>> +		printk(KERN_ERR "tce_vfio: get_user_pages_fast failed
>> tce=%llx ioba=%lx ret=%d\n",
>>> +				tce, entry << IOMMU_PAGE_SHIFT, ret);
>>> +		if (!ret)
>>> +			ret = -EFAULT;
>>
>> Missing return ret?  Otherwise we've got some bogus uses of page below
>> and we're setting ret for no reason here.
>>
>>> +	}
>>> +
>>> +	kva = (unsigned long) page_address(page);
>>> +	kva += offset;
>>> +
>>> +	/* tce_build receives a virtual address */
>>> +	entry += tbl->it_offset; /* Offset into real TCE table */
>>> +	ret = ppc_md.tce_build(tbl, entry, 1, kva, direction, NULL);
>>> +
>>> +	/* tce_build() only returns non-zero for transient errors */
>>> +	if (unlikely(ret)) {
>>> +		printk(KERN_ERR "tce_vfio: tce_put failed on tce=%llx
>> ioba=%lx kva=%lx ret=%d\n",
>>> +				tce, entry << IOMMU_PAGE_SHIFT, kva, ret);
>>> +		put_page(page);
>>> +		return -EIO;
>>> +	}
>>> +
>>> +	return 0;
>>> +}
>>> +
>>> +static void tce_flush(struct iommu_table *tbl) {
>>> +	/* Flush/invalidate TLB caches if necessary */
>>> +	if (ppc_md.tce_flush)
>>> +		ppc_md.tce_flush(tbl);
>>> +
>>> +	/* Make sure updates are seen by hardware */
>>> +	mb();
>>> +}
>>> +
>>> +long iommu_put_tces(struct iommu_table *tbl, unsigned long entry,
>> uint64_t tce,
>>> +		enum dma_data_direction direction, unsigned long pages) {
>>> +	int i, ret = 0, pages_to_put = 0;
>>> +	struct page *page;
>>> +	struct iommu_pool *pool = get_pool(tbl, entry);
>>> +	struct page **oldpages;
>>> +	const int oldpagesnum = PAGE_SIZE/sizeof(*oldpages);
>>> +
>>> +	BUILD_BUG_ON(PAGE_SIZE < IOMMU_PAGE_SIZE);
>>> +
>>> +	/* Handle a single page request without allocation
>>> +	   of pages-to-release array */
>>> +	if (pages == 1) {
>>> +		spin_lock(&(pool->lock));
>>> +		page = free_tce(tbl, entry);
>>> +
>>> +		if (direction != DMA_NONE)
>>> +			ret = put_tce(tbl, entry, tce, direction);
>>> +
>>> +		tce_flush(tbl);
>>> +
>>> +		if (page)
>>> +			put_page(page);
>>> +
>>> +		spin_unlock(&(pool->lock));
>>> +		return ret;
>>> +	}
>>> +
>>> +	/* Releasing multiple pages */
>>> +	/* Allocate an array for pages to be released after TCE table
>>> +	   is updated */
>>> +	oldpages = kmalloc(PAGE_SIZE, GFP_KERNEL);
>>> +	if (!oldpages)
>>> +		return -ENOMEM;
>>> +
>>> +	spin_lock(&(pool->lock));
>>> +
>>> +	for (i = 0; (i < pages) && !ret; ++i, ++entry, tce +=
>> IOMMU_PAGE_SIZE) {
>>> +		page = free_tce(tbl, entry);
>>> +		if (page) {
>>> +			oldpages[pages_to_put] = page;
>>> +			++pages_to_put;
>>> +		}
>>> +
>>> +		if (direction != DMA_NONE)
>>> +			ret = put_tce(tbl, entry, tce, direction);
>>> +
>>> +		/* Release old pages if we reached the end of oldpages[] or
>>> +		   it is the last page or we are about to exit the loop */
>>> +		if ((pages_to_put == oldpagesnum) || (i == pages - 1) || ret)
>> {
>>> +			tce_flush(tbl);
>>
>> Avoiding tce_flush() is the reason for all this extra overhead, right?
>> I wonder if it'd be cleaner separating map vs unmap, where the map case
>> can avoid the oldpages array... but that means inserting new mappings on
>> top of old ones wouldn't put the pages.


Yes, we do not want to loose pages if the guest forgot to unmap them.


>>> +
>>> +			/* Release pages after removing them from TCE table */
>>> +			while (pages_to_put) {
>>> +				--pages_to_put;
>>> +				put_page(oldpages[pages_to_put]);
>>> +			}
>>> +		}
>>> +	}
>>> +
>>> +	spin_unlock(&(pool->lock));
>>> +	kfree(oldpages);
>>> +
>>> +	return ret;
>>> +}
>>> +EXPORT_SYMBOL_GPL(iommu_put_tces);
>>> +#endif /* CONFIG_IOMMU_API */
>>> diff --git a/arch/powerpc/platforms/powernv/pci.c
>>> b/arch/powerpc/platforms/powernv/pci.c
>>> index 05205cf..676f4d9 100644
>>> --- a/arch/powerpc/platforms/powernv/pci.c
>>> +++ b/arch/powerpc/platforms/powernv/pci.c
>>> @@ -8,30 +8,31 @@
>>>    * 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.
>>>    */
>>>
>>>   #include <linux/kernel.h>
>>>   #include <linux/pci.h>
>>>   #include <linux/delay.h>
>>>   #include <linux/string.h>
>>>   #include <linux/init.h>
>>>   #include <linux/bootmem.h>
>>>   #include <linux/irq.h>
>>>   #include <linux/io.h>
>>>   #include <linux/msi.h>
>>> +#include <linux/iommu.h>
>>>
>>>   #include <asm/sections.h>
>>>   #include <asm/io.h>
>>>   #include <asm/prom.h>
>>>   #include <asm/pci-bridge.h>
>>>   #include <asm/machdep.h>
>>>   #include <asm/ppc-pci.h>
>>>   #include <asm/opal.h>
>>>   #include <asm/iommu.h>
>>>   #include <asm/tce.h>
>>>   #include <asm/abs_addr.h>
>>>   #include <asm/firmware.h>
>>>
>>>   #include "powernv.h"
>>>   #include "pci.h"
>>> @@ -601,15 +602,149 @@ void __init pnv_pci_init(void)
>>>   	/* Configure IOMMU DMA hooks */
>>>   	ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
>>>   	ppc_md.tce_build = pnv_tce_build;
>>>   	ppc_md.tce_free = pnv_tce_free;
>>>   	ppc_md.tce_get = pnv_tce_get;
>>>   	ppc_md.pci_probe_mode = pnv_pci_probe_mode;
>>>   	set_pci_dma_ops(&dma_iommu_ops);
>>>
>>>   	/* Configure MSIs */
>>>   #ifdef CONFIG_PCI_MSI
>>>   	ppc_md.msi_check_device = pnv_msi_check_device;
>>>   	ppc_md.setup_msi_irqs = pnv_setup_msi_irqs;
>>>   	ppc_md.teardown_msi_irqs = pnv_teardown_msi_irqs;  #endif  }
>>> +
>>> +#ifdef CONFIG_IOMMU_API
>>> +/*
>>> + * IOMMU groups support required by VFIO  */ static int
>>> +add_device(struct device *dev) {
>>> +	struct iommu_table *tbl;
>>> +	int ret = 0;
>>> +
>>> +	if (WARN_ON(dev->iommu_group)) {
>>> +		printk(KERN_WARNING "tce_vfio: device %s is already in iommu
>> group %d, skipping\n",
>>> +				dev->kobj.name,
>>
>> dev_name(dev)
>>
>>> +				iommu_group_id(dev->iommu_group));
>>> +		return -EBUSY;
>>> +	}
>>> +
>>> +	tbl = get_iommu_table_base(dev);
>>> +	if (!tbl) {
>>> +		pr_debug("tce_vfio: skipping device %s with no tbl\n",
>>> +				dev->kobj.name);
>>> +		return 0;
>>> +	}
>>> +
>>> +	pr_debug("tce_vfio: adding %s to iommu group %d\n",
>>> +			dev->kobj.name, iommu_group_id(tbl->it_group));
>>> +
>>> +	ret = iommu_group_add_device(tbl->it_group, dev);
>>> +	if (ret < 0)
>>> +		printk(KERN_ERR "tce_vfio: %s has not been added, ret=%d\n",
>>> +				dev->kobj.name, ret);
>>> +
>>> +	return ret;
>>> +}
>>> +
>>> +static void del_device(struct device *dev) {
>>> +	iommu_group_remove_device(dev);
>>> +}
>>> +
>>> +static int iommu_bus_notifier(struct notifier_block *nb,
>>> +			      unsigned long action, void *data) {
>>> +	struct device *dev = data;
>>> +
>>> +	switch (action) {
>>> +	case BUS_NOTIFY_ADD_DEVICE:
>>> +		return add_device(dev);
>>> +	case BUS_NOTIFY_DEL_DEVICE:
>>> +		del_device(dev);
>>> +		return 0;
>>> +	default:
>>> +		return 0;
>>> +	}
>>> +}
>>> +
>>> +static struct notifier_block tce_iommu_bus_nb = {
>>> +	.notifier_call = iommu_bus_notifier, };
>>> +
>>> +static void group_release(void *iommu_data) {
>>> +	struct iommu_table *tbl = iommu_data;
>>> +	tbl->it_group = NULL;
>>> +}
>>> +
>>> +static int __init tce_iommu_init(void) {
>>> +	struct pci_dev *pdev = NULL;
>>> +	struct iommu_table *tbl;
>>> +	struct iommu_group *grp;
>>> +
>>> +	bus_register_notifier(&pci_bus_type, &tce_iommu_bus_nb);
>>
>> There's already a notifier in the iommu code if you were to register an
>> iommu_ops with the add/remove_device entries.  That would allow you to
>> remove the notifier block and notifier function below and the second loop
>> below.  Are you avoiding that to avoid the rest of iommu_ops?

Yes. I need to implement either a small part of iommu_ops (especially the 
part which I think should not be there at all) or notifier, cannot how how 
the first is simpler.


> [Sethi Varun-B16395] Could be one reason, also they are associating the iommu group with the tce table entry and not the device.

Also true.
I would actually allocate IOMMU groups right after we discovered the new 
one but this is done during PCI scan which works before 
subsys_initcall(iommu_init) is called so I added this first loop.


>> Also, shouldn't this notifier only be registered after the first loop
>> below?  Otherwise ADD_DEVICE could race with setting up groups, which we
>> assume are present in the add_device() above.
> [Sethi Varun-B16395] Isn't this similar to how how the notifier is registered in iommu_bus_init? First a notifier is registered and then we check for devices that have already been probed.

Yep. Not very familiar with this stuff but if it is done one way and it is 
already upstream, I cannot see why I should go another way :)



-- 
Alexey

^ permalink raw reply

* Re: [PATCH 065/493] i2c: remove use of __devexit_p
From: Wolfram Sang @ 2012-11-22 21:49 UTC (permalink / raw)
  To: Jean Delvare
  Cc: Rudolf Marek, Tony Lindgren, gregkh, Mark M. Hoffman, linux-omap,
	Bill Pemberton, linux-i2c, Ben Dooks, Barry Song, Olof Johansson,
	Guan Xuetao, linuxppc-dev, linux-arm-kernel
In-Reply-To: <20121120144621.5d2c213a@endymion.delvare>

[-- Attachment #1: Type: text/plain, Size: 1013 bytes --]

On Tue, Nov 20, 2012 at 02:46:21PM +0100, Jean Delvare wrote:
> On Mon, 19 Nov 2012 13:20:14 -0500, Bill Pemberton wrote:
> > CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
> > needed.
> 
> As mentioned on the lm-sensors list for hwmon patches already, I think
> it would be much clearer to not split __devexit, __devexit_p, __devinit
> etc. removal into separate patches. One patch per subsystem would be
> easier to review and apply. If patches grow too large then you'd rather
> split in a different direction, for example drivers/i2c/muxes vs.
> drivers/i2c/busses or even grouped by related bus drivers (see entries
> "I2C OVER PARALLEL PORT" and "I2C/SMBUS CONTROLLER DRIVERS FOR PC" in
> MAINTAINERS for examples of meaningful groups.)

I agree with Jean here. Is there a V2 planned? With a change like this?

-- 
Pengutronix e.K.                           | Wolfram Sang                |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 198 bytes --]

^ permalink raw reply

* Re: [PATCH 056/493] edac: remove use of __devexit_p
From: Greg KH @ 2012-11-22 18:22 UTC (permalink / raw)
  To: Borislav Petkov
  Cc: Arvind R., Mark Gross, Mauro Carvalho Chehab, Jason Uhlenkott,
	Ranganathan Desikan, Bill Pemberton, Egor Martovetsky,
	Doug Thompson, Olof Johansson, linux-edac, linuxppc-dev,
	Tim Small
In-Reply-To: <20121122134451.GG17147@x1.alien8.de>

On Thu, Nov 22, 2012 at 02:44:51PM +0100, Borislav Petkov wrote:
> On Mon, Nov 19, 2012 at 01:20:05PM -0500, Bill Pemberton wrote:
> > CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
> > needed.
> 
> Erm, I don't understand. __devexit_p is defined also for modules not
> only for CONFIG_HOTPLUG:
> 
> #if defined(MODULE) || defined(CONFIG_HOTPLUG)
> #define __devexit_p(x) x
> #else
> #define __devexit_p(x) NULL
> #endif
> 
> AFAICT, we cannot remove it yet no?

If MODULE is defined, it defaults to nothing.  And now that
CONFIG_HOTPLUG is always set to Y, this always defaults to nothing.

So it's not set to anything anymore, so it can be removed and then this
whole define chunk can be removed.

thanks,

greg k-h

^ permalink raw reply

* Re: [PATCH 056/493] edac: remove use of __devexit_p
From: Borislav Petkov @ 2012-11-22 13:44 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: Arvind R., Mark Gross, Mauro Carvalho Chehab, Jason Uhlenkott,
	gregkh, Ranganathan Desikan, Egor Martovetsky, Doug Thompson,
	Olof Johansson, linux-edac, linuxppc-dev, Tim Small
In-Reply-To: <1353349642-3677-56-git-send-email-wfp5p@virginia.edu>

On Mon, Nov 19, 2012 at 01:20:05PM -0500, Bill Pemberton wrote:
> CONFIG_HOTPLUG is going away as an option so __devexit_p is no longer
> needed.

Erm, I don't understand. __devexit_p is defined also for modules not
only for CONFIG_HOTPLUG:

#if defined(MODULE) || defined(CONFIG_HOTPLUG)
#define __devexit_p(x) x
#else
#define __devexit_p(x) NULL
#endif

AFAICT, we cannot remove it yet no?

Thanks.

-- 
Regards/Gruss,
Boris.

^ permalink raw reply

* problem with mpc8536 and kernel 2.6.32 and interrupts
From: Koen Swinters @ 2012-11-22 12:12 UTC (permalink / raw)
  To: linuxppc-dev@lists.ozlabs.org

Hi all,

I have a problem. This is on a MPC8536 based platform with 36-bit address s=
pace and linux kernel 2.6.32 (32bit).
after X time we get coredumps from userspace applications(random):

one of the coredumps:
****************************************************
GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.htm=
l>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "powerpc-none-linux-gnuspe"...

warning: core file may not match specified executable file.

warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libm.so.6...done.
Loaded symbols for /lib/libm.so.6
Reading symbols from /lib/libc.so.6...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld.so.1...done.
Loaded symbols for /lib/ld.so.1
Core was generated by `wc -l'.
Program terminated with signal 11, Segmentation fault.
[New process 4782]
#0  0x4800e778 in call_init () from /lib/ld.so.1
(gdb) bt
#0  0x4800e778 in call_init () from /lib/ld.so.1
#1  0x4800e9d8 in _dl_init_internal () from /lib/ld.so.1
#2  0x48015fc8 in _start () from /lib/ld.so.1
Backtrace stopped: frame did not save the PC
(gdb) info frame
Stack level 0, frame at 0xbfc4bc70:
 pc =3D 0x4800e778 in call_init; saved pc 0x4800e9d8
 called by frame at 0xbfc4bca0
 Arglist at 0xbfc4bc40, args:=20
 Locals at 0xbfc4bc40, Previous frame's sp is 0xbfc4bc70
 Saved registers:
  r25 at 0xbfc4bc54, r26 at 0xbfc4bc58, r27 at 0xbfc4bc5c, r28 at 0xbfc4bc6=
0,
  r29 at 0xbfc4bc64, r30 at 0xbfc4bc68, r31 at 0xbfc4bc6c, pc at 0xbfc4bc74=
,
  lr at 0xbfc4bc74
(gdb) frame
#0  0x4800e778 in call_init () from /lib/ld.so.1
(gdb) frame 0
#0  0x4800e778 in call_init () from /lib/ld.so.1
(gdb) frame 1
#1  0x4800e9d8 in _dl_init_internal () from /lib/ld.so.1
(gdb) frame 2
#2  0x48015fc8 in _start () from /lib/ld.so.1
(gdb) frame 3
#0  0x00000000 in ?? ()
(gdb)=20

*************************************************

another cordump is:

GNU gdb 6.8
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.htm=
l>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "powerpc-none-linux-gnuspe"...

warning: core file may not match specified executable file.
Core was generated by `/bin/bash /usr/bin/check_apps'.
Program terminated with signal 11, Segmentation fault.
[New process 7823]
#0  0x10057ae8 in print_stats_cpu_struct (stats=3D0x100c3008)
    at procps/iostat.c:247
247     procps/iostat.c: No such file or directory.
        in procps/iostat.c
(gdb) bt
#0  0x10057ae8 in print_stats_cpu_struct (stats=3D0x100c3008)
    at procps/iostat.c:247
#1  0x100b5c68 in nvalloc (n=3D269193816) at editors/awk.c:933
#2  0x4801fab8 in ?? ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)
(gdb) info frame
Stack level 0, frame at 0xbfb395a0:
 pc =3D 0x10057ae8 in print_stats_cpu_struct (procps/iostat.c:247);=20
    saved pc 0x100b5c68
 called by frame at 0xbfb395d0
 source language c.
 Arglist at 0xbfb394e0, args: stats=3D0x100c3008
 Locals at 0xbfb394e0, Previous frame's sp is 0xbfb395a0
 Saved registers:
  r25 at 0xbfb3956c, r26 at 0xbfb39574, r27 at 0xbfb3957c, r28 at 0xbfb3958=
4,
  r29 at 0xbfb3958c, pc at 0xbfb395a4, lr at 0xbfb395a4, ev25 at 0xbfb39568=
,
  ev26 at 0xbfb39570, ev27 at 0xbfb39578, ev28 at 0xbfb39580,
  ev29 at 0xbfb39588
(gdb) info frame 1
Stack frame at 0xbfb395d0:
 pc =3D 0x100b5c68 in nvalloc (editors/awk.c:933); saved pc 0x4801fab8
 called by frame at 0x12, caller of frame at 0xbfb395a0
 source language c.
 Arglist at 0xbfb395a0, args: n=3D269193816
 Locals at 0xbfb395a0, Previous frame's sp is 0xbfb395d0
 Saved registers:
  r29 at 0xbfb395c4, pc at 0xbfb395d4, lr at 0xbfb395d4
(gdb) info frame 2
Stack frame at 0x12:
 pc =3D 0x4801fab8; saved pc Cannot access memory at address 0x16
(gdb) info frame 3
Stack frame at 0x3:
 pc =3D 0x0; saved pc 0xfe7bcc8
 Outermost frame: unwinder did not report frame ID
 Arglist at 0xbfb394e0, args:=20
 Locals at 0xbfb394e0, Previous frame's sp is 0xbfb394e0
(gdb) info frame 4
Stack frame at 0x4:
 pc =3D 0x0; saved pc 0xfe7bcc8
 Outermost frame: unwinder did not report frame ID
 Arglist at 0xbfb394e0, args:=20
 Locals at 0xbfb394e0, Previous frame's sp is 0xbfb394e0
(gdb)=20

******************************************************************



We have a module from broadcom loaded that makes use of interrupts via PCI =
and interrupt driver FSL-MSI . When we disable this interrupt the coredumps=
 dissapear.
I`ve tried the following patch: 78e2e68a2b79f394b7cd61e07987a8a89af907f7. B=
ut is does not fix this problem.
Does some-one know what is happenging here.


Thanks,

Koen

^ permalink raw reply

* RE: [PATCH] vfio powerpc: enabled and supported on powernv platform
From: Sethi Varun-B16395 @ 2012-11-22 11:56 UTC (permalink / raw)
  To: Alex Williamson, Alexey Kardashevskiy
  Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Paul Mackerras,
	linuxppc-dev@lists.ozlabs.org, David Gibson
In-Reply-To: <1353435584.2234.87.camel@bling.home>

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogbGludXgta2VybmVsLW93
bmVyQHZnZXIua2VybmVsLm9yZyBbbWFpbHRvOmxpbnV4LWtlcm5lbC0NCj4gb3duZXJAdmdlci5r
ZXJuZWwub3JnXSBPbiBCZWhhbGYgT2YgQWxleCBXaWxsaWFtc29uDQo+IFNlbnQ6IFR1ZXNkYXks
IE5vdmVtYmVyIDIwLCAyMDEyIDExOjUwIFBNDQo+IFRvOiBBbGV4ZXkgS2FyZGFzaGV2c2tpeQ0K
PiBDYzogQmVuamFtaW4gSGVycmVuc2NobWlkdDsgUGF1bCBNYWNrZXJyYXM7IGxpbnV4cHBjLQ0K
PiBkZXZAbGlzdHMub3psYWJzLm9yZzsgbGludXgta2VybmVsQHZnZXIua2VybmVsLm9yZzsga3Zt
QHZnZXIua2VybmVsLm9yZzsNCj4gRGF2aWQgR2lic29uDQo+IFN1YmplY3Q6IFJlOiBbUEFUQ0hd
IHZmaW8gcG93ZXJwYzogZW5hYmxlZCBhbmQgc3VwcG9ydGVkIG9uIHBvd2VybnYNCj4gcGxhdGZv
cm0NCj4gDQo+IE9uIFR1ZSwgMjAxMi0xMS0yMCBhdCAxMTo0OCArMTEwMCwgQWxleGV5IEthcmRh
c2hldnNraXkgd3JvdGU6DQo+ID4gVkZJTyBpbXBsZW1lbnRzIHBsYXRmb3JtIGluZGVwZW5kZW50
IHN0dWZmIHN1Y2ggYXMgYSBQQ0kgZHJpdmVyLCBCQVINCj4gPiBhY2Nlc3MgKHZpYSByZWFkL3dy
aXRlIG9uIGEgZmlsZSBkZXNjcmlwdG9yIG9yIGRpcmVjdCBtYXBwaW5nIHdoZW4NCj4gPiBwb3Nz
aWJsZSkgYW5kIElSUSBzaWduYWxpbmcuDQo+ID4gVGhlIHBsYXRmb3JtIGRlcGVuZGVudCBwYXJ0
IGluY2x1ZGVzIElPTU1VIGluaXRpYWxpemF0aW9uIGFuZA0KPiA+IGhhbmRsaW5nLg0KPiA+DQo+
ID4gVGhpcyBwYXRjaCBpbml0aWFsaXplcyBJT01NVSBncm91cHMgYmFzZWQgb24gdGhlIElPTU1V
IGNvbmZpZ3VyYXRpb24NCj4gPiBkaXNjb3ZlcmVkIGR1cmluZyB0aGUgUENJIHNjYW4sIG9ubHkg
UE9XRVJOViBwbGF0Zm9ybSBpcyBzdXBwb3J0ZWQgYXQNCj4gPiB0aGUgbW9tZW50Lg0KPiA+DQo+
ID4gQWxzbyB0aGUgcGF0Y2ggaW1wbGVtZW50cyBhbiBWRklPLUlPTU1VIGRyaXZlciB3aGljaCBt
YW5hZ2VzIERNQQ0KPiA+IG1hcHBpbmcvdW5tYXBwaW5nIHJlcXVlc3RzIGNvbWluZyBmcm9tIHRo
ZSBjbGllbnQgKG5vdyBRRU1VKS4gSXQgYWxzbw0KPiA+IHJldHVybnMgYSBETUEgd2luZG93IGlu
Zm9ybWF0aW9uIHRvIGxldCB0aGUgZ3Vlc3QgaW5pdGlhbGl6ZSB0aGUNCj4gPiBkZXZpY2UgdHJl
ZSBmb3IgYSBndWVzdCBPUyBwcm9wZXJseS4gQWx0aG91Z2ggdGhpcyBkcml2ZXIgaGFzIGJlZW4N
Cj4gPiB0ZXN0ZWQgb25seSBvbiBQT1dFUk5WLCBpdCBzaG91bGQgd29yayBvbiBhbnkgcGxhdGZv
cm0gc3VwcG9ydGluZyBUQ0UNCj4gPiB0YWJsZXMuDQo+ID4NCj4gPiBUbyBlbmFibGUgVkZJTyBv
biBQT1dFUiwgZW5hYmxlIFNQQVBSX1RDRV9JT01NVSBjb25maWcgb3B0aW9uLg0KPiA+DQo+ID4g
Q2M6IERhdmlkIEdpYnNvbiA8ZGF2aWRAZ2lic29uLmRyb3BiZWFyLmlkLmF1Pg0KPiA+IFNpZ25l
ZC1vZmYtYnk6IEFsZXhleSBLYXJkYXNoZXZza2l5IDxhaWtAb3psYWJzLnJ1Pg0KPiA+IC0tLQ0K
PiA+ICBhcmNoL3Bvd2VycGMvaW5jbHVkZS9hc20vaW9tbXUuaCAgICAgfCAgICA2ICsNCj4gPiAg
YXJjaC9wb3dlcnBjL2tlcm5lbC9pb21tdS5jICAgICAgICAgIHwgIDE0MCArKysrKysrKysrKysr
KysrKysrDQo+ID4gIGFyY2gvcG93ZXJwYy9wbGF0Zm9ybXMvcG93ZXJudi9wY2kuYyB8ICAxMzUg
KysrKysrKysrKysrKysrKysrKw0KPiA+ICBkcml2ZXJzL2lvbW11L0tjb25maWcgICAgICAgICAg
ICAgICAgfCAgICA4ICsrDQo+ID4gIGRyaXZlcnMvdmZpby9LY29uZmlnICAgICAgICAgICAgICAg
ICB8ICAgIDYgKw0KPiA+ICBkcml2ZXJzL3ZmaW8vTWFrZWZpbGUgICAgICAgICAgICAgICAgfCAg
ICAxICsNCj4gPiAgZHJpdmVycy92ZmlvL3ZmaW9faW9tbXVfc3BhcHJfdGNlLmMgIHwgIDI0Nw0K
PiArKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrDQo+ID4gIGluY2x1ZGUvbGludXgv
dmZpby5oICAgICAgICAgICAgICAgICB8ICAgMjAgKysrDQo+ID4gIDggZmlsZXMgY2hhbmdlZCwg
NTYzIGluc2VydGlvbnMoKykNCj4gPiAgY3JlYXRlIG1vZGUgMTAwNjQ0IGRyaXZlcnMvdmZpby92
ZmlvX2lvbW11X3NwYXByX3RjZS5jDQo+ID4NCj4gPiBkaWZmIC0tZ2l0IGEvYXJjaC9wb3dlcnBj
L2luY2x1ZGUvYXNtL2lvbW11LmgNCj4gPiBiL2FyY2gvcG93ZXJwYy9pbmNsdWRlL2FzbS9pb21t
dS5oDQo+ID4gaW5kZXggY2JmZTY3OC4uNWJhNjZjYiAxMDA2NDQNCj4gPiAtLS0gYS9hcmNoL3Bv
d2VycGMvaW5jbHVkZS9hc20vaW9tbXUuaA0KPiA+ICsrKyBiL2FyY2gvcG93ZXJwYy9pbmNsdWRl
L2FzbS9pb21tdS5oDQo+ID4gQEAgLTY0LDMwICs2NCwzMyBAQCBzdHJ1Y3QgaW9tbXVfcG9vbCB7
ICB9DQo+ID4gX19fX2NhY2hlbGluZV9hbGlnbmVkX2luX3NtcDsNCj4gPg0KPiA+ICBzdHJ1Y3Qg
aW9tbXVfdGFibGUgew0KPiA+ICAJdW5zaWduZWQgbG9uZyAgaXRfYnVzbm87ICAgICAvKiBCdXMg
bnVtYmVyIHRoaXMgdGFibGUgYmVsb25ncyB0byAqLw0KPiA+ICAJdW5zaWduZWQgbG9uZyAgaXRf
c2l6ZTsgICAgICAvKiBTaXplIG9mIGlvbW11IHRhYmxlIGluIGVudHJpZXMgKi8NCj4gPiAgCXVu
c2lnbmVkIGxvbmcgIGl0X29mZnNldDsgICAgLyogT2Zmc2V0IGludG8gZ2xvYmFsIHRhYmxlICov
DQo+ID4gIAl1bnNpZ25lZCBsb25nICBpdF9iYXNlOyAgICAgIC8qIG1hcHBlZCBhZGRyZXNzIG9m
IHRjZSB0YWJsZSAqLw0KPiA+ICAJdW5zaWduZWQgbG9uZyAgaXRfaW5kZXg7ICAgICAvKiB3aGlj
aCBpb21tdSB0YWJsZSB0aGlzIGlzICovDQo+ID4gIAl1bnNpZ25lZCBsb25nICBpdF90eXBlOyAg
ICAgIC8qIHR5cGU6IFBDSSBvciBWaXJ0dWFsIEJ1cyAqLw0KPiA+ICAJdW5zaWduZWQgbG9uZyAg
aXRfYmxvY2tzaXplOyAvKiBFbnRyaWVzIGluIGVhY2ggYmxvY2sgKGNhY2hlbGluZSkNCj4gKi8N
Cj4gPiAgCXVuc2lnbmVkIGxvbmcgIHBvb2xzaXplOw0KPiA+ICAJdW5zaWduZWQgbG9uZyAgbnJf
cG9vbHM7DQo+ID4gIAlzdHJ1Y3QgaW9tbXVfcG9vbCBsYXJnZV9wb29sOw0KPiA+ICAJc3RydWN0
IGlvbW11X3Bvb2wgcG9vbHNbSU9NTVVfTlJfUE9PTFNdOw0KPiA+ICAJdW5zaWduZWQgbG9uZyAq
aXRfbWFwOyAgICAgICAvKiBBIHNpbXBsZSBhbGxvY2F0aW9uIGJpdG1hcCBmb3Igbm93DQo+ICov
DQo+ID4gKyNpZmRlZiBDT05GSUdfSU9NTVVfQVBJDQo+ID4gKwlzdHJ1Y3QgaW9tbXVfZ3JvdXAg
Kml0X2dyb3VwOw0KPiA+ICsjZW5kaWYNCj4gPiAgfTsNCj4gPg0KPiA+ICBzdHJ1Y3Qgc2NhdHRl
cmxpc3Q7DQo+ID4NCj4gPiAgc3RhdGljIGlubGluZSB2b2lkIHNldF9pb21tdV90YWJsZV9iYXNl
KHN0cnVjdCBkZXZpY2UgKmRldiwgdm9pZA0KPiA+ICpiYXNlKSAgew0KPiA+ICAJZGV2LT5hcmNo
ZGF0YS5kbWFfZGF0YS5pb21tdV90YWJsZV9iYXNlID0gYmFzZTsgIH0NCj4gPg0KPiA+ICBzdGF0
aWMgaW5saW5lIHZvaWQgKmdldF9pb21tdV90YWJsZV9iYXNlKHN0cnVjdCBkZXZpY2UgKmRldikg
IHsNCj4gPiAgCXJldHVybiBkZXYtPmFyY2hkYXRhLmRtYV9kYXRhLmlvbW11X3RhYmxlX2Jhc2U7
DQo+ID4gIH0NCj4gPg0KPiA+ICAvKiBGcmVlcyB0YWJsZSBmb3IgYW4gaW5kaXZpZHVhbCBkZXZp
Y2Ugbm9kZSAqLyBAQCAtMTM1LDE3ICsxMzgsMjAgQEANCj4gPiBzdGF0aWMgaW5saW5lIHZvaWQg
cGNpX2lvbW11X2luaXQodm9pZCkgeyB9ICBleHRlcm4gdm9pZA0KPiA+IGFsbG9jX2RhcnRfdGFi
bGUodm9pZCk7ICAjaWYgZGVmaW5lZChDT05GSUdfUFBDNjQpICYmDQo+ID4gZGVmaW5lZChDT05G
SUdfUE0pICBzdGF0aWMgaW5saW5lIHZvaWQgaW9tbXVfc2F2ZSh2b2lkKSAgew0KPiA+ICAJaWYg
KHBwY19tZC5pb21tdV9zYXZlKQ0KPiA+ICAJCXBwY19tZC5pb21tdV9zYXZlKCk7DQo+ID4gIH0N
Cj4gPg0KPiA+ICBzdGF0aWMgaW5saW5lIHZvaWQgaW9tbXVfcmVzdG9yZSh2b2lkKSAgew0KPiA+
ICAJaWYgKHBwY19tZC5pb21tdV9yZXN0b3JlKQ0KPiA+ICAJCXBwY19tZC5pb21tdV9yZXN0b3Jl
KCk7DQo+ID4gIH0NCj4gPiAgI2VuZGlmDQo+ID4NCj4gPiArZXh0ZXJuIGxvbmcgaW9tbXVfcHV0
X3RjZXMoc3RydWN0IGlvbW11X3RhYmxlICp0YmwsIHVuc2lnbmVkIGxvbmcNCj4gZW50cnksIHVp
bnQ2NF90IHRjZSwNCj4gPiArCQllbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXJlY3Rpb24sIHVu
c2lnbmVkIGxvbmcgcGFnZXMpOw0KPiA+ICsNCj4gPiAgI2VuZGlmIC8qIF9fS0VSTkVMX18gKi8N
Cj4gPiAgI2VuZGlmIC8qIF9BU01fSU9NTVVfSCAqLw0KPiA+IGRpZmYgLS1naXQgYS9hcmNoL3Bv
d2VycGMva2VybmVsL2lvbW11LmMgYi9hcmNoL3Bvd2VycGMva2VybmVsL2lvbW11LmMNCj4gPiBp
bmRleCBmZjVhNmNlLi45NGY2MTRiIDEwMDY0NA0KPiA+IC0tLSBhL2FyY2gvcG93ZXJwYy9rZXJu
ZWwvaW9tbXUuYw0KPiA+ICsrKyBiL2FyY2gvcG93ZXJwYy9rZXJuZWwvaW9tbXUuYw0KPiA+IEBA
IC0zMiwzMCArMzIsMzEgQEANCj4gPiAgI2luY2x1ZGUgPGxpbnV4L2RtYS1tYXBwaW5nLmg+DQo+
ID4gICNpbmNsdWRlIDxsaW51eC9iaXRtYXAuaD4NCj4gPiAgI2luY2x1ZGUgPGxpbnV4L2lvbW11
LWhlbHBlci5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvY3Jhc2hfZHVtcC5oPg0KPiA+ICAjaW5j
bHVkZSA8bGludXgvaGFzaC5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvZmF1bHQtaW5qZWN0Lmg+
DQo+ID4gICNpbmNsdWRlIDxsaW51eC9wY2kuaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9pby5oPg0K
PiA+ICAjaW5jbHVkZSA8YXNtL3Byb20uaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9pb21tdS5oPg0K
PiA+ICAjaW5jbHVkZSA8YXNtL3BjaS1icmlkZ2UuaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9tYWNo
ZGVwLmg+DQo+ID4gICNpbmNsdWRlIDxhc20va2R1bXAuaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9m
YWR1bXAuaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS92aW8uaD4NCj4gPiArI2luY2x1ZGUgPGFzbS90
Y2UuaD4NCj4gPg0KPiA+ICAjZGVmaW5lIERCRyguLi4pDQo+ID4NCj4gPiAgc3RhdGljIGludCBu
b3ZtZXJnZTsNCj4gPg0KPiA+ICBzdGF0aWMgdm9pZCBfX2lvbW11X2ZyZWUoc3RydWN0IGlvbW11
X3RhYmxlICosIGRtYV9hZGRyX3QsIHVuc2lnbmVkDQo+ID4gaW50KTsNCj4gPg0KPiA+ICBzdGF0
aWMgaW50IF9faW5pdCBzZXR1cF9pb21tdShjaGFyICpzdHIpICB7DQo+ID4gIAlpZiAoIXN0cmNt
cChzdHIsICJub3ZtZXJnZSIpKQ0KPiA+ICAJCW5vdm1lcmdlID0gMTsNCj4gPiAgCWVsc2UgaWYg
KCFzdHJjbXAoc3RyLCAidm1lcmdlIikpDQo+ID4gIAkJbm92bWVyZ2UgPSAwOw0KPiA+ICAJcmV0
dXJuIDE7DQo+ID4gIH0NCj4gPiBAQCAtODQ0LDE1ICs4NDUsMTU0IEBAIHZvaWQgKmlvbW11X2Fs
bG9jX2NvaGVyZW50KHN0cnVjdCBkZXZpY2UgKmRldiwNCj4gPiBzdHJ1Y3QgaW9tbXVfdGFibGUg
KnRibCwgIH0NCj4gPg0KPiA+ICB2b2lkIGlvbW11X2ZyZWVfY29oZXJlbnQoc3RydWN0IGlvbW11
X3RhYmxlICp0YmwsIHNpemVfdCBzaXplLA0KPiA+ICAJCQkgdm9pZCAqdmFkZHIsIGRtYV9hZGRy
X3QgZG1hX2hhbmRsZSkgIHsNCj4gPiAgCWlmICh0YmwpIHsNCj4gPiAgCQl1bnNpZ25lZCBpbnQg
bmlvX3BhZ2VzOw0KPiA+DQo+ID4gIAkJc2l6ZSA9IFBBR0VfQUxJR04oc2l6ZSk7DQo+ID4gIAkJ
bmlvX3BhZ2VzID0gc2l6ZSA+PiBJT01NVV9QQUdFX1NISUZUOw0KPiA+ICAJCWlvbW11X2ZyZWUo
dGJsLCBkbWFfaGFuZGxlLCBuaW9fcGFnZXMpOw0KPiA+ICAJCXNpemUgPSBQQUdFX0FMSUdOKHNp
emUpOw0KPiA+ICAJCWZyZWVfcGFnZXMoKHVuc2lnbmVkIGxvbmcpdmFkZHIsIGdldF9vcmRlcihz
aXplKSk7DQo+ID4gIAl9DQo+ID4gIH0NCj4gPiArDQo+ID4gKyNpZmRlZiBDT05GSUdfSU9NTVVf
QVBJDQo+ID4gKy8qDQo+ID4gKyAqIFNQQVBSIFRDRSBBUEkNCj4gPiArICovDQo+ID4gK3N0YXRp
YyBzdHJ1Y3QgcGFnZSAqZnJlZV90Y2Uoc3RydWN0IGlvbW11X3RhYmxlICp0YmwsIHVuc2lnbmVk
IGxvbmcNCj4gPiArZW50cnkpIHsNCj4gPiArCXN0cnVjdCBwYWdlICpwYWdlID0gTlVMTDsNCj4g
DQo+IE5VTEwgaW5pdGlhbGl6YXRpb24gZG9lc24ndCBhcHBlYXIgdG8gYmUgbmVjZXNzYXJ5DQo+
IA0KPiA+ICsJdW5zaWduZWQgbG9uZyBvbGR0Y2U7DQo+ID4gKw0KPiA+ICsJb2xkdGNlID0gcHBj
X21kLnRjZV9nZXQodGJsLCBlbnRyeSk7DQo+ID4gKw0KPiA+ICsJaWYgKCEob2xkdGNlICYgKFRD
RV9QQ0lfV1JJVEUgfCBUQ0VfUENJX1JFQUQpKSkNCj4gPiArCQlyZXR1cm4gTlVMTDsNCj4gPiAr
DQo+ID4gKwlwYWdlID0gcGZuX3RvX3BhZ2Uob2xkdGNlID4+IFBBR0VfU0hJRlQpOw0KPiA+ICsN
Cj4gPiArCVdBUk5fT04oIXBhZ2UpOw0KPiA+ICsJaWYgKHBhZ2UgJiYgKG9sZHRjZSAmIFRDRV9Q
Q0lfV1JJVEUpKQ0KPiA+ICsJCVNldFBhZ2VEaXJ0eShwYWdlKTsNCj4gPiArCXBwY19tZC50Y2Vf
ZnJlZSh0YmwsIGVudHJ5LCAxKTsNCj4gPiArDQo+ID4gKwlyZXR1cm4gcGFnZTsNCj4gPiArfQ0K
PiA+ICsNCj4gPiArc3RhdGljIGludCBwdXRfdGNlKHN0cnVjdCBpb21tdV90YWJsZSAqdGJsLCB1
bnNpZ25lZCBsb25nIGVudHJ5LA0KPiA+ICsJCXVpbnQ2NF90IHRjZSwgZW51bSBkbWFfZGF0YV9k
aXJlY3Rpb24gZGlyZWN0aW9uKSB7DQo+ID4gKwlpbnQgcmV0Ow0KPiA+ICsJc3RydWN0IHBhZ2Ug
KnBhZ2UgPSBOVUxMOw0KPiA+ICsJdW5zaWduZWQgbG9uZyBrdmEsIG9mZnNldDsNCj4gPiArDQo+
ID4gKwkvKiBNYXAgbmV3IFRDRSAqLw0KPiA+ICsJb2Zmc2V0ID0gKHRjZSAmIElPTU1VX1BBR0Vf
TUFTSykgLSAodGNlICYgUEFHRV9NQVNLKTsNCj4gPiArCXJldCA9IGdldF91c2VyX3BhZ2VzX2Zh
c3QodGNlICYgUEFHRV9NQVNLLCAxLA0KPiA+ICsJCQlkaXJlY3Rpb24gIT0gRE1BX1RPX0RFVklD
RSwgJnBhZ2UpOw0KPiA+ICsJaWYgKHJldCA8IDEpIHsNCj4gPiArCQlwcmludGsoS0VSTl9FUlIg
InRjZV92ZmlvOiBnZXRfdXNlcl9wYWdlc19mYXN0IGZhaWxlZA0KPiB0Y2U9JWxseCBpb2JhPSVs
eCByZXQ9JWRcbiIsDQo+ID4gKwkJCQl0Y2UsIGVudHJ5IDw8IElPTU1VX1BBR0VfU0hJRlQsIHJl
dCk7DQo+ID4gKwkJaWYgKCFyZXQpDQo+ID4gKwkJCXJldCA9IC1FRkFVTFQ7DQo+IA0KPiBNaXNz
aW5nIHJldHVybiByZXQ/ICBPdGhlcndpc2Ugd2UndmUgZ290IHNvbWUgYm9ndXMgdXNlcyBvZiBw
YWdlIGJlbG93DQo+IGFuZCB3ZSdyZSBzZXR0aW5nIHJldCBmb3Igbm8gcmVhc29uIGhlcmUuDQo+
IA0KPiA+ICsJfQ0KPiA+ICsNCj4gPiArCWt2YSA9ICh1bnNpZ25lZCBsb25nKSBwYWdlX2FkZHJl
c3MocGFnZSk7DQo+ID4gKwlrdmEgKz0gb2Zmc2V0Ow0KPiA+ICsNCj4gPiArCS8qIHRjZV9idWls
ZCByZWNlaXZlcyBhIHZpcnR1YWwgYWRkcmVzcyAqLw0KPiA+ICsJZW50cnkgKz0gdGJsLT5pdF9v
ZmZzZXQ7IC8qIE9mZnNldCBpbnRvIHJlYWwgVENFIHRhYmxlICovDQo+ID4gKwlyZXQgPSBwcGNf
bWQudGNlX2J1aWxkKHRibCwgZW50cnksIDEsIGt2YSwgZGlyZWN0aW9uLCBOVUxMKTsNCj4gPiAr
DQo+ID4gKwkvKiB0Y2VfYnVpbGQoKSBvbmx5IHJldHVybnMgbm9uLXplcm8gZm9yIHRyYW5zaWVu
dCBlcnJvcnMgKi8NCj4gPiArCWlmICh1bmxpa2VseShyZXQpKSB7DQo+ID4gKwkJcHJpbnRrKEtF
Uk5fRVJSICJ0Y2VfdmZpbzogdGNlX3B1dCBmYWlsZWQgb24gdGNlPSVsbHgNCj4gaW9iYT0lbHgg
a3ZhPSVseCByZXQ9JWRcbiIsDQo+ID4gKwkJCQl0Y2UsIGVudHJ5IDw8IElPTU1VX1BBR0VfU0hJ
RlQsIGt2YSwgcmV0KTsNCj4gPiArCQlwdXRfcGFnZShwYWdlKTsNCj4gPiArCQlyZXR1cm4gLUVJ
TzsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwlyZXR1cm4gMDsNCj4gPiArfQ0KPiA+ICsNCj4gPiAr
c3RhdGljIHZvaWQgdGNlX2ZsdXNoKHN0cnVjdCBpb21tdV90YWJsZSAqdGJsKSB7DQo+ID4gKwkv
KiBGbHVzaC9pbnZhbGlkYXRlIFRMQiBjYWNoZXMgaWYgbmVjZXNzYXJ5ICovDQo+ID4gKwlpZiAo
cHBjX21kLnRjZV9mbHVzaCkNCj4gPiArCQlwcGNfbWQudGNlX2ZsdXNoKHRibCk7DQo+ID4gKw0K
PiA+ICsJLyogTWFrZSBzdXJlIHVwZGF0ZXMgYXJlIHNlZW4gYnkgaGFyZHdhcmUgKi8NCj4gPiAr
CW1iKCk7DQo+ID4gK30NCj4gPiArDQo+ID4gK2xvbmcgaW9tbXVfcHV0X3RjZXMoc3RydWN0IGlv
bW11X3RhYmxlICp0YmwsIHVuc2lnbmVkIGxvbmcgZW50cnksDQo+IHVpbnQ2NF90IHRjZSwNCj4g
PiArCQllbnVtIGRtYV9kYXRhX2RpcmVjdGlvbiBkaXJlY3Rpb24sIHVuc2lnbmVkIGxvbmcgcGFn
ZXMpIHsNCj4gPiArCWludCBpLCByZXQgPSAwLCBwYWdlc190b19wdXQgPSAwOw0KPiA+ICsJc3Ry
dWN0IHBhZ2UgKnBhZ2U7DQo+ID4gKwlzdHJ1Y3QgaW9tbXVfcG9vbCAqcG9vbCA9IGdldF9wb29s
KHRibCwgZW50cnkpOw0KPiA+ICsJc3RydWN0IHBhZ2UgKipvbGRwYWdlczsNCj4gPiArCWNvbnN0
IGludCBvbGRwYWdlc251bSA9IFBBR0VfU0laRS9zaXplb2YoKm9sZHBhZ2VzKTsNCj4gPiArDQo+
ID4gKwlCVUlMRF9CVUdfT04oUEFHRV9TSVpFIDwgSU9NTVVfUEFHRV9TSVpFKTsNCj4gPiArDQo+
ID4gKwkvKiBIYW5kbGUgYSBzaW5nbGUgcGFnZSByZXF1ZXN0IHdpdGhvdXQgYWxsb2NhdGlvbg0K
PiA+ICsJICAgb2YgcGFnZXMtdG8tcmVsZWFzZSBhcnJheSAqLw0KPiA+ICsJaWYgKHBhZ2VzID09
IDEpIHsNCj4gPiArCQlzcGluX2xvY2soJihwb29sLT5sb2NrKSk7DQo+ID4gKwkJcGFnZSA9IGZy
ZWVfdGNlKHRibCwgZW50cnkpOw0KPiA+ICsNCj4gPiArCQlpZiAoZGlyZWN0aW9uICE9IERNQV9O
T05FKQ0KPiA+ICsJCQlyZXQgPSBwdXRfdGNlKHRibCwgZW50cnksIHRjZSwgZGlyZWN0aW9uKTsN
Cj4gPiArDQo+ID4gKwkJdGNlX2ZsdXNoKHRibCk7DQo+ID4gKw0KPiA+ICsJCWlmIChwYWdlKQ0K
PiA+ICsJCQlwdXRfcGFnZShwYWdlKTsNCj4gPiArDQo+ID4gKwkJc3Bpbl91bmxvY2soJihwb29s
LT5sb2NrKSk7DQo+ID4gKwkJcmV0dXJuIHJldDsNCj4gPiArCX0NCj4gPiArDQo+ID4gKwkvKiBS
ZWxlYXNpbmcgbXVsdGlwbGUgcGFnZXMgKi8NCj4gPiArCS8qIEFsbG9jYXRlIGFuIGFycmF5IGZv
ciBwYWdlcyB0byBiZSByZWxlYXNlZCBhZnRlciBUQ0UgdGFibGUNCj4gPiArCSAgIGlzIHVwZGF0
ZWQgKi8NCj4gPiArCW9sZHBhZ2VzID0ga21hbGxvYyhQQUdFX1NJWkUsIEdGUF9LRVJORUwpOw0K
PiA+ICsJaWYgKCFvbGRwYWdlcykNCj4gPiArCQlyZXR1cm4gLUVOT01FTTsNCj4gPiArDQo+ID4g
KwlzcGluX2xvY2soJihwb29sLT5sb2NrKSk7DQo+ID4gKw0KPiA+ICsJZm9yIChpID0gMDsgKGkg
PCBwYWdlcykgJiYgIXJldDsgKytpLCArK2VudHJ5LCB0Y2UgKz0NCj4gSU9NTVVfUEFHRV9TSVpF
KSB7DQo+ID4gKwkJcGFnZSA9IGZyZWVfdGNlKHRibCwgZW50cnkpOw0KPiA+ICsJCWlmIChwYWdl
KSB7DQo+ID4gKwkJCW9sZHBhZ2VzW3BhZ2VzX3RvX3B1dF0gPSBwYWdlOw0KPiA+ICsJCQkrK3Bh
Z2VzX3RvX3B1dDsNCj4gPiArCQl9DQo+ID4gKw0KPiA+ICsJCWlmIChkaXJlY3Rpb24gIT0gRE1B
X05PTkUpDQo+ID4gKwkJCXJldCA9IHB1dF90Y2UodGJsLCBlbnRyeSwgdGNlLCBkaXJlY3Rpb24p
Ow0KPiA+ICsNCj4gPiArCQkvKiBSZWxlYXNlIG9sZCBwYWdlcyBpZiB3ZSByZWFjaGVkIHRoZSBl
bmQgb2Ygb2xkcGFnZXNbXSBvcg0KPiA+ICsJCSAgIGl0IGlzIHRoZSBsYXN0IHBhZ2Ugb3Igd2Ug
YXJlIGFib3V0IHRvIGV4aXQgdGhlIGxvb3AgKi8NCj4gPiArCQlpZiAoKHBhZ2VzX3RvX3B1dCA9
PSBvbGRwYWdlc251bSkgfHwgKGkgPT0gcGFnZXMgLSAxKSB8fCByZXQpDQo+IHsNCj4gPiArCQkJ
dGNlX2ZsdXNoKHRibCk7DQo+IA0KPiBBdm9pZGluZyB0Y2VfZmx1c2goKSBpcyB0aGUgcmVhc29u
IGZvciBhbGwgdGhpcyBleHRyYSBvdmVyaGVhZCwgcmlnaHQ/DQo+IEkgd29uZGVyIGlmIGl0J2Qg
YmUgY2xlYW5lciBzZXBhcmF0aW5nIG1hcCB2cyB1bm1hcCwgd2hlcmUgdGhlIG1hcCBjYXNlDQo+
IGNhbiBhdm9pZCB0aGUgb2xkcGFnZXMgYXJyYXkuLi4gYnV0IHRoYXQgbWVhbnMgaW5zZXJ0aW5n
IG5ldyBtYXBwaW5ncyBvbg0KPiB0b3Agb2Ygb2xkIG9uZXMgd291bGRuJ3QgcHV0IHRoZSBwYWdl
cy4NCj4gDQo+ID4gKw0KPiA+ICsJCQkvKiBSZWxlYXNlIHBhZ2VzIGFmdGVyIHJlbW92aW5nIHRo
ZW0gZnJvbSBUQ0UgdGFibGUgKi8NCj4gPiArCQkJd2hpbGUgKHBhZ2VzX3RvX3B1dCkgew0KPiA+
ICsJCQkJLS1wYWdlc190b19wdXQ7DQo+ID4gKwkJCQlwdXRfcGFnZShvbGRwYWdlc1twYWdlc190
b19wdXRdKTsNCj4gPiArCQkJfQ0KPiA+ICsJCX0NCj4gPiArCX0NCj4gPiArDQo+ID4gKwlzcGlu
X3VubG9jaygmKHBvb2wtPmxvY2spKTsNCj4gPiArCWtmcmVlKG9sZHBhZ2VzKTsNCj4gPiArDQo+
ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gK0VYUE9SVF9TWU1CT0xfR1BMKGlvbW11X3B1
dF90Y2VzKTsNCj4gPiArI2VuZGlmIC8qIENPTkZJR19JT01NVV9BUEkgKi8NCj4gPiBkaWZmIC0t
Z2l0IGEvYXJjaC9wb3dlcnBjL3BsYXRmb3Jtcy9wb3dlcm52L3BjaS5jDQo+ID4gYi9hcmNoL3Bv
d2VycGMvcGxhdGZvcm1zL3Bvd2VybnYvcGNpLmMNCj4gPiBpbmRleCAwNTIwNWNmLi42NzZmNGQ5
IDEwMDY0NA0KPiA+IC0tLSBhL2FyY2gvcG93ZXJwYy9wbGF0Zm9ybXMvcG93ZXJudi9wY2kuYw0K
PiA+ICsrKyBiL2FyY2gvcG93ZXJwYy9wbGF0Zm9ybXMvcG93ZXJudi9wY2kuYw0KPiA+IEBAIC04
LDMwICs4LDMxIEBADQo+ID4gICAqIFRoaXMgcHJvZ3JhbSBpcyBmcmVlIHNvZnR3YXJlOyB5b3Ug
Y2FuIHJlZGlzdHJpYnV0ZSBpdCBhbmQvb3INCj4gPiAgICogbW9kaWZ5IGl0IHVuZGVyIHRoZSB0
ZXJtcyBvZiB0aGUgR05VIEdlbmVyYWwgUHVibGljIExpY2Vuc2UNCj4gPiAgICogYXMgcHVibGlz
aGVkIGJ5IHRoZSBGcmVlIFNvZnR3YXJlIEZvdW5kYXRpb247IGVpdGhlciB2ZXJzaW9uDQo+ID4g
ICAqIDIgb2YgdGhlIExpY2Vuc2UsIG9yIChhdCB5b3VyIG9wdGlvbikgYW55IGxhdGVyIHZlcnNp
b24uDQo+ID4gICAqLw0KPiA+DQo+ID4gICNpbmNsdWRlIDxsaW51eC9rZXJuZWwuaD4NCj4gPiAg
I2luY2x1ZGUgPGxpbnV4L3BjaS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvZGVsYXkuaD4NCj4g
PiAgI2luY2x1ZGUgPGxpbnV4L3N0cmluZy5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgvaW5pdC5o
Pg0KPiA+ICAjaW5jbHVkZSA8bGludXgvYm9vdG1lbS5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgv
aXJxLmg+DQo+ID4gICNpbmNsdWRlIDxsaW51eC9pby5oPg0KPiA+ICAjaW5jbHVkZSA8bGludXgv
bXNpLmg+DQo+ID4gKyNpbmNsdWRlIDxsaW51eC9pb21tdS5oPg0KPiA+DQo+ID4gICNpbmNsdWRl
IDxhc20vc2VjdGlvbnMuaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9pby5oPg0KPiA+ICAjaW5jbHVk
ZSA8YXNtL3Byb20uaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9wY2ktYnJpZGdlLmg+DQo+ID4gICNp
bmNsdWRlIDxhc20vbWFjaGRlcC5oPg0KPiA+ICAjaW5jbHVkZSA8YXNtL3BwYy1wY2kuaD4NCj4g
PiAgI2luY2x1ZGUgPGFzbS9vcGFsLmg+DQo+ID4gICNpbmNsdWRlIDxhc20vaW9tbXUuaD4NCj4g
PiAgI2luY2x1ZGUgPGFzbS90Y2UuaD4NCj4gPiAgI2luY2x1ZGUgPGFzbS9hYnNfYWRkci5oPg0K
PiA+ICAjaW5jbHVkZSA8YXNtL2Zpcm13YXJlLmg+DQo+ID4NCj4gPiAgI2luY2x1ZGUgInBvd2Vy
bnYuaCINCj4gPiAgI2luY2x1ZGUgInBjaS5oIg0KPiA+IEBAIC02MDEsMTUgKzYwMiwxNDkgQEAg
dm9pZCBfX2luaXQgcG52X3BjaV9pbml0KHZvaWQpDQo+ID4gIAkvKiBDb25maWd1cmUgSU9NTVUg
RE1BIGhvb2tzICovDQo+ID4gIAlwcGNfbWQucGNpX2RtYV9kZXZfc2V0dXAgPSBwbnZfcGNpX2Rt
YV9kZXZfc2V0dXA7DQo+ID4gIAlwcGNfbWQudGNlX2J1aWxkID0gcG52X3RjZV9idWlsZDsNCj4g
PiAgCXBwY19tZC50Y2VfZnJlZSA9IHBudl90Y2VfZnJlZTsNCj4gPiAgCXBwY19tZC50Y2VfZ2V0
ID0gcG52X3RjZV9nZXQ7DQo+ID4gIAlwcGNfbWQucGNpX3Byb2JlX21vZGUgPSBwbnZfcGNpX3By
b2JlX21vZGU7DQo+ID4gIAlzZXRfcGNpX2RtYV9vcHMoJmRtYV9pb21tdV9vcHMpOw0KPiA+DQo+
ID4gIAkvKiBDb25maWd1cmUgTVNJcyAqLw0KPiA+ICAjaWZkZWYgQ09ORklHX1BDSV9NU0kNCj4g
PiAgCXBwY19tZC5tc2lfY2hlY2tfZGV2aWNlID0gcG52X21zaV9jaGVja19kZXZpY2U7DQo+ID4g
IAlwcGNfbWQuc2V0dXBfbXNpX2lycXMgPSBwbnZfc2V0dXBfbXNpX2lycXM7DQo+ID4gIAlwcGNf
bWQudGVhcmRvd25fbXNpX2lycXMgPSBwbnZfdGVhcmRvd25fbXNpX2lycXM7ICAjZW5kaWYgIH0N
Cj4gPiArDQo+ID4gKyNpZmRlZiBDT05GSUdfSU9NTVVfQVBJDQo+ID4gKy8qDQo+ID4gKyAqIElP
TU1VIGdyb3VwcyBzdXBwb3J0IHJlcXVpcmVkIGJ5IFZGSU8gICovIHN0YXRpYyBpbnQNCj4gPiAr
YWRkX2RldmljZShzdHJ1Y3QgZGV2aWNlICpkZXYpIHsNCj4gPiArCXN0cnVjdCBpb21tdV90YWJs
ZSAqdGJsOw0KPiA+ICsJaW50IHJldCA9IDA7DQo+ID4gKw0KPiA+ICsJaWYgKFdBUk5fT04oZGV2
LT5pb21tdV9ncm91cCkpIHsNCj4gPiArCQlwcmludGsoS0VSTl9XQVJOSU5HICJ0Y2VfdmZpbzog
ZGV2aWNlICVzIGlzIGFscmVhZHkgaW4gaW9tbXUNCj4gZ3JvdXAgJWQsIHNraXBwaW5nXG4iLA0K
PiA+ICsJCQkJZGV2LT5rb2JqLm5hbWUsDQo+IA0KPiBkZXZfbmFtZShkZXYpDQo+IA0KPiA+ICsJ
CQkJaW9tbXVfZ3JvdXBfaWQoZGV2LT5pb21tdV9ncm91cCkpOw0KPiA+ICsJCXJldHVybiAtRUJV
U1k7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJdGJsID0gZ2V0X2lvbW11X3RhYmxlX2Jhc2UoZGV2
KTsNCj4gPiArCWlmICghdGJsKSB7DQo+ID4gKwkJcHJfZGVidWcoInRjZV92ZmlvOiBza2lwcGlu
ZyBkZXZpY2UgJXMgd2l0aCBubyB0YmxcbiIsDQo+ID4gKwkJCQlkZXYtPmtvYmoubmFtZSk7DQo+
ID4gKwkJcmV0dXJuIDA7DQo+ID4gKwl9DQo+ID4gKw0KPiA+ICsJcHJfZGVidWcoInRjZV92Zmlv
OiBhZGRpbmcgJXMgdG8gaW9tbXUgZ3JvdXAgJWRcbiIsDQo+ID4gKwkJCWRldi0+a29iai5uYW1l
LCBpb21tdV9ncm91cF9pZCh0YmwtPml0X2dyb3VwKSk7DQo+ID4gKw0KPiA+ICsJcmV0ID0gaW9t
bXVfZ3JvdXBfYWRkX2RldmljZSh0YmwtPml0X2dyb3VwLCBkZXYpOw0KPiA+ICsJaWYgKHJldCA8
IDApDQo+ID4gKwkJcHJpbnRrKEtFUk5fRVJSICJ0Y2VfdmZpbzogJXMgaGFzIG5vdCBiZWVuIGFk
ZGVkLCByZXQ9JWRcbiIsDQo+ID4gKwkJCQlkZXYtPmtvYmoubmFtZSwgcmV0KTsNCj4gPiArDQo+
ID4gKwlyZXR1cm4gcmV0Ow0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgdm9pZCBkZWxfZGV2
aWNlKHN0cnVjdCBkZXZpY2UgKmRldikgew0KPiA+ICsJaW9tbXVfZ3JvdXBfcmVtb3ZlX2Rldmlj
ZShkZXYpOw0KPiA+ICt9DQo+ID4gKw0KPiA+ICtzdGF0aWMgaW50IGlvbW11X2J1c19ub3RpZmll
cihzdHJ1Y3Qgbm90aWZpZXJfYmxvY2sgKm5iLA0KPiA+ICsJCQkgICAgICB1bnNpZ25lZCBsb25n
IGFjdGlvbiwgdm9pZCAqZGF0YSkgew0KPiA+ICsJc3RydWN0IGRldmljZSAqZGV2ID0gZGF0YTsN
Cj4gPiArDQo+ID4gKwlzd2l0Y2ggKGFjdGlvbikgew0KPiA+ICsJY2FzZSBCVVNfTk9USUZZX0FE
RF9ERVZJQ0U6DQo+ID4gKwkJcmV0dXJuIGFkZF9kZXZpY2UoZGV2KTsNCj4gPiArCWNhc2UgQlVT
X05PVElGWV9ERUxfREVWSUNFOg0KPiA+ICsJCWRlbF9kZXZpY2UoZGV2KTsNCj4gPiArCQlyZXR1
cm4gMDsNCj4gPiArCWRlZmF1bHQ6DQo+ID4gKwkJcmV0dXJuIDA7DQo+ID4gKwl9DQo+ID4gK30N
Cj4gPiArDQo+ID4gK3N0YXRpYyBzdHJ1Y3Qgbm90aWZpZXJfYmxvY2sgdGNlX2lvbW11X2J1c19u
YiA9IHsNCj4gPiArCS5ub3RpZmllcl9jYWxsID0gaW9tbXVfYnVzX25vdGlmaWVyLCB9Ow0KPiA+
ICsNCj4gPiArc3RhdGljIHZvaWQgZ3JvdXBfcmVsZWFzZSh2b2lkICppb21tdV9kYXRhKSB7DQo+
ID4gKwlzdHJ1Y3QgaW9tbXVfdGFibGUgKnRibCA9IGlvbW11X2RhdGE7DQo+ID4gKwl0YmwtPml0
X2dyb3VwID0gTlVMTDsNCj4gPiArfQ0KPiA+ICsNCj4gPiArc3RhdGljIGludCBfX2luaXQgdGNl
X2lvbW11X2luaXQodm9pZCkgew0KPiA+ICsJc3RydWN0IHBjaV9kZXYgKnBkZXYgPSBOVUxMOw0K
PiA+ICsJc3RydWN0IGlvbW11X3RhYmxlICp0Ymw7DQo+ID4gKwlzdHJ1Y3QgaW9tbXVfZ3JvdXAg
KmdycDsNCj4gPiArDQo+ID4gKwlidXNfcmVnaXN0ZXJfbm90aWZpZXIoJnBjaV9idXNfdHlwZSwg
JnRjZV9pb21tdV9idXNfbmIpOw0KPiANCj4gVGhlcmUncyBhbHJlYWR5IGEgbm90aWZpZXIgaW4g
dGhlIGlvbW11IGNvZGUgaWYgeW91IHdlcmUgdG8gcmVnaXN0ZXIgYW4NCj4gaW9tbXVfb3BzIHdp
dGggdGhlIGFkZC9yZW1vdmVfZGV2aWNlIGVudHJpZXMuICBUaGF0IHdvdWxkIGFsbG93IHlvdSB0
bw0KPiByZW1vdmUgdGhlIG5vdGlmaWVyIGJsb2NrIGFuZCBub3RpZmllciBmdW5jdGlvbiBiZWxv
dyBhbmQgdGhlIHNlY29uZCBsb29wDQo+IGJlbG93LiAgQXJlIHlvdSBhdm9pZGluZyB0aGF0IHRv
IGF2b2lkIHRoZSByZXN0IG9mIGlvbW11X29wcz8NCj4gDQpbU2V0aGkgVmFydW4tQjE2Mzk1XSBD
b3VsZCBiZSBvbmUgcmVhc29uLCBhbHNvIHRoZXkgYXJlIGFzc29jaWF0aW5nIHRoZSBpb21tdSBn
cm91cCB3aXRoIHRoZSB0Y2UgdGFibGUgZW50cnkgYW5kIG5vdCB0aGUgZGV2aWNlLg0KDQo+IEFs
c28sIHNob3VsZG4ndCB0aGlzIG5vdGlmaWVyIG9ubHkgYmUgcmVnaXN0ZXJlZCBhZnRlciB0aGUg
Zmlyc3QgbG9vcA0KPiBiZWxvdz8gIE90aGVyd2lzZSBBRERfREVWSUNFIGNvdWxkIHJhY2Ugd2l0
aCBzZXR0aW5nIHVwIGdyb3Vwcywgd2hpY2ggd2UNCj4gYXNzdW1lIGFyZSBwcmVzZW50IGluIHRo
ZSBhZGRfZGV2aWNlKCkgYWJvdmUuDQpbU2V0aGkgVmFydW4tQjE2Mzk1XSBJc24ndCB0aGlzIHNp
bWlsYXIgdG8gaG93IGhvdyB0aGUgbm90aWZpZXIgaXMgcmVnaXN0ZXJlZCBpbiBpb21tdV9idXNf
aW5pdD8gRmlyc3QgYSBub3RpZmllciBpcyByZWdpc3RlcmVkIGFuZCB0aGVuIHdlIGNoZWNrIGZv
ciBkZXZpY2VzIHRoYXQgaGF2ZSBhbHJlYWR5IGJlZW4gcHJvYmVkLg0KDQotVmFydW4NCg==

^ permalink raw reply

* [PATCH] mmc: esdhi: Add SDHCI_QUIRK_QORIQ_CIRCUIT_SUPPORT_VS33 quirk support
From: Chunhe Lan @ 2012-11-22  8:14 UTC (permalink / raw)
  To: linux-mmc; +Cc: kumar.gala, cjb, linuxppc-dev, Chunhe Lan

On the some platforms of Freescale, sdhci controller can only
support 1.8V voltage, but the peripheral hardware circuit has
capability to support 3.3V voltage.

Signed-off-by: Chunhe Lan <Chunhe.Lan@freescale.com>
---
 drivers/mmc/host/sdhci.c  |    3 +++
 include/linux/mmc/sdhci.h |    4 ++++
 2 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index 4fe2de8..e4a537d 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -2682,6 +2682,9 @@ int sdhci_add_host(struct sdhci_host *host)
 			host->caps1 :
 			sdhci_readl(host, SDHCI_CAPABILITIES_1);
 
+	if (host->quirks & SDHCI_QUIRK_QORIQ_CIRCUIT_SUPPORT_VS33)
+		caps[0] = caps[0] | SDHCI_CAN_VDD_330;
+
 	if (host->quirks & SDHCI_QUIRK_FORCE_DMA)
 		host->flags |= SDHCI_USE_SDMA;
 	else if (!(caps[0] & SDHCI_CAN_DO_SDMA))
diff --git a/include/linux/mmc/sdhci.h b/include/linux/mmc/sdhci.h
index 1edcb4d..78eced5 100644
--- a/include/linux/mmc/sdhci.h
+++ b/include/linux/mmc/sdhci.h
@@ -87,6 +87,10 @@ struct sdhci_host {
 #define SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC		(1<<30)
 /* The read-only detection via SDHCI_PRESENT_STATE register is unstable */
 #define SDHCI_QUIRK_UNSTABLE_RO_DETECT			(1<<31)
+/* Controller can only supports 1.8V, but the peripheral hardware
+ * circuit has capability to support 3.3V
+ */
+#define SDHCI_QUIRK_QORIQ_CIRCUIT_SUPPORT_VS33		(1U<<32)
 
 	unsigned int quirks2;	/* More deviations from spec. */
 
-- 
1.7.6.5

^ permalink raw reply related

* Re: [PATCH v3 00/12] memory-hotplug: hot-remove physical memory
From: Yasuaki Ishimatsu @ 2012-11-22  1:33 UTC (permalink / raw)
  To: Andrew Morton
  Cc: linux-s390, linux-ia64, Wen Congyang, linux-acpi, linux-sh,
	Len Brown, x86, linux-kernel, cmetcalf, Jianguo Wu, linux-mm,
	paulus, Minchan Kim, KOSAKI Motohiro, David Rientjes, sparclinux,
	Christoph Lameter, linuxppc-dev, Jiang Liu
In-Reply-To: <1351763083-7905-1-git-send-email-wency@cn.fujitsu.com>

Hi Andrew,

The patch-set aims to linux-3.8. So we would like you to merge
the patch-set into your tree.

The patch-set applied many comments. Currently there is no
comment to the patch-set.

Additionally, we have spent a lot of time on the verification
of the patch-set. And we found many bugs, and fixed them.

So we believe that Linux on x86_64 can support memory hot remove
by the patch-set. 

Thanks,
Yasuaki Ishimatsu

2012/11/01 18:44, Wen Congyang wrote:
> The patch-set was divided from following thread's patch-set.
>      https://lkml.org/lkml/2012/9/5/201
> 
> The last version of this patchset:
>      https://lkml.org/lkml/2012/10/23/213
> 
> If you want to know the reason, please read following thread.
> 
> https://lkml.org/lkml/2012/10/2/83
> 
> The patch-set has only the function of kernel core side for physical
> memory hot remove. So if you use the patch, please apply following
> patches.
> 
> - bug fix for memory hot remove
>    https://lkml.org/lkml/2012/10/31/269
>    
> - acpi framework
>    https://lkml.org/lkml/2012/10/26/175
> 
> The patches can free/remove the following things:
> 
>    - /sys/firmware/memmap/X/{end, start, type} : [PATCH 2/10]
>    - mem_section and related sysfs files       : [PATCH 3-4/10]
>    - memmap of sparse-vmemmap                  : [PATCH 5-7/10]
>    - page table of removed memory              : [RFC PATCH 8/10]
>    - node and related sysfs files              : [RFC PATCH 9-10/10]
> 
> * [PATCH 2/10] checks whether the memory can be removed or not.
> 
> If you find lack of function for physical memory hot-remove, please let me
> know.
> 
> How to test this patchset?
> 1. apply this patchset and build the kernel. MEMORY_HOTPLUG, MEMORY_HOTREMOVE,
>     ACPI_HOTPLUG_MEMORY must be selected.
> 2. load the module acpi_memhotplug
> 3. hotplug the memory device(it depends on your hardware)
>     You will see the memory device under the directory /sys/bus/acpi/devices/.
>     Its name is PNP0C80:XX.
> 4. online/offline pages provided by this memory device
>     You can write online/offline to /sys/devices/system/memory/memoryX/state to
>     online/offline pages provided by this memory device
> 5. hotremove the memory device
>     You can hotremove the memory device by the hardware, or writing 1 to
>     /sys/bus/acpi/devices/PNP0C80:XX/eject.
> 
> Note: if the memory provided by the memory device is used by the kernel, it
> can't be offlined. It is not a bug.
> 
> Known problems:
> 1. hotremoving memory device may cause kernel panicked
>     This bug will be fixed by Liu Jiang's patch:
>     https://lkml.org/lkml/2012/7/3/1
> 
> 
> Changelogs from v2 to v3:
>   Patch9: call sync_global_pgds() if pgd is changed
>   Patch10: fix a problem int the patch
> 
> Changelogs from v1 to v2:
>   Patch1: new patch, offline memory twice. 1st iterate: offline every non primary
>           memory block. 2nd iterate: offline primary (i.e. first added) memory
>           block.
> 
>   Patch3: new patch, no logical change, just remove reduntant codes.
> 
>   Patch9: merge the patch from wujianguo into this patch. flush tlb on all cpu
>           after the pagetable is changed.
> 
>   Patch12: new patch, free node_data when a node is offlined
> 
> Wen Congyang (6):
>    memory-hotplug: try to offline the memory twice to avoid dependence
>    memory-hotplug: remove redundant codes
>    memory-hotplug: introduce new function arch_remove_memory() for
>      removing page table depends on architecture
>    memory-hotplug: remove page table of x86_64 architecture
>    memory-hotplug: remove sysfs file of node
>    memory-hotplug: free node_data when a node is offlined
> 
> Yasuaki Ishimatsu (6):
>    memory-hotplug: check whether all memory blocks are offlined or not
>      when removing memory
>    memory-hotplug: remove /sys/firmware/memmap/X sysfs
>    memory-hotplug: unregister memory section on SPARSEMEM_VMEMMAP
>    memory-hotplug: implement register_page_bootmem_info_section of
>      sparse-vmemmap
>    memory-hotplug: remove memmap of sparse-vmemmap
>    memory-hotplug: memory_hotplug: clear zone when removing the memory
> 
>   arch/ia64/mm/discontig.c             |  14 ++
>   arch/ia64/mm/init.c                  |  18 ++
>   arch/powerpc/mm/init_64.c            |  14 ++
>   arch/powerpc/mm/mem.c                |  12 +
>   arch/s390/mm/init.c                  |  12 +
>   arch/s390/mm/vmem.c                  |  14 ++
>   arch/sh/mm/init.c                    |  17 ++
>   arch/sparc/mm/init_64.c              |  14 ++
>   arch/tile/mm/init.c                  |   8 +
>   arch/x86/include/asm/pgtable_types.h |   1 +
>   arch/x86/mm/init_32.c                |  12 +
>   arch/x86/mm/init_64.c                | 417 +++++++++++++++++++++++++++++++++++
>   arch/x86/mm/pageattr.c               |  47 ++--
>   drivers/acpi/acpi_memhotplug.c       |   8 +-
>   drivers/base/memory.c                |   6 +
>   drivers/firmware/memmap.c            |  98 +++++++-
>   include/linux/firmware-map.h         |   6 +
>   include/linux/memory_hotplug.h       |  15 +-
>   include/linux/mm.h                   |   5 +-
>   mm/memory_hotplug.c                  | 409 ++++++++++++++++++++++++++++++++--
>   mm/sparse.c                          |   5 +-
>   21 files changed, 1095 insertions(+), 57 deletions(-)
> 

^ permalink raw reply

* [PATCH 3/9] powerpc/PCI: Remove CONFIG_HOTPLUG ifdefs
From: Bill Pemberton @ 2012-11-21 20:34 UTC (permalink / raw)
  To: gregkh
  Cc: linux-pci, devicetree-discuss, Rob Herring, Paul Mackerras,
	Bjorn Helgaas, linuxppc-dev
In-Reply-To: <1353530100-728-1-git-send-email-wfp5p@virginia.edu>

Remove conditional code based on CONFIG_HOTPLUG being false.  It's
always on now in preparation of it going away as an option.

Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: Rob Herring <rob.herring@calxeda.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: devicetree-discuss@lists.ozlabs.org
---
 arch/powerpc/kernel/pci-common.c | 4 ----
 arch/powerpc/kernel/pci_64.c     | 4 ----
 2 files changed, 8 deletions(-)

diff --git a/arch/powerpc/kernel/pci-common.c b/arch/powerpc/kernel/pci-common.c
index 7f94f76..abc0d08 100644
--- a/arch/powerpc/kernel/pci-common.c
+++ b/arch/powerpc/kernel/pci-common.c
@@ -1428,8 +1428,6 @@ void __init pcibios_resource_survey(void)
 		ppc_md.pcibios_fixup();
 }
 
-#ifdef CONFIG_HOTPLUG
-
 /* This is used by the PCI hotplug driver to allocate resource
  * of newly plugged busses. We can try to consolidate with the
  * rest of the code later, for now, keep it as-is as our main
@@ -1488,8 +1486,6 @@ void pcibios_finish_adding_to_bus(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_finish_adding_to_bus);
 
-#endif /* CONFIG_HOTPLUG */
-
 int pcibios_enable_device(struct pci_dev *dev, int mask)
 {
 	if (ppc_md.pcibios_enable_device_hook)
diff --git a/arch/powerpc/kernel/pci_64.c b/arch/powerpc/kernel/pci_64.c
index 4ff190f..2cbe676 100644
--- a/arch/powerpc/kernel/pci_64.c
+++ b/arch/powerpc/kernel/pci_64.c
@@ -74,8 +74,6 @@ static int __init pcibios_init(void)
 
 subsys_initcall(pcibios_init);
 
-#ifdef CONFIG_HOTPLUG
-
 int pcibios_unmap_io_space(struct pci_bus *bus)
 {
 	struct pci_controller *hose;
@@ -124,8 +122,6 @@ int pcibios_unmap_io_space(struct pci_bus *bus)
 }
 EXPORT_SYMBOL_GPL(pcibios_unmap_io_space);
 
-#endif /* CONFIG_HOTPLUG */
-
 static int __devinit pcibios_map_phb_io_space(struct pci_controller *hose)
 {
 	struct vm_struct *area;
-- 
1.8.0

^ permalink raw reply related

* Re: [PATCH 192/493] scsi: remove use of __devinit
From: Guennadi Liakhovetski @ 2012-11-21 12:13 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: Oliver Neukum, VMware PV-Drivers, Kurt Garloff, Kai Mäkisara,
	GOTO Masanori, Russell King, linux-scsi, Jamie Lenehan,
	osst-users, Michael Reed, cbe-oss-dev, iss_storagedev,
	Matthew Wilcox, Ali Akcaagac, dc395x, linux-arm-kernel,
	Neela Syam Kolli, Geoff Levand, gregkh, Arvind Kumar,
	James E.J. Bottomley, Willem Riede, YOKOTA Hiroshi, linuxppc-dev
In-Reply-To: <1353349642-3677-192-git-send-email-wfp5p@virginia.edu>

On Mon, 19 Nov 2012, Bill Pemberton wrote:

>  drivers/scsi/tmscsim.c                    | 16 +++---

Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>

Thanks
Guennadi
---
Guennadi Liakhovetski, Ph.D.
Freelance Open-Source Software Developer
http://www.open-technology.de/

^ permalink raw reply

* Re: [PATCH 298/493] video: remove use of __devinitdata
From: Russell King - ARM Linux @ 2012-11-21 12:00 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: cbe-oss-dev, linux-fbdev, Maik Broemme, Antonino Daplas,
	Florian Tobias Schandinat, Geoff Levand, gregkh,
	Thomas Winischhofer, linux-geode, Kristoffer Ericson,
	Ferenc Bakonyi, Michal Januszewski, Peter Jones, Paul Mackerras,
	linux-nvidia, linuxppc-dev, linux-arm-kernel, Jaya Kumar
In-Reply-To: <1353349642-3677-298-git-send-email-wfp5p@virginia.edu>

On Mon, Nov 19, 2012 at 01:24:07PM -0500, Bill Pemberton wrote:
>  drivers/video/acornfb.c                |  8 +++---
>  drivers/video/cyber2000fb.c            |  2 +-
>  drivers/video/sa1100fb.c               |  2 +-

For these three,

Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>

^ permalink raw reply

* Re: [PATCH 198/493] ethernet: remove use of __devinit
From: Russell King - ARM Linux @ 2012-11-21 11:55 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: linux-mips, Chris Snook, Samuel Chessman, David Dillow,
	Jaroslav Kysela, Daniele Venzano, Stephen Hemminger, John Linn,
	e1000-devel, Guo-Fu Tseng, linux-acenic, cbe-oss-dev,
	Francois Romieu, Steve Glendinning, Jes Sorensen, Jay Cliburn,
	Realtek linux nic maintainers, Grant Grundler, Wan ZongShun,
	Anirudha Sarangi, linuxppc-dev, Don Fry,
	Thadeu Lima de Souza Cascardo, Roger Luethi, Florian Fainelli,
	linux-arm-kernel, Mirko Lindner, Steffen Klassert, Geoff Levand,
	gregkh, Ralf Baechle, Vitaly Bordug, netdev, Olof Johansson,
	uclinux-dist-devel, Kristoffer Glembo, Sorbica Shieh,
	Krzysztof Halasa
In-Reply-To: <1353349642-3677-198-git-send-email-wfp5p@virginia.edu>

On Mon, Nov 19, 2012 at 01:22:27PM -0500, Bill Pemberton wrote:
>  drivers/net/ethernet/8390/etherh.c                 |  4 +-
>  drivers/net/ethernet/amd/am79c961a.c               |  2 +-
>  drivers/net/ethernet/i825xx/ether1.c               |  8 +-
>  drivers/net/ethernet/seeq/ether3.c                 | 10 +--

For these four,

Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>

^ permalink raw reply

* Re: [PATCH 238/493] mtd: remove use of __devinit
From: Russell King - ARM Linux @ 2012-11-21 11:58 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: Wan ZongShun, gregkh, Kyungmin Park, linux-mtd, Olof Johansson,
	linuxppc-dev, David Woodhouse, linux-arm-kernel
In-Reply-To: <1353349642-3677-238-git-send-email-wfp5p@virginia.edu>

On Mon, Nov 19, 2012 at 01:23:07PM -0500, Bill Pemberton wrote:
>  drivers/mtd/maps/pismo.c               | 14 +++++++-------
>  drivers/mtd/maps/sa1100-flash.c        |  5 ++---

For these two,

Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>

^ permalink raw reply

* Re: [PATCH 192/493] scsi: remove use of __devinit
From: Russell King - ARM Linux @ 2012-11-21 11:51 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: Oliver Neukum, VMware PV-Drivers, Kurt Garloff, Kai Mäkisara,
	GOTO Masanori, linux-scsi, Jamie Lenehan, osst-users,
	Michael Reed, cbe-oss-dev, iss_storagedev, Matthew Wilcox,
	Ali Akcaagac, dc395x, linux-arm-kernel, Neela Syam Kolli,
	Geoff Levand, gregkh, Arvind Kumar, James E.J. Bottomley,
	Willem Riede, YOKOTA Hiroshi, linuxppc-dev, Guennadi Liakhovetski
In-Reply-To: <1353349642-3677-192-git-send-email-wfp5p@virginia.edu>

On Mon, Nov 19, 2012 at 01:22:21PM -0500, Bill Pemberton wrote:
>  drivers/scsi/arm/acornscsi.c              |  2 +-
>  drivers/scsi/arm/arxescsi.c               |  2 +-
>  drivers/scsi/arm/cumana_1.c               |  2 +-
>  drivers/scsi/arm/cumana_2.c               |  2 +-
>  drivers/scsi/arm/eesox.c                  |  2 +-
>  drivers/scsi/arm/oak.c                    |  2 +-
>  drivers/scsi/arm/powertec.c               |  2 +-

For these,

Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>

^ permalink raw reply

* Re: [PATCH 207/493] i2c: remove use of __devinit
From: Barry Song @ 2012-11-21 11:02 UTC (permalink / raw)
  To: Bill Pemberton
  Cc: Rudolf Marek, Tony Lindgren, gregkh, Wolfram Sang,
	DL-SHA-WorkGroupLinux, Olof Johansson, linux-omap,
	Mark M. Hoffman, linux-i2c, Ben Dooks, Barry Song, Jean Delvare,
	Guan Xuetao, linuxppc-dev, linux-arm-kernel
In-Reply-To: <1353349642-3677-207-git-send-email-wfp5p@virginia.edu>

2012/11/20 Bill Pemberton <wfp5p@virginia.edu>:
> CONFIG_HOTPLUG is going away as an option so __devinit is no longer
> needed.
>
> Signed-off-by: Bill Pemberton <wfp5p@virginia.edu>
> Cc: Jean Delvare <khali@linux-fr.org>
> Cc: Wolfram Sang <w.sang@pengutronix.de>
> Cc: "Ben Dooks " <ben-linux@fluff.org>
> Cc: Rudolf Marek <r.marek@assembler.cz>
> Cc: Jochen Friedrich <jochen@scram.de>
> Cc: Peter Korsgaard <jacmet@sunsite.dk>
> Cc: Tony Lindgren <tony@atomide.com>
> Cc: Olof Johansson <olof@lixom.net>
> Cc: Vitaly Wool <vitalywool@gmail.com>
> Cc: Guan Xuetao <gxt@mprc.pku.edu.cn>
> Cc: Barry Song <baohua.song@csr.com>
> Cc: "Mark M. Hoffman" <mhoffman@lightlink.com>
> Cc: linux-i2c@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-omap@vger.kernel.org
> Cc: linux-arm-kernel@lists.infradead.org
> ---

Acked-by: Barry Song <baohua.song@csr.com>

>  drivers/i2c/busses/i2c-ali1535.c            |  4 ++--
>  drivers/i2c/busses/i2c-ali1563.c            |  4 ++--
>  drivers/i2c/busses/i2c-ali15x3.c            |  4 ++--
>  drivers/i2c/busses/i2c-amd756.c             |  2 +-
>  drivers/i2c/busses/i2c-amd8111.c            |  2 +-
>  drivers/i2c/busses/i2c-at91.c               |  6 +++---
>  drivers/i2c/busses/i2c-au1550.c             |  2 +-
>  drivers/i2c/busses/i2c-cpm.c                |  4 ++--
>  drivers/i2c/busses/i2c-designware-pcidrv.c  |  2 +-
>  drivers/i2c/busses/i2c-designware-platdrv.c |  2 +-
>  drivers/i2c/busses/i2c-eg20t.c              |  2 +-
>  drivers/i2c/busses/i2c-elektor.c            |  4 ++--
>  drivers/i2c/busses/i2c-gpio.c               |  4 ++--
>  drivers/i2c/busses/i2c-highlander.c         |  2 +-
>  drivers/i2c/busses/i2c-hydra.c              |  2 +-
>  drivers/i2c/busses/i2c-i801.c               | 14 +++++++-------
>  drivers/i2c/busses/i2c-ibm_iic.c            |  4 ++--
>  drivers/i2c/busses/i2c-intel-mid.c          |  2 +-
>  drivers/i2c/busses/i2c-isch.c               |  2 +-
>  drivers/i2c/busses/i2c-mpc.c                | 20 ++++++++++----------
>  drivers/i2c/busses/i2c-mv64xxx.c            | 12 ++++++------
>  drivers/i2c/busses/i2c-mxs.c                |  2 +-
>  drivers/i2c/busses/i2c-nforce2.c            |  4 ++--
>  drivers/i2c/busses/i2c-nuc900.c             |  2 +-
>  drivers/i2c/busses/i2c-ocores.c             |  2 +-
>  drivers/i2c/busses/i2c-octeon.c             |  6 +++---
>  drivers/i2c/busses/i2c-omap.c               |  2 +-
>  drivers/i2c/busses/i2c-parport-light.c      |  2 +-
>  drivers/i2c/busses/i2c-pasemi.c             |  2 +-
>  drivers/i2c/busses/i2c-pca-isa.c            |  4 ++--
>  drivers/i2c/busses/i2c-pca-platform.c       |  2 +-
>  drivers/i2c/busses/i2c-piix4.c              | 10 +++++-----
>  drivers/i2c/busses/i2c-pmcmsp.c             |  2 +-
>  drivers/i2c/busses/i2c-pnx.c                |  2 +-
>  drivers/i2c/busses/i2c-powermac.c           | 12 ++++++------
>  drivers/i2c/busses/i2c-puv3.c               |  2 +-
>  drivers/i2c/busses/i2c-pxa-pci.c            |  2 +-
>  drivers/i2c/busses/i2c-rcar.c               |  2 +-
>  drivers/i2c/busses/i2c-s6000.c              |  4 ++--
>  drivers/i2c/busses/i2c-sh7760.c             |  4 ++--
>  drivers/i2c/busses/i2c-sirf.c               |  2 +-
>  drivers/i2c/busses/i2c-sis5595.c            |  4 ++--
>  drivers/i2c/busses/i2c-sis630.c             |  4 ++--
>  drivers/i2c/busses/i2c-sis96x.c             |  2 +-
>  drivers/i2c/busses/i2c-tegra.c              |  2 +-
>  drivers/i2c/busses/i2c-via.c                |  2 +-
>  drivers/i2c/busses/i2c-viapro.c             |  2 +-
>  drivers/i2c/busses/i2c-xiic.c               |  2 +-
>  drivers/i2c/busses/i2c-xlr.c                |  2 +-
>  drivers/i2c/busses/scx200_acb.c             | 10 +++++-----
>  drivers/i2c/muxes/i2c-mux-gpio.c            |  4 ++--
>  drivers/i2c/muxes/i2c-mux-pinctrl.c         |  2 +-
>  52 files changed, 103 insertions(+), 103 deletions(-)
>

^ permalink raw reply

* [PATCH 2/2] powerpc/dma/raidengine: enable Freescale RaidEngine device
From: b29237 @ 2012-11-21  9:01 UTC (permalink / raw)
  To: dan.j.williams, vinod.koul, linuxppc-dev, linux-kernel
  Cc: Harninder Rai, Xuelin Shi, Naveen Burmi, iws
In-Reply-To: <1353488481-14371-1-git-send-email-b29237@freescale.com>

From: Xuelin Shi <b29237@freescale.com>

The RaidEngine is a new FSL hardware that used as hardware acceration
for RAID5/6.

This patch enables the RaidEngine functionality and provides hardware
offloading capability for memcpy, xor and raid6 pq computation. It works
under dmaengine control with async_layer interface.

Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
Signed-off-by: Xuelin Shi <b29237@freescale.com>
---
 drivers/dma/Kconfig    |   14 +
 drivers/dma/Makefile   |    1 +
 drivers/dma/fsl_raid.c |  990 ++++++++++++++++++++++++++++++++++++++++++++++++
 drivers/dma/fsl_raid.h |  317 ++++++++++++++++
 4 files changed, 1322 insertions(+)
 create mode 100644 drivers/dma/fsl_raid.c
 create mode 100644 drivers/dma/fsl_raid.h

diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d4c1218..aa37279 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -320,6 +320,20 @@ config MMP_PDMA
 	help
 	  Support the MMP PDMA engine for PXA and MMP platfrom.
 
+config FSL_RAID
+        tristate "Freescale RAID Engine Device Driver"
+        depends on FSL_SOC && !FSL_DMA
+        select DMA_ENGINE
+        select ASYNC_TX_ENABLE_CHANNEL_SWITCH
+        select ASYNC_MEMCPY
+        select ASYNC_XOR
+        select ASYNC_PQ
+        ---help---
+          Enable support for Freescale RAID Engine. RAID Engine is
+          available on some QorIQ SoCs (like P5020). It has
+          the capability to offload RAID5/RAID6 operations from CPU.
+          RAID5 is XOR and memcpy. RAID6 is P/Q and memcpy
+
 config DMA_ENGINE
 	bool
 
diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile
index 7428fea..29b65eb 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -9,6 +9,7 @@ obj-$(CONFIG_DMATEST) += dmatest.o
 obj-$(CONFIG_INTEL_IOATDMA) += ioat/
 obj-$(CONFIG_INTEL_IOP_ADMA) += iop-adma.o
 obj-$(CONFIG_FSL_DMA) += fsldma.o
+obj-$(CONFIG_FSL_RAID) += fsl_raid.o
 obj-$(CONFIG_MPC512X_DMA) += mpc512x_dma.o
 obj-$(CONFIG_MV_XOR) += mv_xor.o
 obj-$(CONFIG_DW_DMAC) += dw_dmac.o
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
new file mode 100644
index 0000000..ec19817
--- /dev/null
+++ b/drivers/dma/fsl_raid.c
@@ -0,0 +1,990 @@
+/*
+ * drivers/dma/fsl_raid.c
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ *	Harninder Rai <harninder.rai@freescale.com>
+ *	Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Theory of operation:
+ *
+ * General capabilities:
+ *	RAID Engine (RE) block is capable of offloading XOR, memcpy and P/Q
+ *	calculations required in RAID5 and RAID6 operations. RE driver
+ *	registers with Linux's ASYNC layer as dma driver. RE hardware
+ *	maintains strict ordering of the requests through chained
+ *	command queueing.
+ *
+ * Data flow:
+ *	Software RAID layer of Linux (MD layer) maintains RAID partitions,
+ *	strips, stripes etc. It sends requests to the underlying AYSNC layer
+ *	which further passes it to RE driver. ASYNC layer decides which request
+ *	goes to which job ring of RE hardware. For every request processed by
+ *	RAID Engine, driver gets an interrupt unless coalescing is set. The
+ *	per job ring interrupt handler checks the status register for errors,
+ *	clears the interrupt and schedules a tasklet. Main request processing
+ *	is done in tasklet. A software shadow copy of the HW ring is kept to
+ *	maintain virtual to physical translation. Based on the internal indexes
+ *	maintained, the tasklet picks the descriptor address from shadow copy,
+ *	updates the corresponding cookie, updates the outbound ring job removed
+ *	register in RE hardware and eventually calls the callback function. This
+ *	callback function gets passed as part of request from MD layer.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+
+#include "fsl_raid.h"
+
+#define MAX_XOR_SRCS		16
+#define MAX_PQ_SRCS		16
+#define MAX_INITIAL_DESCS	256
+#define FRAME_FORMAT		0x1
+#define MAX_DATA_LENGTH		(1024*1024)
+
+#define to_fsl_re_dma_desc(tx) container_of(tx, \
+		struct fsl_re_dma_async_tx_desc, async_tx)
+
+/* Add descriptors into per jr software queue - submit_q */
+static dma_cookie_t re_jr_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct fsl_re_dma_async_tx_desc *desc = NULL;
+	struct re_jr *jr = NULL;
+	dma_cookie_t cookie;
+
+	desc = container_of(tx, struct fsl_re_dma_async_tx_desc, async_tx);
+	jr = container_of(tx->chan, struct re_jr, chan);
+
+	spin_lock_bh(&jr->inb_lock);
+
+	jr->timer.data = (unsigned long)tx->chan;
+	cookie = jr->chan.cookie + 1;
+	if (cookie < 0)
+		cookie = 1;
+
+	desc->async_tx.cookie = cookie;
+	jr->chan.cookie = desc->async_tx.cookie;
+	jr->pend_count++;
+
+	if (!timer_pending(&jr->timer))
+		add_timer(&jr->timer);
+
+	spin_unlock_bh(&jr->inb_lock);
+
+	return cookie;
+}
+
+static void re_jr_unmap_dest_src(struct fsl_re_dma_async_tx_desc *desc)
+{
+	int i, j;
+	struct cmpnd_frame *cf;
+	dma_addr_t dest1 = 0, dest2 = 0, src;
+	struct device *dev;
+	enum dma_ctrl_flags flags;
+	enum dma_data_direction dir;
+
+	BUG_ON(!desc);
+	cf = desc->cf_addr;
+	dest1 = cf[1].address;
+	j = 2;
+	if (desc->dest_cnt == 2) {
+		dest2 = cf[2].address;
+		j = 3;
+	}
+	dev = desc->jr->chan.device->dev;
+	flags = desc->async_tx.flags;
+	if (!(flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (desc->cdb_opcode == RE_MOVE_OPCODE)
+			dir = DMA_FROM_DEVICE;
+		else
+			dir = DMA_BIDIRECTIONAL;
+
+		dma_unmap_page(dev, dest1, desc->dma_len, dir);
+
+		if (dest2)
+			dma_unmap_page(dev, dest2, desc->dma_len, dir);
+	}
+
+	if (!(flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		dir = DMA_TO_DEVICE;
+		for (i = j; i < desc->src_cnt+j; i++) {
+			src = cf[i].address;
+			if (src == dest1 || src == dest2)
+				continue;
+			dma_unmap_page(dev, src, desc->dma_len, dir);
+		}
+	}
+}
+
+static void re_jr_desc_done(struct fsl_re_dma_async_tx_desc *desc)
+{
+	struct re_jr *dma_jr = desc->jr;
+	dma_async_tx_callback callback;
+	void *callback_param;
+
+	callback = desc->async_tx.callback;
+	callback_param = desc->async_tx.callback_param;
+
+	dma_run_dependencies(&desc->async_tx);
+
+	if (dma_jr->completed_cookie < desc->async_tx.cookie) {
+		dma_jr->completed_cookie = desc->async_tx.cookie;
+		if (dma_jr->completed_cookie == DMA_MAX_COOKIE)
+			dma_jr->completed_cookie = DMA_MIN_COOKIE;
+	}
+
+	re_jr_unmap_dest_src(desc);
+
+	if (callback)
+		callback(callback_param);
+
+}
+
+/*
+ * Get the virtual address of software desc from virt_addr.
+ * Storing the address of software desc like this makes the
+ * order of alogorithm as O(1)
+ */
+static void re_jr_dequeue(unsigned long data)
+{
+	struct device *dev;
+	struct re_jr *jr;
+	struct fsl_re_dma_async_tx_desc *desc;
+	unsigned int count;
+	struct fsl_re_dma_async_tx_desc *ack_desc = NULL, *_ack_desc = NULL;
+
+	dev = (struct device *)data;
+	jr = dev_get_drvdata(dev);
+
+	while ((count =
+		RE_JR_OUB_SLOT_FULL(in_be32(&jr->jrregs->oubring_slot_full)))) {
+		while (count--) {
+			spin_lock_bh(&jr->oub_lock);
+			jr->oub_count &= RING_SIZE - 1;
+			desc = &jr->descs[jr->oub_count++];
+
+			/* One job processed */
+			out_be32(&jr->jrregs->oubring_job_rmvd,
+				RE_JR_OUB_JOB_REMOVE(1));
+			spin_unlock_bh(&jr->oub_lock);
+
+			spin_lock_bh(&jr->desc_lock);
+			list_add_tail(&desc->node, &jr->ack_q);
+			re_jr_desc_done(desc);
+			spin_unlock_bh(&jr->desc_lock);
+		}
+	}
+
+	/* To save memory, parse the ack_q and free up descs */
+	list_for_each_entry_safe(ack_desc, _ack_desc, &jr->ack_q, node) {
+		if (async_tx_test_ack(&ack_desc->async_tx)) {
+			spin_lock_bh(&jr->desc_lock);
+			list_del(&ack_desc->node);
+			ack_desc->state = RE_DESC_EMPTY;
+			ack_desc->async_tx.flags = 0;
+			spin_unlock_bh(&jr->desc_lock);
+		}
+	}
+}
+
+/* Per Job Ring interrupt handler */
+static irqreturn_t re_jr_interrupt(int irq, void *data)
+{
+	struct device *dev = data;
+	struct re_jr *jr = dev_get_drvdata(dev);
+	u32 irqstate, status;
+
+	irqstate = in_be32(&jr->jrregs->jr_interrupt_status);
+	if (!irqstate)
+		return IRQ_NONE;
+
+	/*
+	 * There's no way in upper layer (read MD layer) to recover from
+	 * error conditions except restart everything. In long term we
+	 * need to do something more than just crashing
+	 */
+	if (irqstate & RE_JR_ERROR) {
+		status = in_be32(&jr->jrregs->jr_status);
+		dev_err(dev, "%s: jr error irqstate: %x, status: %x\n",
+					__func__, irqstate, status);
+
+		BUG();
+	}
+
+	/* Clear interrupt */
+	out_be32(&jr->jrregs->jr_interrupt_status, RE_JR_CLEAR_INT);
+
+	tasklet_schedule(&jr->irqtask);
+
+	return IRQ_HANDLED;
+}
+
+static enum dma_status re_jr_tx_status(struct dma_chan *chan,
+		dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct re_jr *jr = NULL;
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+
+	jr = container_of(chan, struct re_jr, chan);
+	last_used = chan->cookie;
+	smp_mb();
+	last_complete = jr->completed_cookie;
+
+	dma_set_tx_state(txstate, last_complete, last_used, 0);
+
+	return dma_async_is_complete(cookie, last_complete, last_used);
+}
+
+
+/* Copy descriptor from per jr software queue into hardware job ring */
+void re_jr_issue_pending(struct dma_chan *chan)
+{
+	struct re_jr *jr = NULL;
+	int avail = 0;
+
+	jr = container_of(chan, struct re_jr, chan);
+	if (timer_pending(&jr->timer))
+		del_timer_sync(&jr->timer);
+
+	spin_lock_bh(&jr->inb_lock);
+
+	avail = RE_JR_INB_SLOT_AVAIL(in_be32(&jr->jrregs->inbring_slot_avail));
+
+	if (!(avail && jr->pend_count))
+		goto out_unlock;
+
+	if (avail > jr->pend_count)
+		avail = jr->pend_count;
+
+	jr->pend_count -= avail;
+	jr->inb_count = (jr->inb_count + avail) & (RING_SIZE - 1);
+
+	/* add jobs into job ring */
+	out_be32(&jr->jrregs->inbring_add_job, RE_JR_INB_JOB_ADD(avail));
+
+out_unlock:
+	spin_unlock_bh(&jr->inb_lock);
+}
+
+/* Per Job Ring timer handler */
+static void raide_timer_handler(unsigned long data)
+{
+	struct dma_chan *chan = NULL;
+	chan = (struct dma_chan *)data;
+
+	re_jr_issue_pending(chan);
+
+	return;
+}
+
+inline void fill_cfd_frame(struct cmpnd_frame *cf, u8 index,
+		size_t length, dma_addr_t addr, bool final)
+{
+	cf[index].final = final;
+	cf[index].length = length;
+	cf[index].address = addr;
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_init_desc(struct re_jr *jr,
+	struct fsl_re_dma_async_tx_desc *desc, void *cf, dma_addr_t paddr)
+{
+	desc->jr = jr;
+	desc->async_tx.tx_submit = re_jr_tx_submit;
+	dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
+	INIT_LIST_HEAD(&desc->node);
+
+	desc->hwdesc->format = FRAME_FORMAT;
+	desc->hwdesc->address = paddr;
+	desc->cf_addr = cf;
+
+	desc->cdb_addr = (void *)(cf + RE_CF_DESC_SIZE);
+	desc->cdb_paddr = paddr + RE_CF_DESC_SIZE;
+
+	return desc;
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_alloc_desc(struct re_jr *jr,
+		unsigned long flags)
+{
+	struct fsl_re_dma_async_tx_desc *desc;
+
+	spin_lock_bh(&jr->inb_lock);
+
+	jr->inb_count &= RING_SIZE - 1;
+	desc = &jr->descs[jr->inb_count];
+
+	if (desc->state != RE_DESC_EMPTY) {
+		spin_unlock_bh(&jr->inb_lock);
+		re_jr_issue_pending(&jr->chan);
+		return NULL;
+	}
+	spin_unlock_bh(&jr->inb_lock);
+
+	desc->state = RE_DESC_ALLOC;
+	desc->async_tx.flags = flags;
+	return desc;
+}
+
+static struct dma_async_tx_descriptor *re_jr_prep_genq(
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+		unsigned int src_cnt, const unsigned char *scf, size_t len,
+		unsigned long flags)
+{
+	struct re_jr *jr = NULL;
+	struct fsl_re_dma_async_tx_desc *desc = NULL;
+	struct xor_cdb *xor = NULL;
+	struct cmpnd_frame *cf;
+	unsigned int i = 0;
+	unsigned int j = 0;
+
+	if (len > MAX_DATA_LENGTH) {
+		pr_err("%s: Length greater than %d not supported\n",
+				__func__, MAX_DATA_LENGTH);
+		return NULL;
+	}
+	jr = container_of(chan, struct re_jr, chan);
+	desc = re_jr_alloc_desc(jr, flags);
+	if (!desc || desc < 0)
+		return NULL;
+
+	desc->dma_len = len;
+	desc->dest_cnt = 1;
+	desc->src_cnt = src_cnt;
+
+	desc->cdb_opcode = RE_XOR_OPCODE;
+	desc->cdb_len = sizeof(struct xor_cdb);
+
+	/* Filling xor CDB */
+	xor = desc->cdb_addr;
+	xor->opcode = RE_XOR_OPCODE;
+	xor->nrcs = (src_cnt - 1);
+	xor->blk_size = RE_BLOCK_SIZE;
+	xor->error_attrib = INTERRUPT_ON_ERROR;
+	xor->data_depend = DATA_DEPENDENCY;
+
+	if (scf != NULL) {
+		/* compute q = src0*coef0^src1*coef1^..., * is GF(8) mult */
+		for (i = 0; i < src_cnt; i++)
+			xor->gfm[i] = scf[i];
+	} else {
+		/* compute P, that is XOR all srcs */
+		for (i = 0; i < src_cnt; i++)
+			xor->gfm[i] = 1;
+	}
+
+	/* Filling frame 0 of compound frame descriptor with CDB */
+	cf = desc->cf_addr;
+	fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+	/* Fill CFD's 1st frame with dest buffer */
+	fill_cfd_frame(cf, 1, len, dest, 0);
+
+	/* Fill CFD's rest of the frames with source buffers */
+	for (i = 2, j = 0; j < src_cnt; i++, j++)
+		fill_cfd_frame(cf, i, len, src[j], 0);
+
+	/* Setting the final bit in the last source buffer frame in CFD */
+	cf[i - 1].final = 1;
+
+	return &desc->async_tx;
+}
+
+/*
+ * Prep function for P parity calculation.In RAID Engine terminology,
+ * XOR calculation is called GenQ calculation done through GenQ command
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_dma_xor(
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t *src,
+		unsigned int src_cnt, size_t len, unsigned long flags)
+{
+	/* NULL let genq take all coef as 1 */
+	return re_jr_prep_genq(chan, dest, src, src_cnt, NULL, len, flags);
+}
+
+/*
+ * Prep function for P/Q parity calculation.In RAID Engine terminology,
+ * P/Q calculation is called GenQQ done through GenQQ command
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_pq(
+		struct dma_chan *chan, dma_addr_t *dest, dma_addr_t *src,
+		unsigned int src_cnt, const unsigned char *scf, size_t len,
+		unsigned long flags)
+{
+	struct re_jr *jr = NULL;
+	struct fsl_re_dma_async_tx_desc *desc = NULL;
+	struct pq_cdb *pq = NULL;
+	struct cmpnd_frame *cf;
+	u8 *p;
+	int gfmq_len, i, j;
+
+	if (len > MAX_DATA_LENGTH) {
+		pr_err("%s: Length greater than %d not supported\n",
+				__func__, MAX_DATA_LENGTH);
+		return NULL;
+	}
+
+	/*
+	 * RE requires at least 2 sources, if given only one source, we pass the
+	 * second source same as the first one.
+	 * With only one source, generate P is meaningless, only care Q.
+	 */
+	if (src_cnt == 1) {
+		struct dma_async_tx_descriptor *tx = NULL;
+		dma_addr_t dma_src[2];
+		unsigned char coef[2];
+		dma_src[0] = *src;
+		coef[0] = *scf;
+		dma_src[1] = *src;
+		coef[1] = 0;
+		tx = re_jr_prep_genq(chan, dest[1], dma_src, 2, coef, len,
+				flags);
+		if (tx) {
+			desc = to_fsl_re_dma_desc(tx);
+			desc->src_cnt = 1;
+		}
+		return tx;
+	}
+
+	/*
+	 * During RAID6 array creation, Linux's MD layer gets P and Q
+	 * calculated separately in two steps. But our RAID Engine has
+	 * the capability to calculate both P and Q with a single command
+	 * Hence to merge well with MD layer, we need to provide a hook
+	 * here and call re_jq_prep_genq() function
+	 */
+
+	if (flags & DMA_PREP_PQ_DISABLE_P)
+		return re_jr_prep_genq(chan, dest[1], src, src_cnt,
+				scf, len, flags);
+
+	jr = container_of(chan, struct re_jr, chan);
+	desc = re_jr_alloc_desc(jr, flags);
+	if (!desc || desc < 0)
+		return NULL;
+
+	desc->dma_len = len;
+	desc->dest_cnt = 2;
+	desc->src_cnt = src_cnt;
+
+	desc->cdb_opcode = RE_PQ_OPCODE;
+	desc->cdb_len = sizeof(struct pq_cdb);
+
+	/* Filling GenQQ CDB */
+	pq = desc->cdb_addr;
+	pq->opcode = RE_PQ_OPCODE;
+	pq->blk_size = RE_BLOCK_SIZE;
+	pq->buffer_attrib = BUFFERABLE_OUTPUT;
+	pq->data_depend = DATA_DEPENDENCY;
+	pq->nrcs = (src_cnt - 1);
+
+	p = pq->gfm_q1;
+	/* Init gfm_q1[] */
+	for (i = 0; i < src_cnt; i++)
+		p[i] = 1;
+
+	/* Align gfm[] to 32bit */
+	gfmq_len = ((src_cnt+3)/4)*4;
+
+	/* Init gfm_q2[] */
+	p += gfmq_len;
+	for (i = 0; i < src_cnt; i++)
+		p[i] = scf[i];
+
+	/* Filling frame 0 of compound frame descriptor with CDB */
+	cf = desc->cf_addr;
+	fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+	/* Fill CFD's 1st & 2nd frame with dest buffers */
+	for (i = 1, j = 0; i < 3; i++, j++)
+		fill_cfd_frame(cf, i, len, dest[j], 0);
+
+	/* Fill CFD's rest of the frames with source buffers */
+	for (i = 3, j = 0; j < src_cnt; i++, j++)
+		fill_cfd_frame(cf, i, len, src[j], 0);
+
+	/* Setting the final bit in the last source buffer frame in CFD */
+	cf[i - 1].final = 1;
+
+	return &desc->async_tx;
+}
+
+/*
+ * Prep function for memcpy. In RAID Engine, memcpy is done through MOVE
+ * command. Logic of this function will need to be modified once multipage
+ * support is added in Linux's MD/ASYNC Layer
+ */
+static struct dma_async_tx_descriptor *re_jr_prep_memcpy(
+		struct dma_chan *chan, dma_addr_t dest, dma_addr_t src,
+		size_t len, unsigned long flags)
+{
+	struct re_jr *jr = NULL;
+	struct fsl_re_dma_async_tx_desc *desc = NULL;
+	size_t length = 0;
+	struct cmpnd_frame *cf = NULL;
+	struct move_cdb *move = NULL;
+
+	jr = container_of(chan, struct re_jr, chan);
+
+	if (len > MAX_DATA_LENGTH) {
+		pr_err("%s: Length greater than %d not supported\n",
+				__func__, MAX_DATA_LENGTH);
+		return NULL;
+	}
+
+	desc = re_jr_alloc_desc(jr, flags);
+	if (!desc || desc < 0)
+		return NULL;
+
+	desc->dma_len = len;
+	desc->src_cnt = 1;
+	desc->dest_cnt = 1;
+
+	desc->cdb_opcode = RE_MOVE_OPCODE;
+	desc->cdb_len = sizeof(struct move_cdb);
+
+	/* Filling move CDB */
+	move = desc->cdb_addr;
+	move->opcode = RE_MOVE_OPCODE; /* Unicast move */
+	move->blk_size = RE_BLOCK_SIZE;
+	move->error_attrib = INTERRUPT_ON_ERROR;
+	move->data_depend = DATA_DEPENDENCY;
+
+	/* Filling frame 0 of CFD with move CDB */
+	cf = desc->cf_addr;
+	fill_cfd_frame(cf, 0, desc->cdb_len, desc->cdb_paddr, 0);
+
+	length = min_t(size_t, len, MAX_DATA_LENGTH);
+
+	/* Fill CFD's 1st frame with dest buffer */
+	fill_cfd_frame(cf, 1, length, dest, 0);
+
+	/* Fill CFD's 2nd frame with src buffer */
+	fill_cfd_frame(cf, 2, length, src, 1);
+
+	return &desc->async_tx;
+}
+
+static int re_jr_alloc_chan_resources(struct dma_chan *chan)
+{
+	int i;
+	struct fsl_re_dma_async_tx_desc *desc;
+	struct re_jr *jr = container_of(chan, struct re_jr, chan);
+	void *cf = NULL;
+	dma_addr_t paddr;
+
+	jr->descs = kzalloc(sizeof(*desc) * RING_SIZE, GFP_KERNEL);
+	if (!jr->descs) {
+		dev_err(jr->dev, "%s: No memory for sw descriptor ring\n",
+			__func__);
+		goto err_free;
+	}
+
+	cf = dma_pool_alloc(jr->re_dev->desc_pool, GFP_ATOMIC, &paddr);
+	if (!cf) {
+		dev_err(jr->dev, "%s: No memory for dma descriptor ring\n",
+			__func__);
+		goto err_free;
+	}
+	memset(cf, 0, RE_CF_CDB_SIZE * RING_SIZE);
+	jr->cfs = cf;
+	jr->phys = paddr;
+
+	for (i = 0; i < RING_SIZE; i++) {
+		u32 offset = i * RE_CF_CDB_SIZE;
+		desc = &jr->descs[i];
+		desc->hwdesc = &jr->inb_ring_virt_addr[i];
+		re_jr_init_desc(jr, desc, cf + offset, paddr + offset);
+		desc->state = RE_DESC_EMPTY;
+	}
+	return 0;
+
+err_free:
+	kfree(jr->descs);
+	return -ENOMEM;
+}
+
+static void re_jr_free_chan_resources(struct dma_chan *chan)
+{
+	struct re_jr *jr = container_of(chan, struct re_jr, chan);
+	dma_pool_free(jr->re_dev->desc_pool, jr->cfs, jr->phys);
+	kfree(jr->descs);
+	return;
+}
+
+int re_jr_probe(struct platform_device *ofdev,
+		struct device_node *np, u8 q, u32 *off)
+{
+	struct device *dev = NULL;
+	struct re_drv_private *repriv = NULL;
+	struct re_jr *jr = NULL;
+	struct dma_device *dma_dev = NULL;
+	u32 *ptr = NULL;
+	u32 status;
+	int ret = 0;
+	struct platform_device *jr_ofdev = NULL;
+
+	dev = &ofdev->dev;
+	repriv = dev_get_drvdata(dev);
+	dma_dev = &repriv->dma_dev;
+
+	jr = kzalloc(sizeof(struct re_jr), GFP_KERNEL);
+	if (!jr) {
+		dev_err(dev, "%s: No free memory for allocating JR struct\n",
+			__func__);
+		return -ENOMEM;
+	}
+
+	jr_ofdev = of_platform_device_create(np, NULL, dev);
+	if (jr_ofdev == NULL) {
+		dev_err(dev, "%s: Not able to create ofdev for jr %d\n",
+			__func__, q);
+		ret = -EINVAL;
+		goto err_free;
+	}
+	dev_set_drvdata(&jr_ofdev->dev, jr);
+
+	ptr = (u32 *)of_get_property(np, "reg", NULL);
+	if (!ptr) {
+		dev_err(dev, "%s: Reg property not found in JR number %d\n",
+			__func__, q);
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	jr->jrregs = (struct jr_config_regs *)((u8 *)repriv->re_regs +
+			*off + *ptr);
+
+	jr->irq = irq_of_parse_and_map(np, 0);
+	if (jr->irq == NO_IRQ) {
+		dev_err(dev, "%s: No IRQ defined for JR %d\n", __func__, q);
+		ret = -ENODEV;
+		goto err_free;
+	}
+
+	tasklet_init(&jr->irqtask, re_jr_dequeue,
+			(unsigned long)&jr_ofdev->dev);
+
+	ret = request_irq(jr->irq, re_jr_interrupt, 0, "re-jr", &jr_ofdev->dev);
+	if (ret) {
+		dev_err(dev, "%s: Unable to register JR interrupt for JR %d\n",
+			__func__, q);
+		ret = -EINVAL;
+		goto err_free;
+	}
+
+	repriv->re_jrs[q] = jr;
+	jr->chan.device = dma_dev;
+	jr->chan.private = jr;
+	jr->dev = &jr_ofdev->dev;
+	jr->re_dev = repriv;
+	jr->pend_count = 0;
+	INIT_LIST_HEAD(&jr->ack_q);
+	spin_lock_init(&jr->desc_lock);
+	spin_lock_init(&jr->inb_lock);
+	spin_lock_init(&jr->oub_lock);
+
+	init_timer(&jr->timer);
+	jr->timer.expires = jiffies + 10*HZ;
+	jr->timer.function = raide_timer_handler;
+
+	list_add_tail(&jr->chan.device_node, &dma_dev->channels);
+	dma_dev->chancnt++;
+
+	jr->inb_ring_virt_addr = dma_pool_alloc(jr->re_dev->hw_desc_pool,
+		GFP_ATOMIC, &jr->inb_phys_addr);
+
+	if (!jr->inb_ring_virt_addr) {
+		dev_err(dev, "%s:No dma memory for inb_ring_virt_addr\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	jr->oub_ring_virt_addr = dma_pool_alloc(jr->re_dev->hw_desc_pool,
+		GFP_ATOMIC, &jr->oub_phys_addr);
+
+	if (!jr->oub_ring_virt_addr) {
+		dev_err(dev, "%s:No dma memory for oub_ring_virt_addr\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free;
+	}
+
+	jr->inb_count = 0;
+	jr->pend_count = 0;
+	jr->oub_count = 0;
+
+	status = in_be32(&jr->jrregs->jr_status);
+
+	if (status & RE_JR_PAUSE) {
+		dev_info(dev, "%s: JR is in paused state...enable it\n",
+			__func__);
+	} else {
+		dev_err(dev, "%s: Error:- JR shud be in paused state\n",
+			__func__);
+		ret = -EINVAL;
+		goto pool_free;
+	}
+
+	/* Program the Inbound/Outbound ring base addresses and size */
+	out_be32(&jr->jrregs->inbring_base_h,
+			jr->inb_phys_addr & RE_JR_ADDRESS_BIT_MASK);
+	out_be32(&jr->jrregs->oubring_base_h,
+			jr->oub_phys_addr & RE_JR_ADDRESS_BIT_MASK);
+	out_be32(&jr->jrregs->inbring_base_l,
+			jr->inb_phys_addr >> RE_JR_ADDRESS_BIT_SHIFT);
+	out_be32(&jr->jrregs->oubring_base_l,
+			jr->oub_phys_addr >> RE_JR_ADDRESS_BIT_SHIFT);
+	out_be32(&jr->jrregs->inbring_size, RING_SIZE << RING_SIZE_SHIFT);
+	out_be32(&jr->jrregs->oubring_size, RING_SIZE << RING_SIZE_SHIFT);
+
+	/* Read LIODN value from u-boot */
+	status = in_be32(&jr->jrregs->jr_config_1) & RE_JR_REG_LIODN_MASK;
+
+	/* Program the CFG reg */
+	out_be32(&jr->jrregs->jr_config_1,
+			RE_JR_CFG1_CBSI | RE_JR_CFG1_CBS0 | status);
+
+	/* Enable RE/JR */
+	out_be32(&jr->jrregs->jr_command, RE_JR_ENABLE);
+
+	return 0;
+
+pool_free:
+	dma_pool_free(jr->re_dev->hw_desc_pool, jr->inb_ring_virt_addr,
+			jr->inb_phys_addr);
+err_free:
+	kfree(jr);
+	return ret;
+}
+
+/* Probe function for RAID Engine */
+static int __devinit raide_probe(struct platform_device *ofdev)
+{
+	struct re_drv_private *repriv = NULL;
+	struct device *dev = NULL;
+	struct device_node *np = NULL;
+	struct device_node *child = NULL;
+	u32 *off = NULL;
+	u8 ridx = 0;
+	struct dma_device *dma_dev = NULL;
+	int ret = 0;
+
+	dev_info(&ofdev->dev, "Freescale RAID Engine driver\n");
+
+	repriv = kzalloc(sizeof(struct re_drv_private), GFP_KERNEL);
+	if (!repriv) {
+		dev_err(dev, "%s: No memory for repriv\n", __func__);
+		return -ENOMEM;
+	}
+
+	dev = &ofdev->dev;
+	dev_set_drvdata(dev, repriv);
+
+	/* IOMAP the entire RAID Engine region */
+	repriv->re_regs = of_iomap(ofdev->dev.of_node, 0);
+	if (repriv->re_regs == NULL) {
+		dev_err(dev, "%s: of_iomap failed\n", __func__);
+		kfree(repriv);
+		ret = -ENOMEM;
+		goto err_free_4;
+	}
+
+	/* Print the RE version to make sure RE is alive */
+	dev_info(dev, "Ver = %x\n", in_be32(&repriv->re_regs->re_version_id));
+
+	/* Program the RE mode */
+	out_be32(&repriv->re_regs->global_config, RE_NON_DPAA_MODE);
+	dev_info(dev, "%s:RE mode is %x\n", __func__,
+			in_be32(&repriv->re_regs->global_config));
+
+	/* Program Galois Field polynomial */
+	out_be32(&repriv->re_regs->galois_field_config, RE_GFM_POLY);
+	dev_info(dev, "%s:Galois Field Polynomial is %x\n", __func__,
+			in_be32(&repriv->re_regs->galois_field_config));
+
+	dma_dev = &repriv->dma_dev;
+	dma_dev->dev = dev;
+	INIT_LIST_HEAD(&dma_dev->channels);
+	dma_set_mask(dev, DMA_BIT_MASK(40));
+
+	dma_dev->device_alloc_chan_resources = re_jr_alloc_chan_resources;
+	dma_dev->device_tx_status = re_jr_tx_status;
+	dma_dev->device_issue_pending = re_jr_issue_pending;
+
+	dma_dev->max_xor = MAX_XOR_SRCS;
+	dma_dev->device_prep_dma_xor = re_jr_prep_dma_xor;
+	dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+
+	dma_dev->max_pq = MAX_PQ_SRCS;
+	dma_dev->device_prep_dma_pq = re_jr_prep_pq;
+	dma_cap_set(DMA_PQ, dma_dev->cap_mask);
+
+	dma_dev->device_prep_dma_memcpy = re_jr_prep_memcpy;
+	dma_cap_set(DMA_MEMCPY, dma_dev->cap_mask);
+
+	dma_dev->device_free_chan_resources = re_jr_free_chan_resources;
+
+	repriv->total_jrs = 0;
+
+	repriv->desc_pool = dma_pool_create("re_dma_desc_pool", dev,
+					RE_CF_CDB_SIZE * RING_SIZE,
+					RE_CF_CDB_ALIGN, 0);
+
+	if (!repriv->desc_pool) {
+		pr_err("%s:No memory for dma desc pool\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_3;
+	}
+
+	repriv->hw_desc_pool = dma_pool_create("re_hw_desc_pool", dev,
+				sizeof(struct jr_hw_desc) * RING_SIZE,
+				FRAME_DESC_ALIGNMENT, 0);
+	if (!repriv->hw_desc_pool) {
+		pr_err("%s:No memory for hw desc pool\n", __func__);
+		ret = -ENOMEM;
+		goto err_free_2;
+	}
+
+	/* Parse Device tree to find out the total number of JQs present */
+	for_each_compatible_node(np, NULL, "fsl,raideng-v1.0-job-queue") {
+		off = (u32 *)of_get_property(np, "reg", NULL);
+		if (!off) {
+			dev_err(dev, "%s: Reg property not found in JQ node\n",
+				__func__);
+			return -ENODEV;
+		}
+
+		/* Find out the Job Rings present under each JQ */
+		for_each_child_of_node(np, child) {
+			if (of_device_is_compatible(child,
+				"fsl,raideng-v1.0-job-ring")) {
+				re_jr_probe(ofdev, child, ridx++, off);
+				repriv->total_jrs++;
+			}
+		}
+	}
+
+	dma_async_device_register(dma_dev);
+	return 0;
+
+err_free_2:
+	dma_pool_destroy(repriv->desc_pool);
+err_free_3:
+	iounmap(repriv->re_regs);
+err_free_4:
+	kfree(repriv);
+
+	return ret;
+}
+
+static void release_jr(struct re_jr *jr)
+{
+	/* Free the memory allocated from DMA pools and destroy them */
+	dma_pool_free(jr->re_dev->hw_desc_pool, jr->inb_ring_virt_addr,
+		jr->inb_phys_addr);
+	kfree(jr);
+}
+
+static int raide_remove(struct platform_device *ofdev)
+{
+	struct re_drv_private *repriv = NULL;
+	struct device *dev = NULL;
+	int i;
+
+	dev = &ofdev->dev;
+	repriv = dev_get_drvdata(dev);
+
+	/* Cleanup JR related memory areas */
+	for (i = 0; i < repriv->total_jrs; i++)
+		release_jr(repriv->re_jrs[i]);
+
+	dma_pool_destroy(repriv->hw_desc_pool);
+	dma_pool_destroy(repriv->desc_pool);
+
+	/* Unregister the driver */
+	dma_async_device_unregister(&repriv->dma_dev);
+
+	/* Unmap the RAID Engine region */
+	iounmap(repriv->re_regs);
+
+	kfree(repriv);
+
+	return 0;
+}
+
+static struct of_device_id raide_ids[] = {
+	{ .compatible = "fsl,raideng-v1.0", },
+	{}
+};
+
+static struct platform_driver raide_driver = {
+	.driver = {
+		.name = "fsl-raideng",
+		.owner = THIS_MODULE,
+		.of_match_table = raide_ids,
+	},
+	.probe = raide_probe,
+	.remove = raide_remove,
+};
+
+static __init int raide_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&raide_driver);
+	if (ret)
+		pr_err("fsl-raid: Failed to register platform driver\n");
+
+	return ret;
+}
+
+static void __exit raide_exit(void)
+{
+	platform_driver_unregister(&raide_driver);
+}
+
+subsys_initcall(raide_init);
+module_exit(raide_exit);
+
+MODULE_AUTHOR("Harninder Rai <harninder.rai@freescale.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Freescale RAID Engine Device Driver");
diff --git a/drivers/dma/fsl_raid.h b/drivers/dma/fsl_raid.h
new file mode 100644
index 0000000..3cb8454
--- /dev/null
+++ b/drivers/dma/fsl_raid.h
@@ -0,0 +1,317 @@
+/*
+ * drivers/dma/fsl_raid.h
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ *	Harninder Rai <harninder.rai@freescale.com>
+ *	Naveen Burmi <naveenburmi@freescale.com>
+ *
+ * Copyright (c) 2010-2012 Freescale Semiconductor, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#define RE_DPAA_MODE		(1 << 30)
+#define RE_NON_DPAA_MODE	(1 << 31)
+#define RE_GFM_POLY		(0x1d000000)
+#define RE_JR_INB_JOB_ADD(x)	((x) << 16)
+#define RE_JR_OUB_JOB_REMOVE(x)	((x) << 16)
+#define RE_JR_CFG1_CBSI		0x08000000
+#define RE_JR_CFG1_CBS0		0x00080000
+#define RE_JR_OUB_SLOT_FULL_SHIFT	8
+#define RE_JR_OUB_SLOT_FULL(x)	((x) >> RE_JR_OUB_SLOT_FULL_SHIFT)
+#define RE_JR_INB_SLOT_AVAIL_SHIFT	8
+#define RE_JR_INB_SLOT_AVAIL(x)	((x) >> RE_JR_INB_SLOT_AVAIL_SHIFT)
+#define RE_PQ_OPCODE		0x1B
+#define RE_XOR_OPCODE		0x1A
+#define RE_MOVE_OPCODE		0x8
+#define FRAME_DESC_ALIGNMENT	16
+#define RE_BLOCK_SIZE		0x3 /* 4096 bytes */
+#define CACHEABLE_INPUT_OUTPUT	0x0
+#define BUFFERABLE_OUTPUT	0x0
+#define INTERRUPT_ON_ERROR	0x1
+#define DATA_DEPENDENCY		0x1
+#define ENABLE_DPI		0x0
+#define RING_SIZE		0x1000
+#define RING_SIZE_SHIFT		8
+#define RE_JR_ADDRESS_BIT_SHIFT	4
+#define RE_JR_ADDRESS_BIT_MASK	((1 << RE_JR_ADDRESS_BIT_SHIFT) - 1)
+#define RE_JR_ERROR		0x40000000
+#define RE_JR_INTERRUPT		0x80000000
+#define RE_JR_CLEAR_INT		0x80000000
+#define RE_JR_PAUSE		0x80000000
+#define RE_JR_ENABLE		0x80000000
+
+#define RE_JR_REG_LIODN_MASK	0x00000fff
+#define RE_CF_CDB_ALIGN		64
+/*
+ * the largest cf block is 19*sizeof(struct cmpnd_frame), which is 304 bytes.
+ * here 19 = 1(cdb)+2(dest)+16(src), align to 64bytes, that is 320 bytes.
+ * the largest cdb block: struct pq_cdb which is 180 bytes, adding to cf block
+ * 320+180=500, align to 64bytes, that is 512 bytes.
+ */
+#define RE_CF_DESC_SIZE		320
+#define RE_CF_CDB_SIZE		512
+
+struct re_ctrl {
+	/* General Configuration Registers */
+	__be32 global_config;	/* Global Configuration Register */
+	u8     rsvd1[4];
+	__be32 galois_field_config; /* Galois Field Configuration Register */
+	u8     rsvd2[4];
+	__be32 jq_wrr_config;   /* WRR Configuration register */
+	u8     rsvd3[4];
+	__be32 crc_config;	/* CRC Configuration register */
+	u8     rsvd4[228];
+	__be32 system_reset;	/* System Reset Register */
+	u8     rsvd5[252];
+	__be32 global_status;	/* Global Status Register */
+	u8     rsvd6[832];
+	__be32 re_liodn_base;	/* LIODN Base Register */
+	u8     rsvd7[1712];
+	__be32 re_version_id;	/* Version ID register of RE */
+	__be32 re_version_id_2; /* Version ID 2 register of RE */
+	u8     rsvd8[512];
+	__be32 host_config;	/* Host I/F Configuration Register */
+};
+
+struct jr_config_regs {
+	/* Registers for JR interface */
+	__be32 jr_config_0;	/* Job Queue Configuration 0 Register */
+	__be32 jr_config_1;	/* Job Queue Configuration 1 Register */
+	__be32 jr_interrupt_status; /* Job Queue Interrupt Status Register */
+	u8     rsvd1[4];
+	__be32 jr_command;	/* Job Queue Command Register */
+	u8     rsvd2[4];
+	__be32 jr_status;	/* Job Queue Status Register */
+	u8     rsvd3[228];
+
+	/* Input Ring */
+	__be32 inbring_base_h;	/* Inbound Ring Base Address Register - High */
+	__be32 inbring_base_l;	/* Inbound Ring Base Address Register - Low */
+	__be32 inbring_size;	/* Inbound Ring Size Register */
+	u8     rsvd4[4];
+	__be32 inbring_slot_avail; /* Inbound Ring Slot Available Register */
+	u8     rsvd5[4];
+	__be32 inbring_add_job;	/* Inbound Ring Add Job Register */
+	u8     rsvd6[4];
+	__be32 inbring_cnsmr_indx; /* Inbound Ring Consumer Index Register */
+	u8     rsvd7[220];
+
+	/* Output Ring */
+	__be32 oubring_base_h;	/* Outbound Ring Base Address Register - High */
+	__be32 oubring_base_l;	/* Outbound Ring Base Address Register - Low */
+	__be32 oubring_size;	/* Outbound Ring Size Register */
+	u8     rsvd8[4];
+	__be32 oubring_job_rmvd; /* Outbound Ring Job Removed Register */
+	u8     rsvd9[4];
+	__be32 oubring_slot_full; /* Outbound Ring Slot Full Register */
+	u8     rsvd10[4];
+	__be32 oubring_prdcr_indx; /* Outbound Ring Producer Index */
+};
+
+/*
+ * Command Descriptor Block (CDB) for unicast move command.
+ * In RAID Engine terms, memcpy is done through move command
+ */
+struct move_cdb {
+	u32 opcode:5;
+	u32 rsvd1:11;
+	u32 blk_size:2;
+	u32 cache_attrib:2;
+	u32 buffer_attrib:1;
+	u32 error_attrib:1;
+	u32 rsvd2:6;
+	u32 data_depend:1;
+	u32 dpi:1;
+	u32 rsvd3:2;
+} __packed;
+
+/* Data protection/integrity related fields */
+struct dpi_related {
+	u32 apps_mthd:2;
+	u32 ref_mthd:2;
+	u32 guard_mthd:2;
+	u32 dpi_attr:2;
+	u32 rsvd1:8;
+	u32 meta_tag:16;
+	u32 ref_tag:32;
+} __packed;
+
+/*
+ * CDB for GenQ command. In RAID Engine terminology, XOR is
+ * done through this command
+ */
+struct xor_cdb {
+	u32 opcode:5;
+	u32 rsvd1:11;
+	u32 blk_size:2;
+	u32 cache_attrib:2;
+	u32 buffer_attrib:1;
+	u32 error_attrib:1;
+	u32 nrcs:4;
+	u32 rsvd2:2;
+	u32 data_depend:1;
+	u32 dpi:1;
+	u32 rsvd3:2;
+	u8 gfm[16];
+	struct dpi_related dpi_dest_spec;
+	struct dpi_related dpi_src_spec[16];
+} __packed;
+
+/* CDB for no-op command */
+struct noop_cdb {
+	u32 opcode:5;
+	u32 rsvd1:23;
+	u32 dependency:1;
+	u32 rsvd2:3;
+} __packed;
+
+/*
+ * CDB for GenQQ command. In RAID Engine terminology, P/Q is
+ * done through this command
+ */
+struct pq_cdb {
+	u32 opcode:5;
+	u32 rsvd1:1;
+	u32 excl_enable:2;
+	u32 excl_q1:4;
+	u32 excl_q2:4;
+	u32 blk_size:2;
+	u32 cache_attrib:2;
+	u32 buffer_attrib:1;
+	u32 error_attrib:1;
+	u32 nrcs:4;
+	u32 rsvd2:2;
+	u32 data_depend:1;
+	u32 dpi:1;
+	u32 rsvd3:2;
+	u8 gfm_q1[16];
+	u8 gfm_q2[16];
+	struct dpi_related dpi_dest_spec[2];
+	struct dpi_related dpi_src_spec[16];
+} __packed;
+
+/* Compound frame */
+struct cmpnd_frame {
+	u64 rsvd1:24;
+	u64 address:40;
+	u32 extension:1;
+	u32 final:1;
+	u32 rsvd3:10;
+	u32 length:20;
+	u32 rsvd4:8;
+	u32 bpid:8;
+	u32 rsvd5:3;
+	u32 offset:13;
+} __packed;
+
+/* Frame descriptor */
+struct jr_hw_desc {
+	u64 debug:2;
+	u64 liodn_off:6;
+	u64 bpid:8;
+	u64 eliodn_off:4;
+	u64 rsvd1:4;
+	u64 address:40;
+	u64 format:3;
+	u64 rsvd2:29;
+	u64 status:32;
+} __packed;
+
+#define MAX_RE_JRS		4
+
+/* Raid Engine device private data */
+struct re_drv_private {
+	u8 total_jrs;
+	struct dma_device dma_dev;
+	struct re_ctrl *re_regs;
+	struct re_jr *re_jrs[MAX_RE_JRS];
+	struct dma_pool *desc_pool;
+	struct dma_pool *hw_desc_pool;
+};
+
+/* Per job ring data structure */
+struct re_jr {
+	dma_cookie_t completed_cookie;
+	spinlock_t desc_lock;
+	struct list_head ack_q;
+	struct device *dev;
+	struct re_drv_private *re_dev;
+	struct dma_chan chan;
+	struct jr_config_regs *jrregs;
+	int irq;
+	struct tasklet_struct irqtask;
+
+	/* hw descriptor ring for inbound queue*/
+	dma_addr_t inb_phys_addr;
+	struct jr_hw_desc *inb_ring_virt_addr;
+	u32 inb_count;
+	u32 pend_count;
+	spinlock_t inb_lock;
+
+	/* hw descriptor ring for outbound queue */
+	dma_addr_t oub_phys_addr;
+	struct jr_hw_desc *oub_ring_virt_addr;
+	u32 oub_count;
+	spinlock_t oub_lock;
+
+	struct fsl_re_dma_async_tx_desc *descs; /* sw descriptor ring */
+	void *cfs;				/* dma descriptor ring */
+	dma_addr_t phys;          /* phys addr for dma descriptor ring */
+
+	struct timer_list timer;
+};
+
+enum desc_state {
+	RE_DESC_EMPTY,
+	RE_DESC_ALLOC,
+};
+
+/* Async transaction descriptor */
+struct fsl_re_dma_async_tx_desc {
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head node;
+	struct list_head tx_list;
+	struct jr_hw_desc *hwdesc;
+	struct re_jr *jr;
+
+	void *cf_addr;
+	int dma_len;
+	u8 dest_cnt;
+	u8 src_cnt;
+
+	u16 cdb_opcode;
+	void *cdb_addr;
+	dma_addr_t cdb_paddr;
+	int cdb_len;
+
+	enum desc_state state;
+};
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 1/2] powerpc/dma/raidengine: add raidengine device
From: b29237 @ 2012-11-21  9:01 UTC (permalink / raw)
  To: dan.j.williams, vinod.koul, linuxppc-dev, linux-kernel
  Cc: Harninder Rai, Xuelin Shi, Naveen Burmi, iws

From: Xuelin Shi <b29237@freescale.com>

The RaidEngine is a new Freescale hardware that used for parity
computation offloading in RAID5/6.

This patch adds the device node in device tree and related binding
documentation.

Signed-off-by: Harninder Rai <harninder.rai@freescale.com>
Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
Signed-off-by: Xuelin Shi <b29237@freescale.com>
---
 .../devicetree/bindings/powerpc/fsl/raideng.txt    |   81 +++++++++++++++++++
 arch/powerpc/boot/dts/fsl/p5020si-post.dtsi        |    1 +
 arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi         |    6 ++
 arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi     |   85 ++++++++++++++++++++
 4 files changed, 173 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
 create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi

diff --git a/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt b/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
new file mode 100644
index 0000000..4ad29b9
--- /dev/null
+++ b/Documentation/devicetree/bindings/powerpc/fsl/raideng.txt
@@ -0,0 +1,81 @@
+* Freescale 85xx RAID Engine nodes
+
+RAID Engine nodes are defined to describe on-chip RAID accelerators.  Each RAID
+Engine should have a separate node.
+
+Supported chips:
+P5020, P5040
+
+Required properties:
+
+- compatible:	Should contain "fsl,raideng-v1.0" as the value
+		This identifies RAID Engine block. 1 in 1.0 represents
+		major number whereas 0 represents minor number. The
+		version matches the hardware IP version.
+- reg:		offset and length of the register set for the device
+- ranges:	standard ranges property specifying the translation
+		between child address space and parent address space
+
+Example:
+	/* P5020 */
+	raideng: raideng@320000 {
+		compatible = "fsl,raideng-v1.0";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg	= <0x320000 0x10000>;
+		ranges	= <0 0x320000 0x10000>;
+	};
+
+
+There must be a sub-node for each job queue present in RAID Engine
+This node must be a sub-node of the main RAID Engine node
+
+- compatible:	Should contain "fsl,raideng-v1.0-job-queue" as the value
+		This identifies the job queue interface
+- reg:		offset and length of the register set for job queue
+- ranges:	standard ranges property specifying the translation
+		between child address space and parent address space
+
+Example:
+	/* P5020 */
+	raideng_jq0@1000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		reg	   = <0x1000 0x1000>;
+		ranges	   = <0x0 0x1000 0x1000>;
+	};
+
+
+There must be a sub-node for each job ring present in RAID Engine
+This node must be a sub-node of job queue node
+
+- compatible:	Must contain "fsl,raideng-v1.0-job-ring" as the value
+		This identifies job ring. Should contain either
+		"fsl,raideng-v1.0-hp-ring" or "fsl,raideng-v1.0-lp-ring"
+		depending upon whether ring has high or low priority
+- reg:		offset and length of the register set for job ring
+- interrupts:	interrupt mapping for job ring IRQ
+
+Optional property:
+
+- fsl,liodn:	Specifies the LIODN to be used for Job Ring. This
+		property is normally set by firmware. Value
+		is of 12-bits which is the LIODN number for this JR.
+		This property is used by the IOMMU (PAMU) to distinquish
+		transactions from this JR and than be able to do address
+		translation & protection accordingly.
+
+Example:
+	/* P5020 */
+	raideng_jq0@1000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		reg	   = <0x1000 0x1000>;
+		ranges	   = <0x0 0x1000 0x1000>;
+
+		raideng_jr0: jr@0 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+			reg	   = <0x0 0x400>;
+			interrupts = <139 2 0 0>;
+			interrupt-parent = <&mpic>;
+			fsl,liodn = <0x41>;
+		};
+	};
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
index 64b6abe..5d7205b 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-post.dtsi
@@ -354,4 +354,5 @@
 /include/ "qoriq-sata2-0.dtsi"
 /include/ "qoriq-sata2-1.dtsi"
 /include/ "qoriq-sec4.2-0.dtsi"
+/include/ "qoriq-raid1.0-0.dtsi"
 };
diff --git a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
index 0a198b0..8df47fc 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
@@ -73,6 +73,12 @@
 		rtic_c = &rtic_c;
 		rtic_d = &rtic_d;
 		sec_mon = &sec_mon;
+
+		raideng = &raideng;
+		raideng_jr0 = &raideng_jr0;
+		raideng_jr1 = &raideng_jr1;
+		raideng_jr2 = &raideng_jr2;
+		raideng_jr3 = &raideng_jr3;
 	};
 
 	cpus {
diff --git a/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
new file mode 100644
index 0000000..8d2e8aa
--- /dev/null
+++ b/arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
@@ -0,0 +1,85 @@
+/*
+ * QorIQ RAID 1.0 device tree stub [ controller @ offset 0x320000 ]
+ *
+ * Copyright 2012 Freescale Semiconductor Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of Freescale Semiconductor nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ *
+ * ALTERNATIVELY, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") as published by the Free Software
+ * Foundation, either version 2 of that License or (at your option) any
+ * later version.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+raideng: raideng@320000 {
+	compatible = "fsl,raideng-v1.0";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	reg = <0x320000 0x10000>;
+	ranges = <0 0x320000 0x10000>;
+
+	raideng_jq0@1000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x1000 0x1000>;
+		ranges = <0x0 0x1000 0x1000>;
+
+		raideng_jr0: jr@0 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+			reg = <0x0 0x400>;
+			interrupts = <139 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		raideng_jr1: jr@400 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+			reg = <0x400 0x400>;
+			interrupts = <140 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+
+	raideng_jq1@2000 {
+		compatible = "fsl,raideng-v1.0-job-queue";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0x2000 0x1000>;
+		ranges = <0x0 0x2000 0x1000>;
+
+		raideng_jr2: jr@0 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-hp-ring";
+			reg = <0x0 0x400>;
+			interrupts = <141 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+
+		raideng_jr3: jr@400 {
+			compatible = "fsl,raideng-v1.0-job-ring", "fsl,raideng-v1.0-lp-ring";
+			reg = <0x400 0x400>;
+			interrupts = <142 2 0 0>;
+			interrupt-parent = <&mpic>;
+		};
+	};
+};
-- 
1.7.9.5

^ permalink raw reply related

* Re: [PATCH v3 06/12] memory-hotplug: unregister memory section on SPARSEMEM_VMEMMAP
From: Wen Congyang @ 2012-11-21  5:28 UTC (permalink / raw)
  To: Jaegeuk Hanse
  Cc: linux-s390, linux-ia64, Len Brown, linux-acpi, linux-sh, x86,
	linux-kernel, cmetcalf, Jianguo Wu, linux-mm, Yasuaki Ishimatsu,
	paulus, Minchan Kim, KOSAKI Motohiro, David Rientjes, sparclinux,
	Christoph Lameter, linuxppc-dev, Andrew Morton, Jiang Liu
In-Reply-To: <50AC608F.2020307@gmail.com>

At 11/21/2012 01:03 PM, Jaegeuk Hanse Wrote:
> On 11/21/2012 12:42 PM, Wen Congyang wrote:
>> At 11/21/2012 12:22 PM, Jaegeuk Hanse Wrote:
>>> On 11/21/2012 11:05 AM, Wen Congyang wrote:
>>>> At 11/20/2012 07:16 PM, Jaegeuk Hanse Wrote:
>>>>> On 11/01/2012 05:44 PM, Wen Congyang wrote:
>>>>>> From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>>>>>>
>>>>>> Currently __remove_section for SPARSEMEM_VMEMMAP does nothing. But
>>>>>> even if
>>>>>> we use SPARSEMEM_VMEMMAP, we can unregister the memory_section.
>>>>>>
>>>>>> So the patch add unregister_memory_section() into __remove_section().
>>>>> Hi Yasuaki,
>>>>>
>>>>> I have a question about these sparse vmemmap memory related
>>>>> patches. Hot
>>>>> add memory need allocated vmemmap pages, but this time is allocated by
>>>>> buddy system. How can gurantee virtual address is continuous to the
>>>>> address allocated before? If not continuous, page_to_pfn and
>>>>> pfn_to_page
>>>>> can't work correctly.
>>>> vmemmap has its virtual address range:
>>>> ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
>>>>
>>>> We allocate memory from buddy system to store struct page, and its
>>>> virtual
>>>> address isn't in this range. So we should update the page table:
>>>>
>>>> kmalloc_section_memmap()
>>>>       sparse_mem_map_populate()
>>>>           pfn_to_page() // get the virtual address in the vmemmap range
>>>>           vmemmap_populate() // we update page table here
>>>>
>>>> When we use vmemmap, page_to_pfn() always returns address in the
>>>> vmemmap
>>>> range, not the address that kmalloc() returns. So the virtual address
>>>> is continuous.
>>> Hi Congyang,
>>>
>>> Another question about memory hotplug. During hot remove memory, it will
>>> also call memblock_remove to remove related memblock.
>> IIRC, we don't touch memblock when hot-add/hot-remove memory. memblock is
>> only used for bootmem allocator. I think it isn't used after booting.
> 
> In IBM pseries servers.
> 
> pseries_remove_memory()
>     pseries_remove_memblock()
>         memblock_remove()

It seems that pseries servers don't use ACPI(ACPI is only supported for
ia64 and x86 now. arm will be supported in the furture).

I am not ppc expert, and I don't know why we touch memblock when hotadding
memory in ppc case. But IIRC, we don't need memblock after the machine has
booted up in x86 case. So there is no need to touch it when hotadd/hotremove
the memory in x86 case.

Thanks
Wen Congyang

> 
> Furthermore, memblock is set to record available memory ranges get from
> e820 map(you can check it in memblock_x86_fill()) in x86 case, after
> hot-remove memory, this range of memory can't be available, why not
> remove them as pseries servers' codes do.
> 
>>> memblock_remove()
>>>             __memblock_remove()memory-hotplug: unregister memory
>>> section on SPARSEMEM_VMEMMAP
>>>
>>>                     memblock_isolate_range()
>>>                     memblock_remove_region()
>>>
>>> But memblock_isolate_range() only record fully contained regions,
>>> regions which are partial overlapped just be splitted instead of record.
>>> So these partial overlapped regions can't be removed. Where I miss?
>> No, memblock_isolate_range() can deal with partial overlapped region.
>> =====================
>>         if (rbase < base) {
>>             /*
>>              * @rgn intersects from below.  Split and continue
>>              * to process the next region - the new top half.
>>              */
>>             rgn->base = base;
>>             rgn->size -= base - rbase;
>>             type->total_size -= base - rbase;
>>             memblock_insert_region(type, i, rbase, base - rbase,
>>                            memblock_get_region_node(rgn));
>>         } else if (rend > end) {
>>             /*
>>              * @rgn intersects from above.  Split and redo the
>>              * current region - the new bottom half.
>>              */
>>             rgn->base = end;
>>             rgn->size -= end - rbase;
>>             type->total_size -= end - rbase;
>>             memblock_insert_region(type, i--, rbase, end - rbase,
>>                            memblock_get_region_node(rgn));
>> =====================
>>
>> If the region is partial overlapped region, we will split the old
>> region into
>> two regions. After doing this, it is full contained region now.
> 
> You are right, I misunderstand the codes.
> 
>>
>> Thanks
>> Wen Congyang
>>
>>> Regards,
>>> Jaegeuk
>>>
>>>> Thanks
>>>> Wen Congyang
>>>>> Regards,
>>>>> Jaegeuk
>>>>>
>>>>>> CC: David Rientjes <rientjes@google.com>
>>>>>> CC: Jiang Liu <liuj97@gmail.com>
>>>>>> CC: Len Brown <len.brown@intel.com>
>>>>>> CC: Christoph Lameter <cl@linux.com>
>>>>>> Cc: Minchan Kim <minchan.kim@gmail.com>
>>>>>> CC: Andrew Morton <akpm@linux-foundation.org>
>>>>>> CC: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
>>>>>> CC: Wen Congyang <wency@cn.fujitsu.com>
>>>>>> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>>>>>> ---
>>>>>>     mm/memory_hotplug.c | 13 ++++++++-----
>>>>>>     1 file changed, 8 insertions(+), 5 deletions(-)
>>>>>>
>>>>>> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
>>>>>> index ca07433..66a79a7 100644
>>>>>> --- a/mm/memory_hotplug.c
>>>>>> +++ b/mm/memory_hotplug.c
>>>>>> @@ -286,11 +286,14 @@ static int __meminit __add_section(int nid,
>>>>>> struct zone *zone,
>>>>>>     #ifdef CONFIG_SPARSEMEM_VMEMMAP
>>>>>>     static int __remove_section(struct zone *zone, struct mem_section
>>>>>> *ms)
>>>>>>     {
>>>>>> -    /*
>>>>>> -     * XXX: Freeing memmap with vmemmap is not implement yet.
>>>>>> -     *      This should be removed later.
>>>>>> -     */
>>>>>> -    return -EBUSY;
>>>>>> +    int ret = -EINVAL;
>>>>>> +
>>>>>> +    if (!valid_section(ms))
>>>>>> +        return ret;
>>>>>> +
>>>>>> +    ret = unregister_memory_section(ms);
>>>>>> +
>>>>>> +    return ret;
>>>>>>     }
>>>>>>     #else
>>>>>>     static int __remove_section(struct zone *zone, struct mem_section
>>>>>> *ms)
>>>
> 
> 

^ permalink raw reply

* Re: [PATCH v3 06/12] memory-hotplug: unregister memory section on SPARSEMEM_VMEMMAP
From: Wen Congyang @ 2012-11-21  5:12 UTC (permalink / raw)
  To: Jaegeuk Hanse
  Cc: linux-s390, linux-ia64, Len Brown, linux-acpi, linux-sh, x86,
	linux-kernel, cmetcalf, Jianguo Wu, linux-mm, Yasuaki Ishimatsu,
	paulus, Minchan Kim, KOSAKI Motohiro, David Rientjes, sparclinux,
	Christoph Lameter, linuxppc-dev, Andrew Morton, Jiang Liu
In-Reply-To: <50AC608F.2020307@gmail.com>

At 11/21/2012 01:03 PM, Jaegeuk Hanse Wrote:
> On 11/21/2012 12:42 PM, Wen Congyang wrote:
>> At 11/21/2012 12:22 PM, Jaegeuk Hanse Wrote:
>>> On 11/21/2012 11:05 AM, Wen Congyang wrote:
>>>> At 11/20/2012 07:16 PM, Jaegeuk Hanse Wrote:
>>>>> On 11/01/2012 05:44 PM, Wen Congyang wrote:
>>>>>> From: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>>>>>>
>>>>>> Currently __remove_section for SPARSEMEM_VMEMMAP does nothing. But
>>>>>> even if
>>>>>> we use SPARSEMEM_VMEMMAP, we can unregister the memory_section.
>>>>>>
>>>>>> So the patch add unregister_memory_section() into __remove_section().
>>>>> Hi Yasuaki,
>>>>>
>>>>> I have a question about these sparse vmemmap memory related
>>>>> patches. Hot
>>>>> add memory need allocated vmemmap pages, but this time is allocated by
>>>>> buddy system. How can gurantee virtual address is continuous to the
>>>>> address allocated before? If not continuous, page_to_pfn and
>>>>> pfn_to_page
>>>>> can't work correctly.
>>>> vmemmap has its virtual address range:
>>>> ffffea0000000000 - ffffeaffffffffff (=40 bits) virtual memory map (1TB)
>>>>
>>>> We allocate memory from buddy system to store struct page, and its
>>>> virtual
>>>> address isn't in this range. So we should update the page table:
>>>>
>>>> kmalloc_section_memmap()
>>>>       sparse_mem_map_populate()
>>>>           pfn_to_page() // get the virtual address in the vmemmap range
>>>>           vmemmap_populate() // we update page table here
>>>>
>>>> When we use vmemmap, page_to_pfn() always returns address in the
>>>> vmemmap
>>>> range, not the address that kmalloc() returns. So the virtual address
>>>> is continuous.
>>> Hi Congyang,
>>>
>>> Another question about memory hotplug. During hot remove memory, it will
>>> also call memblock_remove to remove related memblock.
>> IIRC, we don't touch memblock when hot-add/hot-remove memory. memblock is
>> only used for bootmem allocator. I think it isn't used after booting.
> 
> In IBM pseries servers.
> 
> pseries_remove_memory()
>     pseries_remove_memblock()
>         memblock_remove()
> 
> Furthermore, memblock is set to record available memory ranges get from
> e820 map(you can check it in memblock_x86_fill()) in x86 case, after
> hot-remove memory, this range of memory can't be available, why not
> remove them as pseries servers' codes do.

Oh, it is powerpc, and I don't read this code. I will check it now.

Thanks for pointing it out.

Wen Congyang

> 
>>> memblock_remove()
>>>             __memblock_remove()memory-hotplug: unregister memory
>>> section on SPARSEMEM_VMEMMAP
>>>
>>>                     memblock_isolate_range()
>>>                     memblock_remove_region()
>>>
>>> But memblock_isolate_range() only record fully contained regions,
>>> regions which are partial overlapped just be splitted instead of record.
>>> So these partial overlapped regions can't be removed. Where I miss?
>> No, memblock_isolate_range() can deal with partial overlapped region.
>> =====================
>>         if (rbase < base) {
>>             /*
>>              * @rgn intersects from below.  Split and continue
>>              * to process the next region - the new top half.
>>              */
>>             rgn->base = base;
>>             rgn->size -= base - rbase;
>>             type->total_size -= base - rbase;
>>             memblock_insert_region(type, i, rbase, base - rbase,
>>                            memblock_get_region_node(rgn));
>>         } else if (rend > end) {
>>             /*
>>              * @rgn intersects from above.  Split and redo the
>>              * current region - the new bottom half.
>>              */
>>             rgn->base = end;
>>             rgn->size -= end - rbase;
>>             type->total_size -= end - rbase;
>>             memblock_insert_region(type, i--, rbase, end - rbase,
>>                            memblock_get_region_node(rgn));
>> =====================
>>
>> If the region is partial overlapped region, we will split the old
>> region into
>> two regions. After doing this, it is full contained region now.
> 
> You are right, I misunderstand the codes.
> 
>>
>> Thanks
>> Wen Congyang
>>
>>> Regards,
>>> Jaegeuk
>>>
>>>> Thanks
>>>> Wen Congyang
>>>>> Regards,
>>>>> Jaegeuk
>>>>>
>>>>>> CC: David Rientjes <rientjes@google.com>
>>>>>> CC: Jiang Liu <liuj97@gmail.com>
>>>>>> CC: Len Brown <len.brown@intel.com>
>>>>>> CC: Christoph Lameter <cl@linux.com>
>>>>>> Cc: Minchan Kim <minchan.kim@gmail.com>
>>>>>> CC: Andrew Morton <akpm@linux-foundation.org>
>>>>>> CC: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
>>>>>> CC: Wen Congyang <wency@cn.fujitsu.com>
>>>>>> Signed-off-by: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com>
>>>>>> ---
>>>>>>     mm/memory_hotplug.c | 13 ++++++++-----
>>>>>>     1 file changed, 8 insertions(+), 5 deletions(-)
>>>>>>
>>>>>> diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
>>>>>> index ca07433..66a79a7 100644
>>>>>> --- a/mm/memory_hotplug.c
>>>>>> +++ b/mm/memory_hotplug.c
>>>>>> @@ -286,11 +286,14 @@ static int __meminit __add_section(int nid,
>>>>>> struct zone *zone,
>>>>>>     #ifdef CONFIG_SPARSEMEM_VMEMMAP
>>>>>>     static int __remove_section(struct zone *zone, struct mem_section
>>>>>> *ms)
>>>>>>     {
>>>>>> -    /*
>>>>>> -     * XXX: Freeing memmap with vmemmap is not implement yet.
>>>>>> -     *      This should be removed later.
>>>>>> -     */
>>>>>> -    return -EBUSY;
>>>>>> +    int ret = -EINVAL;
>>>>>> +
>>>>>> +    if (!valid_section(ms))
>>>>>> +        return ret;
>>>>>> +
>>>>>> +    ret = unregister_memory_section(ms);
>>>>>> +
>>>>>> +    return ret;
>>>>>>     }
>>>>>>     #else
>>>>>>     static int __remove_section(struct zone *zone, struct mem_section
>>>>>> *ms)
>>>
> 
> 

^ permalink raw reply


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