LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v3 2/2] powerpc: Uprobes port to powerpc
From: Ananth N Mavinakayanahalli @ 2012-08-21 11:24 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Srikar Dronamraju, peterz, lkml, Paul Mackerras, Anton Blanchard,
	Ingo Molnar, linuxppc-dev
In-Reply-To: <20120817150031.GA5029@redhat.com>

On Fri, Aug 17, 2012 at 05:00:31PM +0200, Oleg Nesterov wrote:
> On 08/17, Ananth N Mavinakayanahalli wrote:
> >
> > On Thu, Aug 16, 2012 at 05:21:12PM +0200, Oleg Nesterov wrote:
> >
> > > Hmm, I am not sure. is_swbp_insn(insn), as it is used in the arch agnostic
> > > code, should only return true if insn == UPROBE_SWBP_INSN (just in case,
> > > this logic needs more fixes but this is offtopic).
> >
> > I think it does...
> >
> > > If powerpc has another insn(s) which can trigger powerpc's do_int3()
> > > counterpart, they should be rejected by arch_uprobe_analyze_insn().
> > > I think.
> >
> > The insn that gets passed to arch_uprobe_analyze_insn() is copy_insn()'s
> > version, which is the file copy of the instruction.
> 
> Yes, exactly. And we are going to single-step this saved uprobe->arch.insn,
> even if gdb/whatever replaces the original insn later or already replaced.
> 
> So arch_uprobe_analyze_insn() should reject the "unsafe" instructions which
> we can't step over safely.

Agreed.

> > We should also take
> > care of the in-memory copy, in case gdb had inserted a breakpoint at the
> > same location, right?
> 
> gdb (or even the application itself) and uprobes can obviously confuse
> each other, in many ways, and we can do nothing at least currently.
> Just we should ensure that the kernel can't crash/hang/etc.

Absolutely. The proper fix for this at least from a breakpoint insertion
perspective is to educate gdb (possibly ptrace itself) to fail on a
breakpoint insertion request on an already existing one.

> > Updating is_swbp_insn() per-arch where needed will
> > take care of both the cases, 'cos it gets called before
> > arch_analyze_uprobe_insn() too.
> 
> For example. set_swbp()->is_swbp_insn() == T means that (for example)
> uprobe_register() and uprobe_mmap() raced with each other and there is
> no need for set_swbp().

This is true for Intel like architectures that have *one* swbp
instruction. On Powerpc, gdb for instance, can insert a trap variant at
the address. Therefore, is_swbp_insn() by definition should return true
for all trap variants.

> However, find_active_uprobe()->is_swbp_at_addr()->is_swbp_insn() is
> different, "true" confirms that this insn has triggered do_int3() and
> thus we need send_sig(SIGTRAP) (just in case, this is not strictly
> correct too but offtopic again).
> 
> We definitely need more changes/fixes/improvements in this area. And
> perhaps powerpc requires more changes in the arch-neutral code, I dunno.

For powerpc, just having is_swbp_insn() (already a weak function) handle
the trap variants, should suffice.

> In particular, I think is_swbp_insn() should have a single caller,
> is_swbp_at_addr(), and this caller should always play with current->mm.
> And many, many other changes in the long term.
> 
> So far I think that, if powerpc really needs to change is_swbp_insn(),
> it would be better to make another patch and discuss this change.
> But of course I can't judge.

OK. I will separate out the is_swbp_insn() change into a separate patch.

Ananth

^ permalink raw reply

* [PATCH v2 0/2][powerpc] Export memory_limit via device tree
From: Suzuki K. Poulose @ 2012-08-21 11:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mahesh, linux-kernel

The following series exports the linux memory_limit set by
the mem= parameter via device-tree, so that kexec-tools
can limit the crash regions to the actual memory used by
the kernel.

Change since V1:

 * Added a patch to change the type of memory_limit to a
   fixed size(unsigned long long) from 'phys_addr_t' (which
   is 32bit on some ppc32 and 64 bit on ppc64 and some ppc32)

 * Rebased the patch to use recently fixed prom_update_property()
   which would add the property if it didn't exist.

---

Suzuki K. Poulose (2):
      [powerpc] Change memory_limit from phys_addr_t to unsigned long long
      [powerpc] Export memory limit via device tree


 arch/powerpc/include/asm/setup.h    |    2 +-
 arch/powerpc/kernel/fadump.c        |    3 +--
 arch/powerpc/kernel/machine_kexec.c |   14 +++++++++++++-
 arch/powerpc/kernel/prom.c          |    2 +-
 arch/powerpc/mm/mem.c               |    2 +-
 5 files changed, 17 insertions(+), 6 deletions(-)

-- 
Suzuki

^ permalink raw reply

* [PATCH v2 1/2] [powerpc] Change memory_limit from phys_addr_t to unsigned long long
From: Suzuki K. Poulose @ 2012-08-21 11:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mahesh, linux-kernel
In-Reply-To: <20120821113815.29282.4000.stgit@suzukikp.in.ibm.com>

There are some device-tree nodes, whose values are of type phys_addr_t.
The phys_addr_t is variable sized based on the CONFIG_PHSY_T_64BIT.

Change these to a fixed unsigned long long for consistency.

This patch does the change only for memory_limit.

The following is a list of such variables which need the change:

 1) kernel_end, crashk_size - in arch/powerpc/kernel/machine_kexec.c

 2) (struct resource *)crashk_res.start - We could export a local static
    variable from machine_kexec.c.

Changing the above values might break the kexec-tools. So, I will
fix kexec-tools first to handle the different sized values and then change
 the above.

Suggested-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
---

 arch/powerpc/include/asm/setup.h    |    2 +-
 arch/powerpc/kernel/fadump.c        |    3 +--
 arch/powerpc/kernel/machine_kexec.c |    2 +-
 arch/powerpc/kernel/prom.c          |    2 +-
 arch/powerpc/mm/mem.c               |    2 +-
 5 files changed, 5 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/setup.h b/arch/powerpc/include/asm/setup.h
index d084ce1..8b9a306 100644
--- a/arch/powerpc/include/asm/setup.h
+++ b/arch/powerpc/include/asm/setup.h
@@ -9,7 +9,7 @@ extern void ppc_printk_progress(char *s, unsigned short hex);
 extern unsigned int rtas_data;
 extern int mem_init_done;	/* set on boot once kmalloc can be called */
 extern int init_bootmem_done;	/* set once bootmem is available */
-extern phys_addr_t memory_limit;
+extern unsigned long long memory_limit;
 extern unsigned long klimit;
 extern void *zalloc_maybe_bootmem(size_t size, gfp_t mask);
 
diff --git a/arch/powerpc/kernel/fadump.c b/arch/powerpc/kernel/fadump.c
index 18bdf74..06c8202 100644
--- a/arch/powerpc/kernel/fadump.c
+++ b/arch/powerpc/kernel/fadump.c
@@ -289,8 +289,7 @@ int __init fadump_reserve_mem(void)
 		else
 			memory_limit = memblock_end_of_DRAM();
 		printk(KERN_INFO "Adjusted memory_limit for firmware-assisted"
-				" dump, now %#016llx\n",
-				(unsigned long long)memory_limit);
+				" dump, now %#016llx\n", memory_limit);
 	}
 	if (memory_limit)
 		memory_boundary = memory_limit;
diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index 5df7777..4074eff 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -165,7 +165,7 @@ void __init reserve_crashkernel(void)
 	if (memory_limit && memory_limit <= crashk_res.end) {
 		memory_limit = crashk_res.end + 1;
 		printk("Adjusted memory limit for crashkernel, now 0x%llx\n",
-		       (unsigned long long)memory_limit);
+		       memory_limit);
 	}
 
 	printk(KERN_INFO "Reserving %ldMB of memory at %ldMB "
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index f191bf0..c82c77d 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -78,7 +78,7 @@ static int __init early_parse_mem(char *p)
 		return 1;
 
 	memory_limit = PAGE_ALIGN(memparse(p, &p));
-	DBG("memory limit = 0x%llx\n", (unsigned long long)memory_limit);
+	DBG("memory limit = 0x%llx\n", memory_limit);
 
 	return 0;
 }
diff --git a/arch/powerpc/mm/mem.c b/arch/powerpc/mm/mem.c
index baaafde..0a8f353 100644
--- a/arch/powerpc/mm/mem.c
+++ b/arch/powerpc/mm/mem.c
@@ -62,7 +62,7 @@
 
 int init_bootmem_done;
 int mem_init_done;
-phys_addr_t memory_limit;
+unsigned long long memory_limit;
 
 #ifdef CONFIG_HIGHMEM
 pte_t *kmap_pte;

^ permalink raw reply related

* [PATCH v2 2/2] [powerpc] Export memory limit via device tree
From: Suzuki K. Poulose @ 2012-08-21 11:42 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: mahesh, linux-kernel
In-Reply-To: <20120821113815.29282.4000.stgit@suzukikp.in.ibm.com>

The powerpc kernel doesn't export the memory limit enforced by 'mem='
kernel parameter. This is required for building the ELF header in
kexec-tools to limit the vmcore to capture only the used memory. On
powerpc the kexec-tools depends on the device-tree for memory related
information, unlike /proc/iomem on the x86.

Without this information, the kexec-tools assumes the entire System
RAM and vmcore creates an unnecessarily larger dump.

This patch exports the memory limit, if present, via
chosen/linux,memory-limit
property, so that the vmcore can be limited to the memory limit.

The prom_init seems to export this value in the same node. But doesn't
really
appear there.  Also the memory_limit gets adjusted with the processing of
crashkernel= parameter. This patch makes sure we get the actual limit.

The kexec-tools will use the value to limit the 'end' of the memory
regions.

Tested this patch on ppc64 and ppc32(ppc440) with a kexec-tools
patch by Mahesh.

Signed-off-by: Suzuki K. Poulose <suzuki@in.ibm.com>
Tested-by: Mahesh J. Salgaonkar <mahesh@linux.vnet.ibm.com>
---

 arch/powerpc/kernel/machine_kexec.c |   12 ++++++++++++
 1 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/kernel/machine_kexec.c b/arch/powerpc/kernel/machine_kexec.c
index 4074eff..fa9f6c7 100644
--- a/arch/powerpc/kernel/machine_kexec.c
+++ b/arch/powerpc/kernel/machine_kexec.c
@@ -204,6 +204,12 @@ static struct property crashk_size_prop = {
 	.value = &crashk_size,
 };
 
+static struct property memory_limit_prop = {
+	.name = "linux,memory-limit",
+	.length = sizeof(unsigned long long),
+	.value = &memory_limit,
+};
+
 static void __init export_crashk_values(struct device_node *node)
 {
 	struct property *prop;
@@ -223,6 +229,12 @@ static void __init export_crashk_values(struct device_node *node)
 		crashk_size = resource_size(&crashk_res);
 		prom_add_property(node, &crashk_size_prop);
 	}
+
+	/*
+	 * memory_limit is required by the kexec-tools to limit the
+	 * crash regions to the actual memory used.
+	 */
+	prom_update_property(node, &memory_limit_prop);
 }
 
 static int __init kexec_setup(void)

^ permalink raw reply related

* Re: GE IMP3a
From: Martyn Welch @ 2012-08-21 12:39 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev@lists.ozlabs.org list
In-Reply-To: <68C39493-C518-4898-954B-CA2E1DCF5DAD@kernel.crashing.org>

On 15/08/12 22:32, Kumar Gala wrote:
> Do you know why ge_imp3a.c has 0x9000 as the 'primary' PCIe bus on the board?
> 

Hi Kumar,

Sorry, missed your mail.

At a quick guess it's because that's the interface that is used for the
on-board PCI devices.

Martyn


-- 
Martyn Welch (Lead Software Engineer)  | Registered in England and Wales
GE Intelligent Platforms               | (3828642) at 100 Barbirolli Square
T +44(0)1327322748                     | Manchester, M2 3AB
E martyn.welch@ge.com                  | VAT:GB 927559189

^ permalink raw reply

* Re: [PATCH v3 2/2] powerpc: Uprobes port to powerpc
From: Oleg Nesterov @ 2012-08-21 13:09 UTC (permalink / raw)
  To: Ananth N Mavinakayanahalli
  Cc: Srikar Dronamraju, peterz, lkml, Paul Mackerras, Anton Blanchard,
	Ingo Molnar, linuxppc-dev
In-Reply-To: <20120821112433.GB3519@in.ibm.com>

On 08/21, Ananth N Mavinakayanahalli wrote:
>
> On Fri, Aug 17, 2012 at 05:00:31PM +0200, Oleg Nesterov wrote:
>
> > > We should also take
> > > care of the in-memory copy, in case gdb had inserted a breakpoint at the
> > > same location, right?
> >
> > gdb (or even the application itself) and uprobes can obviously confuse
> > each other, in many ways, and we can do nothing at least currently.
> > Just we should ensure that the kernel can't crash/hang/etc.
>
> Absolutely. The proper fix for this at least from a breakpoint insertion
> perspective is to educate gdb (possibly ptrace itself) to fail on a
> breakpoint insertion request on an already existing one.

Oh, I don't think this is possible. And there are other problems like
this. Uprobe can confuse gdb too, in many ways. For example,
uprobe_register() can wrongly _remove_ int3 installed by gdb.

The proper fix, I think, is to rework the whole idea about uprobe bps,
but this is really "in the long term". install_breakpoint() should
only unmap the page and mark its pte as "owned by kernel, FOLL_WRITE
should not work". Something like migration or PROT_NONE. The task
itself should install bp during the page fault. And we need the
"backing store" for the pages with uprobes. Yes, this all is very
vague and I can be wrong.

Anyway, this is relatively minor, we have more serious problems.

> > > Updating is_swbp_insn() per-arch where needed will
> > > take care of both the cases, 'cos it gets called before
> > > arch_analyze_uprobe_insn() too.
> >
> > For example. set_swbp()->is_swbp_insn() == T means that (for example)
> > uprobe_register() and uprobe_mmap() raced with each other and there is
> > no need for set_swbp().
>
> This is true for Intel like architectures that have *one* swbp
> instruction. On Powerpc, gdb for instance, can insert a trap variant at
> the address. Therefore, is_swbp_insn() by definition should return true
> for all trap variants.

Not in this case, I think.

OK, I was going to do this later, but this discussion makes me think
I should try to send the patch sooner.

set_swbp()->is_swbp_at_addr() is simply unneeded and in fact should
be considered as unnecessary pessimization.

set_orig_insn()->is_swbp_at_addr() makes more sense, but it can't fix
all races with userpace. Still it should die.

> OK. I will separate out the is_swbp_insn() change into a separate patch.

Great thanks. And if we remove is_swbp_insn() from set_swbp() and
set_orig_insn() then the semantics of is_swbp_insn() will much more
clear, and in this case I powerpc probably really needs to change it.

Oleg.

^ permalink raw reply

* Re: GE IMP3a
From: Kumar Gala @ 2012-08-21 13:58 UTC (permalink / raw)
  To: Martyn Welch; +Cc: linuxppc-dev@lists.ozlabs.org list
In-Reply-To: <50338169.8040102@ge.com>


On Aug 21, 2012, at 7:39 AM, Martyn Welch wrote:

> On 15/08/12 22:32, Kumar Gala wrote:
>> Do you know why ge_imp3a.c has 0x9000 as the 'primary' PCIe bus on =
the board?
>>=20
>=20
> Hi Kumar,
>=20
> Sorry, missed your mail.

np.

> At a quick guess it's because that's the interface that is used for =
the
> on-board PCI devices.

What PCI devices are on-board?

Does the board have any PCIe-ISA bridges?

[ if you can generate an lspci dump, that might answer some of these =
questions ]

thanks

- k=

^ permalink raw reply

* Re: [2/3][PATCH][v2] TDM Framework
From: Mark Brown @ 2012-08-21 14:13 UTC (permalink / raw)
  To: Greg KH
  Cc: devel@driverdev.osuosl.org, linux-kernel@vger.kernel.org,
	Francois Romieu, linuxppc-dev@lists.ozlabs.org,
	Singh Sandeep-B37400, linux-arm-kernel@lists.infradead.org
In-Reply-To: <20120801123738.GA28291@kroah.com>

On Wed, Aug 01, 2012 at 05:37:38AM -0700, Greg KH wrote:
> On Wed, Aug 01, 2012 at 12:13:19PM +0000, Singh Sandeep-B37400 wrote:

> > But running a complete voice stack itself is beyond the scope of Freescale.
> > So vendors integrate their solutions with FSL solution.

> And sorry, I was thinking you had kernel drivers that attached to this
> framework, not userspace programs.  Actually, what is the user/kernel
> interface for this framework, I seem to have missed that entirely.  You
> will have to document that quite well, and run it by the linux-api
> mailing list.

This does also sound like we ought to be playing nicer with ALSA rather
than just providing a binary only pipe...

^ permalink raw reply

* [PATCH] rapidio: apply RX/TX enable to active switch ports only
From: Alexandre Bounine @ 2012-08-21 14:23 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel, linuxppc-dev; +Cc: Alexandre Bounine
In-Reply-To: <1345559035-25879-1-git-send-email-alexandre.bounine@idt.com>

Modify RIO enumeration to apply RX/TX enable operations only to active
switch ports. This will leave inactive ports in condition consistent with
their state.

This patch is applicable to kernel versions starting from v2.6.35.

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
---
 drivers/rapidio/rio-scan.c |    9 +++++----
 1 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/rapidio/rio-scan.c b/drivers/rapidio/rio-scan.c
index 2bebd79..02e686b 100644
--- a/drivers/rapidio/rio-scan.c
+++ b/drivers/rapidio/rio-scan.c
@@ -839,12 +839,10 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
 		for (port_num = 0;
 		     port_num < RIO_GET_TOTAL_PORTS(rdev->swpinfo);
 		     port_num++) {
-			/*Enable Input Output Port (transmitter reviever)*/
-			rio_enable_rx_tx_port(port, 0,
+			if (sw_inport == port_num) {
+				rio_enable_rx_tx_port(port, 0,
 					      RIO_ANY_DESTID(port->sys_size),
 					      hopcount, port_num);
-
-			if (sw_inport == port_num) {
 				rdev->rswitch->port_ok |= (1 << port_num);
 				continue;
 			}
@@ -857,6 +855,9 @@ static int __devinit rio_enum_peer(struct rio_net *net, struct rio_mport *port,
 				pr_debug(
 				    "RIO: scanning device on port %d\n",
 				    port_num);
+				rio_enable_rx_tx_port(port, 0,
+					      RIO_ANY_DESTID(port->sys_size),
+					      hopcount, port_num);
 				rdev->rswitch->port_ok |= (1 << port_num);
 				rio_route_add_entry(rdev, RIO_GLOBAL_TABLE,
 						RIO_ANY_DESTID(port->sys_size),
-- 
1.7.8.4

^ permalink raw reply related

* [PATCH] rapidio/tsi721: modify mport name assignment
From: Alexandre Bounine @ 2012-08-21 14:23 UTC (permalink / raw)
  To: Andrew Morton, linux-kernel, linuxppc-dev; +Cc: Alexandre Bounine

Modify mport device name assignment to provide clear reference to devices
in systems with multiple Tsi721 bridges.

This patch is applicable to kernel versions starting from v3.2.

Signed-off-by: Alexandre Bounine <alexandre.bounine@idt.com>
Cc: Matt Porter <mporter@kernel.crashing.org>
---
 drivers/rapidio/devices/tsi721.c |    3 ++-
 include/linux/rio.h              |    3 ++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/drivers/rapidio/devices/tsi721.c b/drivers/rapidio/devices/tsi721.c
index 5d44252..8533f36 100644
--- a/drivers/rapidio/devices/tsi721.c
+++ b/drivers/rapidio/devices/tsi721.c
@@ -2165,7 +2165,8 @@ static int __devinit tsi721_setup_mport(struct tsi721_device *priv)
 	rio_init_dbell_res(&mport->riores[RIO_DOORBELL_RESOURCE], 0, 0xffff);
 	rio_init_mbox_res(&mport->riores[RIO_INB_MBOX_RESOURCE], 0, 3);
 	rio_init_mbox_res(&mport->riores[RIO_OUTB_MBOX_RESOURCE], 0, 3);
-	strcpy(mport->name, "Tsi721 mport");
+	snprintf(mport->name, RIO_MAX_MPORT_NAME, "%s(%s)",
+		 dev_driver_string(&pdev->dev), dev_name(&pdev->dev));
 
 	/* Hook up interrupt handler */
 
diff --git a/include/linux/rio.h b/include/linux/rio.h
index a90ebad..1a7b6c7 100644
--- a/include/linux/rio.h
+++ b/include/linux/rio.h
@@ -30,6 +30,7 @@
 #define RIO_MAX_MPORTS		8
 #define RIO_MAX_MPORT_RESOURCES	16
 #define RIO_MAX_DEV_RESOURCES	16
+#define RIO_MAX_MPORT_NAME	40
 
 #define RIO_GLOBAL_TABLE	0xff	/* Indicates access of a switch's
 					   global routing table if it
@@ -255,7 +256,7 @@ struct rio_mport {
 				 */
 	enum rio_phy_type phy_type;	/* RapidIO phy type */
 	u32 phys_efptr;
-	unsigned char name[40];
+	unsigned char name[RIO_MAX_MPORT_NAME];
 	void *priv;		/* Master port private data */
 #ifdef CONFIG_RAPIDIO_DMA_ENGINE
 	struct dma_device	dma;
-- 
1.7.8.4

^ permalink raw reply related

* Re: [PATCH 2/2] powerpc/usb: fix bug of CPU hang when missing USB PHY clock
From: Alan Stern @ 2012-08-21 14:33 UTC (permalink / raw)
  To: Kumar Gala
  Cc: gregkh, linux-usb, linuxppc-dev@lists.ozlabs.org list,
	Liu Shengzhou-B36685
In-Reply-To: <9F42EE26-7362-4B6E-8BD6-92EE02A07A1D@kernel.crashing.org>

On Mon, 20 Aug 2012, Kumar Gala wrote:

> >> Subject: Re: [PATCH 2/2] powerpc/usb: fix bug of CPU hang when missing USB PHY
> >> clock
> >> 
> >> 
> >> On Aug 10, 2012, at 5:48 AM, Shengzhou Liu wrote:
> >> 
> >>> when missing USB PHY clock, kernel booting up will hang during USB
> >>> initialization. We should check USBGP[PHY_CLK_VALID] bit to avoid CPU
> >>> hanging in this case.
> >>> 
> >>> Signed-off-by: Shengzhou Liu <Shengzhou.Liu@freescale.com>
> >>> ---
> >>> drivers/usb/host/ehci-fsl.c |   63 ++++++++++++++++++++++++++++++-----------
> >> -
> >>> drivers/usb/host/ehci-fsl.h |    1 +
> >>> 2 files changed, 46 insertions(+), 18 deletions(-)
> >> 
> >> I assume this should be considered a bug fix and be looked at for inclusion in
> >> v3.6?
> >> 
> >> - k
> > [Shengzhou] Yes. 
> 
> Greg,
> 
> ping?

Greg is away on vacation for the rest of this week.

Alan Stern

^ permalink raw reply

* Re: [PATCH V8] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Scott Wood @ 2012-08-21 17:16 UTC (permalink / raw)
  To: Li Yang-R58472
  Cc: Wood Scott-B07421, Bradley Hughes, linuxppc-dev@lists.ozlabs.org,
	Jia Hongtao-B38951
In-Reply-To: <94F013E7935FF44C83EBE7784D62AD3F093BD870@039-SN2MPN1-023.039d.mgd.msft.net>

On 08/21/2012 01:49 AM, Li Yang-R58472 wrote:
> If there is i8259 node in the device tree, it should be suggesting
> that there is a PCI to ISA bridge but not explicitly described in the
> device tree.  Then we need to fix the device tree to add the ISA
> nodes.

No, we need to work with existing device trees.  Just because they're
hosted in the kernel tree doesn't mean they can be treated as an
internal kernel implementation detail.  They are stable API with
external entities such as bootloaders and hypervisors, get forked for
custom boards, etc.

Boards with this problem should set fsl_pci_primary in platform code
based on whatever criteria is relevant.

-Scott

^ permalink raw reply

* Re: [PATCH V8] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Li Yang-R58472 @ 2012-08-21 18:09 UTC (permalink / raw)
  To: Wood Scott-B07421
  Cc: Wood Scott-B07421, Bradley Hughes, linuxppc-dev@lists.ozlabs.org,
	Jia Hongtao-B38951
In-Reply-To: <5033C250.2000904@freescale.com>



On Aug 22, 2012, at 1:16, "Wood Scott-B07421" <B07421@freescale.com> wrote:

> On 08/21/2012 01:49 AM, Li Yang-R58472 wrote:
>> If there is i8259 node in the device tree, it should be suggesting
>> that there is a PCI to ISA bridge but not explicitly described in the
>> device tree.  Then we need to fix the device tree to add the ISA
>> nodes.
>=20
> No, we need to work with existing device trees.  Just because they're
> hosted in the kernel tree doesn't mean they can be treated as an
> internal kernel implementation detail.  They are stable API with
> external entities such as bootloaders and hypervisors, get forked for
> custom boards, etc.

You are right that device tree binding is a stable API but not a poorly wri=
tten dts instance.  We are not changing any binding definition.  It is just=
 adding the somehow missed node that should be there in some poorly written=
 dts in the first place according to current binding.  Is it making any sen=
se to have ISA devices directly under pci bus?


>=20
> Boards with this problem should set fsl_pci_primary in platform code
> based on whatever criteria is relevant.

I don't know how legitimate it is to use a new kernel but not the device tr=
ee from that source.  If that's the problem that we need to take care of, I=
 think we need to add the workaround in the platform code temporarily for a=
 transitional period.

>=20
> -Scott
>=20

^ permalink raw reply

* Re: [PATCH 4/8] time: Condense timekeeper.xtime into xtime_sec
From: John Stultz @ 2012-08-21 18:14 UTC (permalink / raw)
  To: Andreas Schwab
  Cc: Prarit Bhargava, Peter Zijlstra, Richard Cochran, Linux Kernel,
	Thomas Gleixner, linuxppc-dev, Ingo Molnar
In-Reply-To: <m2d32kemyp.fsf@igel.home>

On 08/21/2012 12:14 AM, Andreas Schwab wrote:
> John Stultz <john.stultz@linaro.org> writes:
>
>> @@ -115,6 +115,7 @@ static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts)
>>   {
>>   	tk->xtime_sec += ts->tv_sec;
>>   	tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift;
>> +	tk_normalize_xtime(tk);
>>   }
> Yes, that does it.  Failure to normalize is always bad.

Great. Thanks for the testing and the bug report! I'll be sending out 
the patch to -tip later today.

thanks
-john

^ permalink raw reply

* [PATCH] powerpc/mm: match variable types to API
From: Paul Gortmaker @ 2012-08-21 18:22 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Paul Mackerras, Paul Gortmaker, Joe MacDonald

From: Joe MacDonald <joe.macdonald@windriver.com>

sys_subpage_prot() takes an unsigned long for 'addr' then does some stuff
with it and the result is stored in a signed int, i, which is eventually
used as the size parameter in a copy_from_user call.  Update 'i' to be an
unsigned long as well and since 'nw' is used in a size_t context which,
depending on whether this is 32- or 64-bit may be unsigned int or unsigned
long, switch that to a size_t and always be right.

Finally, since we're in the neighbourhood, make the same changes to
subpage_prot_clear().

Cc: Paul Mackerras <paulus@samba.org>
Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Joe MacDonald <joe.macdonald@windriver.com>
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
---
 arch/powerpc/mm/subpage-prot.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/mm/subpage-prot.c b/arch/powerpc/mm/subpage-prot.c
index e4f8f1f..7c415dd 100644
--- a/arch/powerpc/mm/subpage-prot.c
+++ b/arch/powerpc/mm/subpage-prot.c
@@ -95,7 +95,8 @@ static void subpage_prot_clear(unsigned long addr, unsigned long len)
 	struct mm_struct *mm = current->mm;
 	struct subpage_prot_table *spt = &mm->context.spt;
 	u32 **spm, *spp;
-	int i, nw;
+	unsigned long i;
+	size_t nw;
 	unsigned long next, limit;
 
 	down_write(&mm->mmap_sem);
@@ -144,7 +145,8 @@ long sys_subpage_prot(unsigned long addr, unsigned long len, u32 __user *map)
 	struct mm_struct *mm = current->mm;
 	struct subpage_prot_table *spt = &mm->context.spt;
 	u32 **spm, *spp;
-	int i, nw;
+	unsigned long i;
+	size_t nw;
 	unsigned long next, limit;
 	int err;
 
-- 
1.7.11.1

^ permalink raw reply related

* Re: [PATCH V8] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Scott Wood @ 2012-08-21 18:24 UTC (permalink / raw)
  To: Li Yang-R58472
  Cc: Wood Scott-B07421, Bradley Hughes, linuxppc-dev@lists.ozlabs.org,
	Jia Hongtao-B38951
In-Reply-To: <C22578AD-1B40-4F3A-AB3B-4ECABE218815@freescale.com>

On 08/21/2012 01:09 PM, Li Yang-R58472 wrote:
> 
> 
> On Aug 22, 2012, at 1:16, "Wood Scott-B07421" <B07421@freescale.com> wrote:
> 
>> On 08/21/2012 01:49 AM, Li Yang-R58472 wrote:
>>> If there is i8259 node in the device tree, it should be suggesting
>>> that there is a PCI to ISA bridge but not explicitly described in the
>>> device tree.  Then we need to fix the device tree to add the ISA
>>> nodes.
>>
>> No, we need to work with existing device trees.  Just because they're
>> hosted in the kernel tree doesn't mean they can be treated as an
>> internal kernel implementation detail.  They are stable API with
>> external entities such as bootloaders and hypervisors, get forked for
>> custom boards, etc.
> 
> You are right that device tree binding is a stable API but not a poorly written dts instance.
>
> We are not changing any binding definition.  It is just adding the
> somehow missed node that should be there in some poorly written dts
> in the first place according to current binding.  Is it making any
> sense to have ISA devices directly under pci bus?

I agree in general, but in this case it's easy enough to work with
existing trees, and the workaround is localized to platform code for the
boards with the problem.  Adding this workaround doesn't prevent adding
an isa node to the device tree.

>> Boards with this problem should set fsl_pci_primary in platform code
>> based on whatever criteria is relevant.
> 
> I don't know how legitimate it is to use a new kernel but not the
> device tree from that source. 

It's legitimate, if a bit risky because we have a history of not getting
device trees right the first time (but it should still be a goal).
Conisder that significant parts of the device tree often come from
firmware rather than the .dts.  As I've said a few times in the past, I
think the device trees should be kept in the U-Boot tree rather than
Linux (only those that are meant to be used with U-Boot, of course).
It's a U-Boot internal implementation issue what comes from the .dts and
what gets fixed up or generated at runtime.

-Scott

^ permalink raw reply

* Re: [PATCH V8] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Scott Wood @ 2012-08-21 18:33 UTC (permalink / raw)
  To: Jia Hongtao-B38951
  Cc: Wood Scott-B07421, Bradley Hughes, linuxppc-dev@lists.ozlabs.org,
	Li Yang-R58472
In-Reply-To: <412C8208B4A0464FA894C5F0C278CD5D01A56A61@039-SN1MPN1-002.039d.mgd.msft.net>

On 08/20/2012 10:26 PM, Jia Hongtao-B38951 wrote:
> 
> 
>> -----Original Message-----
>> From: Wood Scott-B07421
>> Sent: Tuesday, August 21, 2012 6:04 AM
>> To: Jia Hongtao-B38951
>> Cc: linuxppc-dev@lists.ozlabs.org; galak@kernel.crashing.org; Li Yang-
>> R58472; Bradley Hughes
>> Subject: Re: [PATCH V8] powerpc/fsl-pci: Unify pci/pcie initialization
>> code
>>
>> Another interesting case is stxssa8555.dts, which has an i8259 node but
>> no ISA node (are there any other instances of this?).  However, I can't
>> tell if stx_gp3.c is the platform file that goes with this device tree,
>> or if the platform code for stxssa8555 is out-of-tree (or some other file
>> that I'm not seeing).
> 
> MPC8541_CDS and MPC8555_CDS also has i8259 but no ISA node. stx_gp3 seems go
> with stxssa8555.dts but I'm not sure ether.
> 
> So you mean we have to look for i8259 too for determining primary.
> Take device tree as evidence we can tell that real primary ether has isa node
> or i8259 node. And if there is no isa we just arbitrarily designate one.
> 
> If this logic works well then ok.

Yes, but it should be board code that does this, as it's a workaround
for a broken device tree.

Maybe have a common helper function that finds a toplevel PCI bus that
contains a node matching a supplied of_match.  This could be used for
both the ISA lookup and the i8259 lookup, and any other weird thing some
board might have as long as it can be uniquely represented with of_match.

-Scott

^ permalink raw reply

* [PATCH] powerpc/fsl: fix "Failed to mount /dev: No such device" errors
From: Kim Phillips @ 2012-08-21 22:23 UTC (permalink / raw)
  To: linuxppc-dev

Yocto (Built by Poky 7.0) 1.2 root filesystems fail to boot,
at least over nfs, with:

Failed to mount /dev: No such device

Configuring DEVTMPFS fixes it.

Note: all non-DEVTMPFS changes are due to the side effects of
running make savedefconfig.

Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
---
if the savedefconfig effects are undesired, I can re-post
a two-patch series, the first the result of only running
savedefconfig, the second the addition of DEVTMPFS.

based on Kumar's powerpc.git next branch (commit 1ee9545)

 arch/powerpc/configs/85xx/p1023rds_defconfig | 31 +++++++++------------------
 arch/powerpc/configs/corenet32_smp_defconfig | 29 ++++++++-----------------
 arch/powerpc/configs/corenet64_smp_defconfig |  1 +
 arch/powerpc/configs/mpc83xx_defconfig       | 18 +++++-----------
 arch/powerpc/configs/mpc85xx_defconfig       | 32 +++++++---------------------
 arch/powerpc/configs/mpc85xx_smp_defconfig   | 32 +++++++---------------------
 6 files changed, 41 insertions(+), 102 deletions(-)

diff --git a/arch/powerpc/configs/85xx/p1023rds_defconfig b/arch/powerpc/configs/85xx/p1023rds_defconfig
index f4337ba..26e541c 100644
--- a/arch/powerpc/configs/85xx/p1023rds_defconfig
+++ b/arch/powerpc/configs/85xx/p1023rds_defconfig
@@ -6,28 +6,27 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_EMBEDDED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_P1023_RDS=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_CPM2=y
-CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
@@ -63,11 +62,11 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -80,15 +79,14 @@ CONFIG_SATA_FSL=y
 CONFIG_SATA_SIL24=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_FS_ENET=y
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_E1000E=y
 CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FS_ENET=y
-CONFIG_E1000E=y
-CONFIG_FSL_PQ_MDIO=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
@@ -98,16 +96,15 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_QE=m
-CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_SOUND=y
@@ -123,7 +120,6 @@ CONFIG_DMADEVICES=y
 CONFIG_FSL_DMA=y
 # CONFIG_NET_DMA is not set
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
@@ -150,22 +146,15 @@ CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_FRAME_WARN=8092
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
diff --git a/arch/powerpc/configs/corenet32_smp_defconfig b/arch/powerpc/configs/corenet32_smp_defconfig
index 3b40015..1c0f243 100644
--- a/arch/powerpc/configs/corenet32_smp_defconfig
+++ b/arch/powerpc/configs/corenet32_smp_defconfig
@@ -6,8 +6,8 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
-CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -21,24 +21,23 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_P5040_DS=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_FSL_LBC=y
 CONFIG_PCI=y
 CONFIG_PCIEPORTBUS=y
-CONFIG_PCI_MSI=y
 # CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
 CONFIG_RAPIDIO=y
 CONFIG_FSL_RIO=y
 CONFIG_NET=y
@@ -71,6 +70,7 @@ CONFIG_INET_IPCOMP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -78,17 +78,14 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_FSL_IFC=y
 CONFIG_MTD_NAND_FSL_ELBC=y
-CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND_FSL_IFC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -116,11 +113,9 @@ CONFIG_SERIO_LIBPS2=y
 CONFIG_PPC_EPAPR_HV_BYTECHAN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
-CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -133,7 +128,6 @@ CONFIG_SPI_FSL_ESPI=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_USB_HID=m
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_FSL=y
@@ -143,8 +137,6 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
@@ -171,19 +163,16 @@ CONFIG_HUGETLBFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_RCU_TRACE=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_MD4=y
diff --git a/arch/powerpc/configs/corenet64_smp_defconfig b/arch/powerpc/configs/corenet64_smp_defconfig
index 36df45b..88fa5c4 100644
--- a/arch/powerpc/configs/corenet64_smp_defconfig
+++ b/arch/powerpc/configs/corenet64_smp_defconfig
@@ -57,6 +57,7 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
diff --git a/arch/powerpc/configs/mpc83xx_defconfig b/arch/powerpc/configs/mpc83xx_defconfig
index 5aac9a8..9352e44 100644
--- a/arch/powerpc/configs/mpc83xx_defconfig
+++ b/arch/powerpc/configs/mpc83xx_defconfig
@@ -2,12 +2,12 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
 # CONFIG_PPC_CHRP is not set
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_83xx=y
@@ -25,7 +25,6 @@ CONFIG_ASP834x=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -42,10 +41,9 @@ CONFIG_INET_ESP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -64,15 +62,14 @@ CONFIG_ATA=y
 CONFIG_SATA_FSL=y
 CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_UCC_GETH=y
+CONFIG_GIANFAR=y
 CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_GIANFAR=y
-CONFIG_UCC_GETH=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
@@ -112,17 +109,12 @@ CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_CRC_T10DIF=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
diff --git a/arch/powerpc/configs/mpc85xx_defconfig b/arch/powerpc/configs/mpc85xx_defconfig
index 627c257..cf815e8 100644
--- a/arch/powerpc/configs/mpc85xx_defconfig
+++ b/arch/powerpc/configs/mpc85xx_defconfig
@@ -5,7 +5,9 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -17,6 +19,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_MPC8540_ADS=y
 CONFIG_MPC8560_ADS=y
 CONFIG_MPC85xx_CDS=y
@@ -41,8 +45,6 @@ CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 CONFIG_FORCE_MAX_ZONEORDER=12
@@ -75,36 +77,25 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
 CONFIG_FTL=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -136,7 +127,6 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
@@ -185,7 +175,6 @@ CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_FSL=y
@@ -231,18 +220,13 @@ CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
diff --git a/arch/powerpc/configs/mpc85xx_smp_defconfig b/arch/powerpc/configs/mpc85xx_smp_defconfig
index 8d1c2a4..502cd9e 100644
--- a/arch/powerpc/configs/mpc85xx_smp_defconfig
+++ b/arch/powerpc/configs/mpc85xx_smp_defconfig
@@ -7,7 +7,9 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -19,6 +21,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_MPC8540_ADS=y
 CONFIG_MPC8560_ADS=y
 CONFIG_MPC85xx_CDS=y
@@ -43,8 +47,6 @@ CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 CONFIG_IRQ_ALL_CPUS=y
@@ -78,36 +80,25 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
 CONFIG_FTL=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -138,7 +129,6 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
@@ -187,7 +177,6 @@ CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_FSL=y
@@ -233,18 +222,13 @@ CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
-- 
1.7.11.4

^ permalink raw reply related

* Re: [PATCH] powerpc/fsl: fix "Failed to mount /dev: No such device" errors
From: Kumar Gala @ 2012-08-22  3:51 UTC (permalink / raw)
  To: Kim Phillips; +Cc: linuxppc-dev
In-Reply-To: <20120821172303.53d5698006b32063dca99300@freescale.com>


On Aug 21, 2012, at 5:23 PM, Kim Phillips wrote:

> Yocto (Built by Poky 7.0) 1.2 root filesystems fail to boot,
> at least over nfs, with:
>=20
> Failed to mount /dev: No such device
>=20
> Configuring DEVTMPFS fixes it.
>=20
> Note: all non-DEVTMPFS changes are due to the side effects of
> running make savedefconfig.
>=20
> Signed-off-by: Kim Phillips <kim.phillips@freescale.com>
> ---
> if the savedefconfig effects are undesired, I can re-post
> a two-patch series, the first the result of only running
> savedefconfig, the second the addition of DEVTMPFS.
>=20
> based on Kumar's powerpc.git next branch (commit 1ee9545)
>=20
> arch/powerpc/configs/85xx/p1023rds_defconfig | 31 =
+++++++++------------------
> arch/powerpc/configs/corenet32_smp_defconfig | 29 =
++++++++-----------------
> arch/powerpc/configs/corenet64_smp_defconfig |  1 +
> arch/powerpc/configs/mpc83xx_defconfig       | 18 +++++-----------
> arch/powerpc/configs/mpc85xx_defconfig       | 32 =
+++++++---------------------
> arch/powerpc/configs/mpc85xx_smp_defconfig   | 32 =
+++++++---------------------
> 6 files changed, 41 insertions(+), 102 deletions(-)

Do split this into 2 patches.. Also do it against 'merge' and not 'next' =
as this fix should go into v3.6.

- k=

^ permalink raw reply

* [PATCH] DMA/RaidEngine: Enable FSL RaidEngine
From: b29237 @ 2012-08-22  6:24 UTC (permalink / raw)
  To: dan.j.williams, vinod.koul, linuxppc-dev, linux-kernel
  Cc: Harninder Rai, b01044, iws, Naveen Burmi, b16502, Xuelin Shi

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>
---
 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 ++
 drivers/dma/Kconfig                            |   14 +
 drivers/dma/Makefile                           |    1 +
 drivers/dma/fsl_raid.c                         | 1090 ++++++++++++++++++++++++
 drivers/dma/fsl_raid.h                         |  294 +++++++
 7 files changed, 1491 insertions(+), 0 deletions(-)
 create mode 100644 arch/powerpc/boot/dts/fsl/qoriq-raid1.0-0.dtsi
 create mode 100644 drivers/dma/fsl_raid.c
 create mode 100644 drivers/dma/fsl_raid.h

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 ae823a4..d54cd90 100644
--- a/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
+++ b/arch/powerpc/boot/dts/fsl/p5020si-pre.dtsi
@@ -70,6 +70,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>;
+		};
+	};
+};
diff --git a/drivers/dma/Kconfig b/drivers/dma/Kconfig
index d06ea29..1b94c8e 100644
--- a/drivers/dma/Kconfig
+++ b/drivers/dma/Kconfig
@@ -292,6 +292,20 @@ config DMA_OMAP
 	select DMA_ENGINE
 	select DMA_VIRTUAL_CHANNELS
 
+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 4cf6b12..b3e7702 100644
--- a/drivers/dma/Makefile
+++ b/drivers/dma/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_EP93XX_DMA) += ep93xx_dma.o
 obj-$(CONFIG_DMA_SA11X0) += sa11x0-dma.o
 obj-$(CONFIG_MMP_TDMA) += mmp_tdma.o
 obj-$(CONFIG_DMA_OMAP) += omap-dma.o
+obj-$(CONFIG_FSL_RAID) += fsl_raid.o
diff --git a/drivers/dma/fsl_raid.c b/drivers/dma/fsl_raid.c
new file mode 100644
index 0000000..ec860fd
--- /dev/null
+++ b/drivers/dma/fsl_raid.c
@@ -0,0 +1,1090 @@
+/*
+ * drivers/dma/fsl_raid.c
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ *	Harninder Rai <harninder.rai@freescale.com>
+ *	Naveen Burmi <naveenburmi@freescale.com>
+ *	Xuelin Shi <b29237@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/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 <linux/module.h>
+
+#include "fsl_raid.h"
+
+#define MAX_RE_JRS		4
+#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)
+
+struct re_drv_private {
+	struct device *dev;
+	u8 total_jrs;
+	struct dma_device dma_dev;
+	struct re_ctrl *re_regs;
+	struct re_jr *re_jrs[MAX_RE_JRS];
+};
+
+static struct kmem_cache *re_sw_desc_cache;
+
+/* 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->desc_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;
+	list_add_tail(&desc->node, &jr->submit_q);
+
+	if (!timer_pending(&jr->timer))
+		add_timer(&jr->timer);
+
+	spin_unlock_bh(&jr->desc_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;
+
+	dma_run_dependencies(&desc->async_tx);
+
+	spin_lock_bh(&dma_jr->desc_lock);
+	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;
+	}
+	spin_unlock_bh(&dma_jr->desc_lock);
+
+	callback = desc->async_tx.callback;
+	callback_param = desc->async_tx.callback_param;
+
+	re_jr_unmap_dest_src(desc);
+
+	/* Free the cf/cdb address stored in descs
+	 * unconditionally. These pointers are only
+	 * required for RE driver's housekeeping
+	 */
+	dma_pool_free(dma_jr->desc_pool, desc->cf_addr, desc->cf_paddr);
+	dma_pool_free(dma_jr->desc_pool, desc->cdb_addr, desc->cdb_paddr);
+
+	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 device *)data;
+	struct re_jr *jr = dev_get_drvdata(dev);
+	struct fsl_re_dma_async_tx_desc *desc;
+	unsigned int count = 0;
+	struct fsl_re_dma_async_tx_desc *ack_desc = NULL, *_ack_desc = NULL;
+
+	while ((count =
+		RE_JR_OUB_SLOT_FULL(in_be32(&jr->jrregs->oubring_slot_full)))) {
+		while (count--) {
+			spin_lock_bh(&jr->desc_lock);
+
+			/* Wrap around index */
+			jr->oub_count &= RING_SIZE-1;
+
+			desc = (struct fsl_re_dma_async_tx_desc *)
+				jr->virt_arry[jr->oub_count].virt_addr;
+
+			/* Re-initialise so that it can be reused */
+			jr->virt_arry[jr->oub_count].virt_addr = 0;
+			jr->virt_arry[jr->oub_count++].phys_addr = 0;
+
+			/* One job processed */
+			out_be32(&jr->jrregs->oubring_job_rmvd,
+						RE_JR_OUB_JOB_REMOVE);
+
+			list_add_tail(&desc->node, &jr->ack_q);
+
+			spin_unlock_bh(&jr->desc_lock);
+
+			re_jr_desc_done(desc);
+		}
+	}
+
+	/* 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)) {
+			list_del(&ack_desc->node);
+			kmem_cache_free(re_sw_desc_cache, ack_desc);
+		}
+	}
+}
+
+/* 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;
+
+	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) {
+		dev_err(dev, "%s: jr error irqstate: %x\n", __func__,
+			irqstate);
+		BUG();
+	}
+
+	/* Clear interrupt */
+	out_be32(&jr->jrregs->jr_interrupt_status, RE_JR_CLEAR_INT);
+
+	tasklet_schedule(&jr->irqtask);
+
+	return IRQ_HANDLED;
+}
+
+static int re_jr_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct re_jr *jr = container_of(chan, struct re_jr, chan);
+
+	jr->desc_pool = dma_pool_create("re_jr_desc_pool", jr->dev,
+					RE_CF_CDB_SIZE, RE_CF_CDB_ALIGN, 0);
+
+	if (!jr->desc_pool) {
+		pr_err("%s:No memory for re_jr_desc_pool\n", __func__);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+/* This function is just to please the ASYNC layer */
+static void re_jr_free_chan_resources(struct dma_chan *chan)
+{
+	struct re_jr *jr = container_of(chan, struct re_jr, chan);
+	dma_pool_destroy(jr->desc_pool);
+}
+
+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;
+	struct fsl_re_dma_async_tx_desc *desc, *_desc;
+
+	jr = container_of(chan, struct re_jr, chan);
+	if (timer_pending(&jr->timer))
+		del_timer_sync(&jr->timer);
+
+	spin_lock_bh(&jr->desc_lock);
+
+	list_for_each_entry_safe(desc, _desc, &jr->submit_q, node) {
+
+		if (!in_be32(&jr->jrregs->inbring_slot_avail))
+			goto out_unlock;
+
+		/* Wrap around ring index */
+		jr->inb_count &= RING_SIZE-1;
+
+		if (jr->virt_arry[jr->inb_count].phys_addr != 0)
+			goto out_unlock;
+
+		jr->virt_arry[jr->inb_count].phys_addr =
+			(phys_addr_t)desc->hwdesc.address;
+		jr->virt_arry[jr->inb_count++].virt_addr = (unsigned long)desc;
+
+		/* Wrap around ring index */
+		jr->inb_ring_index &= RING_SIZE-1;
+
+		/* Copy frame descriptor into job ring */
+		memcpy(&jr->inb_ring_virt_addr[jr->inb_ring_index],
+			&desc->hwdesc, sizeof(struct jr_hw_desc));
+
+		smp_wmb();
+
+		jr->inb_ring_index++;
+		list_del_init(&desc->node);
+
+		wmb();
+
+		/* One job has been added into job ring */
+		out_be32(&jr->jrregs->inbring_add_job, RE_JR_INB_JOB_ADD);
+	}
+out_unlock:
+	spin_unlock_bh(&jr->desc_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);
+}
+
+static void fill_cfd_frame(struct cmpnd_frame *cf, u8 index,
+		size_t length, dma_addr_t addr, bool final)
+{
+	cf[index].extension = 0;
+	cf[index].final = final;
+	cf[index].rsvd1 = 0;
+	cf[index].rsvd3 = 0;
+	cf[index].rsvd4 = 0;
+	cf[index].rsvd5 = 0;
+	cf[index].length = length;
+	cf[index].offset = 0;
+	cf[index].address = addr;
+
+}
+
+static struct fsl_re_dma_async_tx_desc *re_jr_alloc_desc(struct re_jr *jr,
+					int cf_num, unsigned long flags)
+{
+	struct fsl_re_dma_async_tx_desc *desc = NULL;
+	struct jr_hw_desc *hw_desc = NULL;
+	struct cmpnd_frame *cf;
+	dma_addr_t paddr;
+
+	desc = kmem_cache_alloc(re_sw_desc_cache, GFP_KERNEL);
+	if (!desc)
+		return NULL;
+
+	memset(desc, 0, sizeof(*desc));
+	desc->async_tx.tx_submit = re_jr_tx_submit;
+	dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
+	INIT_LIST_HEAD(&desc->node);
+	hw_desc = &desc->hwdesc;
+	hw_desc->format = FRAME_FORMAT;
+
+	cf = dma_pool_alloc(jr->desc_pool, GFP_ATOMIC, &paddr);
+	if (!cf) {
+		kmem_cache_free(re_sw_desc_cache, desc);
+		return NULL;
+	}
+
+	hw_desc->address = paddr;
+	desc->cf_addr = cf;
+	desc->cf_paddr = paddr;
+	desc->cf_len = sizeof(struct cmpnd_frame)*cf_num;
+	memset(cf, 0, desc->cf_len);
+
+	desc->jr = jr;
+	desc->async_tx.cookie = -EBUSY;
+	desc->async_tx.flags = flags;
+
+	return desc;
+}
+
+static void re_jr_free_desc(struct fsl_re_dma_async_tx_desc *desc)
+{
+	struct re_jr *jr = NULL;
+
+	if (desc == NULL)
+		return;
+
+	jr = desc->jr;
+
+	dma_pool_free(jr->desc_pool, desc->cf_addr, desc->cf_paddr);
+	kmem_cache_free(re_sw_desc_cache, 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;
+	unsigned int cfs_reqd = src_cnt + 2; /* CDB+dest+src_cnt */
+	struct cmpnd_frame *cf;
+	int i = 0, j = 0;
+	dma_addr_t paddr;
+
+	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, cfs_reqd, flags);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->dma_len = len;
+	desc->dest_cnt = 1;
+	desc->src_cnt = src_cnt;
+
+	/* Allocate memory for GenQ CDB */
+	xor = dma_pool_alloc(jr->desc_pool, GFP_ATOMIC, &paddr);
+	if (!xor) {
+		re_jr_free_desc(desc);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	desc->cdb_addr = xor;
+	desc->cdb_paddr = paddr;
+	desc->cdb_len = sizeof(struct xor_cdb);
+	memset(xor, 0, desc->cdb_len);
+	desc->cdb_opcode = RE_XOR_OPCODE;
+
+	/* Filling xor CDB */
+	xor->opcode = RE_XOR_OPCODE;
+	xor->nrcs = (src_cnt - 1);
+	xor->blk_size = RE_BLOCK_SIZE;
+	xor->cache_attrib = CACHEABLE_INPUT_OUTPUT;
+	xor->buffer_attrib = BUFFERABLE_OUTPUT;
+	xor->error_attrib = INTERRUPT_ON_ERROR;
+	xor->data_depend = DATA_DEPENDENCY;
+	xor->dpi = ENABLE_DPI;
+
+	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, 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;
+	u8 cfs_reqd = src_cnt + 3; /* CDB+P+Q+src_cnt */
+	struct cmpnd_frame *cf;
+	u8 *p;
+	int gfmq_len, i, j;
+	dma_addr_t paddr;
+
+	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 generate
+	 * 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, cfs_reqd, flags);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->dma_len = len;
+	desc->dest_cnt = 2;
+	desc->src_cnt = src_cnt;
+
+	/* Filling frame 0 of compound frame descriptor with CDB */
+	pq = dma_pool_alloc(jr->desc_pool, GFP_ATOMIC, &paddr);
+	if (!pq) {
+		re_jr_free_desc(desc);
+		return ERR_PTR(-ENOMEM);
+	}
+	desc->cdb_addr = pq;
+	desc->cdb_paddr = paddr;
+	desc->cdb_len = sizeof(struct pq_cdb);
+	memset(pq, 0, desc->cdb_len);
+	desc->cdb_opcode = RE_PQ_OPCODE;
+
+	/* Filling GenQQ CDB */
+	pq->opcode = RE_PQ_OPCODE;
+	pq->excl_enable = 0x0; /* Don't exclude for Q1/Q2 parity */
+	pq->excl_q1 = 0x0;
+	pq->excl_q2 = 0x0;
+	pq->blk_size = RE_BLOCK_SIZE;
+	pq->cache_attrib = CACHEABLE_INPUT_OUTPUT;
+	pq->buffer_attrib = BUFFERABLE_OUTPUT;
+	pq->error_attrib = INTERRUPT_ON_ERROR;
+	pq->data_depend = DATA_DEPENDENCY;
+	pq->dpi = ENABLE_DPI;
+	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, 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;
+	unsigned int cfs_reqd = 3; /* CDB+dest+src */
+	struct cmpnd_frame *cf = NULL;
+	struct move_cdb *move = NULL;
+	dma_addr_t paddr;
+
+	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, cfs_reqd, flags);
+	if (!desc)
+		return ERR_PTR(-ENOMEM);
+
+	desc->dma_len = len;
+	desc->src_cnt = 1;
+	desc->dest_cnt = 1;
+
+	move = dma_pool_alloc(jr->desc_pool, GFP_ATOMIC, &paddr);
+	if (!move) {
+		re_jr_free_desc(desc);
+		return ERR_PTR(-ENOMEM);
+	}
+	desc->cdb_addr = move;
+	desc->cdb_paddr = paddr;
+	desc->cdb_len = sizeof(struct move_cdb);
+	memset(move, 0, desc->cdb_len);
+	desc->cdb_opcode = RE_MOVE_OPCODE;
+
+	/* Filling move CDB */
+	move->opcode = RE_MOVE_OPCODE; /* Unicast move */
+	move->blk_size = RE_BLOCK_SIZE;
+	move->cache_attrib = CACHEABLE_INPUT_OUTPUT;
+	move->buffer_attrib = BUFFERABLE_OUTPUT;
+	move->error_attrib = INTERRUPT_ON_ERROR;
+	move->data_depend = DATA_DEPENDENCY;
+	move->dpi = ENABLE_DPI;
+
+	/* Filling frame 0 of CFD with move CDB */
+	cf = desc->cf_addr;
+	fill_cfd_frame(cf, 0, desc->cdb_len, 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;
+}
+
+/*
+ * Job ring probe function. This function gets called for each detected
+ * job ring in the system
+ */
+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;
+	int k = 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_2;
+	}
+	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_2;
+	}
+
+	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_2;
+	}
+
+	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_2;
+	}
+
+	repriv->re_jrs[q] = jr;
+	jr->chan.device = dma_dev;
+	jr->dev = &ofdev->dev;
+	jr->chan.private = jr;
+
+	INIT_LIST_HEAD(&jr->submit_q);
+	INIT_LIST_HEAD(&jr->ack_q);
+	spin_lock_init(&jr->desc_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_desc_pool = dma_pool_create("re_jr_inb_desc_pool", jr->dev,
+			sizeof(struct jr_hw_desc) * RING_SIZE,
+			FRAME_DESC_ALIGNMENT, 0);
+	if (!jr->inb_desc_pool) {
+		dev_err(dev, "%s:No memory for re_jr_inb_desc_pool\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free_2;
+	}
+
+	jr->inb_ring_virt_addr = dma_pool_alloc(jr->inb_desc_pool, GFP_ATOMIC,
+			&jr->inb_phys_addr);
+	if (!jr->inb_ring_virt_addr) {
+		dev_err(dev, "%s:No dma_pool mem for inb_ring_virt_addr\n",
+			__func__);
+		ret = -ENOMEM;
+		goto pool_destroy;
+	}
+
+	jr->oub_desc_pool = dma_pool_create("re_jr_oub_desc_pool", jr->dev,
+			sizeof(struct jr_hw_desc) * RING_SIZE,
+			FRAME_DESC_ALIGNMENT, 0);
+	if (!jr->oub_desc_pool) {
+		dev_err(dev, "%s:No memory for re_jr_oub_desc_pool\n",
+			__func__);
+		ret = -ENOMEM;
+		goto pool_free;
+	}
+
+	jr->oub_ring_virt_addr = dma_pool_alloc(jr->oub_desc_pool, GFP_ATOMIC,
+			&jr->oub_phys_addr);
+	if (!jr->inb_ring_virt_addr) {
+		dev_err(dev, "%s:No dma_pool mem for oub_ring_virt_addr\n",
+			__func__);
+		ret = -ENOMEM;
+		goto pool_destroy_2;
+	}
+
+	jr->desc_pool = dma_pool_create("re_jr_desc_pool", jr->dev,
+			RE_CF_CDB_SIZE, RE_CF_CDB_ALIGN, 0);
+
+	if (!jr->desc_pool) {
+		dev_err(dev, "%s:No memory for re_jr_desc_pool\n",
+			__func__);
+		ret = -ENOMEM;
+		goto err_free_2;
+	}
+
+	jr->inb_ring_index = 0;
+	jr->inb_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_2;
+	}
+
+	/* 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);
+
+	/* Zero'ing the array */
+	for (k = 0; k < RING_SIZE; k++) {
+		jr->virt_arry[k].virt_addr = 0;
+		jr->virt_arry[k].phys_addr = 0;
+	}
+
+	return 0;
+
+pool_free_2:
+	dma_pool_free(jr->oub_desc_pool, jr->oub_ring_virt_addr,
+			jr->oub_phys_addr);
+pool_destroy_2:
+	dma_pool_destroy(jr->oub_desc_pool);
+pool_free:
+	dma_pool_free(jr->inb_desc_pool, jr->inb_ring_virt_addr,
+			jr->inb_phys_addr);
+pool_destroy:
+	dma_pool_destroy(jr->inb_desc_pool);
+err_free_2:
+	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;
+
+	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);
+		return -ENOMEM;
+	}
+
+
+	re_sw_desc_cache = kmem_cache_create("re_desc_cache",
+				sizeof(struct fsl_re_dma_async_tx_desc), 0,
+				SLAB_HWCACHE_ALIGN, NULL);
+	if (re_sw_desc_cache == NULL) {
+		dev_err(dev, "%s: No memory for re_sw_desc_cache\n", __func__);
+		iounmap(repriv->re_regs);
+		kfree(repriv);
+		return -ENOMEM;
+	}
+
+	/* 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 polymomial */
+	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_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;
+
+	/* 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;
+}
+
+static void release_jr(struct re_jr *jr)
+{
+	/* Free the memory allocated from DMA pools and destroy them */
+	dma_pool_free(jr->oub_desc_pool, jr->oub_ring_virt_addr,
+			jr->oub_phys_addr);
+	dma_pool_destroy(jr->oub_desc_pool);
+	dma_pool_free(jr->inb_desc_pool, jr->inb_ring_virt_addr,
+			jr->inb_phys_addr);
+	dma_pool_destroy(jr->inb_desc_pool);
+
+	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]);
+
+	kmem_cache_destroy(re_sw_desc_cache);
+
+	/* 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..0f39b8d
--- /dev/null
+++ b/drivers/dma/fsl_raid.h
@@ -0,0 +1,294 @@
+/*
+ * drivers/dma/fsl_raid.h
+ *
+ * Freescale RAID Engine device driver
+ *
+ * Author:
+ *	Harninder Rai <harninder.rai@freescale.com>
+ *	Naveen Burmi <naveenburmi@freescale.com>
+ *	Xuelin Shi <b29237@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	(1 << 16)
+#define RE_JR_OUB_JOB_REMOVE	(1 << 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_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
+
+/*
+ * max size is 19*sizeof(struct cmpnd_frame), 64 bytes align to 320
+ * here 19 = 1(cdb)+2(dest)+16(src)
+ */
+#define RE_CF_CDB_SIZE		320
+
+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;
+
+/* Array to store the virtual/physical address of descriptors */
+struct virt_struct {
+	unsigned long virt_addr;
+	phys_addr_t phys_addr;
+};
+
+/* Per job ring data structure */
+struct re_jr {
+	dma_cookie_t completed_cookie;
+	spinlock_t desc_lock;
+	struct list_head submit_q;
+	struct list_head ack_q;
+	struct device *dev;
+	struct dma_chan chan;
+	struct jr_config_regs *jrregs;
+	int irq;
+	struct tasklet_struct irqtask;
+	dma_addr_t inb_phys_addr;
+	dma_addr_t oub_phys_addr;
+	struct dma_pool *inb_desc_pool;
+	struct dma_pool *oub_desc_pool;
+	struct jr_hw_desc *inb_ring_virt_addr;
+	struct jr_hw_desc *oub_ring_virt_addr;
+	u32 inb_ring_index;
+	u32 inb_count;
+	u32 oub_count;
+	struct virt_struct virt_arry[RING_SIZE];
+	struct timer_list timer;
+	struct dma_pool *desc_pool;
+};
+
+/* 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;
+	int dest_cnt;
+	int src_cnt;
+	dma_addr_t cf_paddr;
+	int cf_len;
+	void *cdb_addr;
+	u32 cdb_opcode;
+	dma_addr_t cdb_paddr;
+	int cdb_len;
+};
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH 0/2] powerpc: perf hardware breakpoint fixes
From: Michael Neuling @ 2012-08-22  7:22 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Michael Neuling

Here are a couple of patches for perf for hardware breakpoints.  Along
with https://lkml.org/lkml/2012/8/16/5 hardware breakpoints now work
for me powerpc.  These patches don't depend on that patch though.

Michael Neuling (2):
  powerpc: Remove unessasary ifdefs
  powerpc: Fix null pointer deref in perf hardware breakpoints

 arch/powerpc/include/asm/cputable.h |    2 --
 arch/powerpc/kernel/hw_breakpoint.c |    3 ++-
 2 files changed, 2 insertions(+), 3 deletions(-)

-- 
1.7.9.5

^ permalink raw reply

* [PATCH] powerpc: Remove unnecessary ifdefs
From: Michael Neuling @ 2012-08-22  7:22 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Michael Neuling
In-Reply-To: <1345620143-17289-1-git-send-email-mikey@neuling.org>

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
 arch/powerpc/include/asm/cputable.h |    2 --
 1 file changed, 2 deletions(-)

diff --git a/arch/powerpc/include/asm/cputable.h b/arch/powerpc/include/asm/cputable.h
index 50d82c8..b3c083d 100644
--- a/arch/powerpc/include/asm/cputable.h
+++ b/arch/powerpc/include/asm/cputable.h
@@ -553,9 +553,7 @@ static inline int cpu_has_feature(unsigned long feature)
 		& feature);
 }
 
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
 #define HBP_NUM 1
-#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
 #endif /* !__ASSEMBLY__ */
 
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] powerpc: Fix null pointer deref in perf hardware breakpoints
From: Michael Neuling @ 2012-08-22  7:22 UTC (permalink / raw)
  To: benh; +Cc: linuxppc-dev, Michael Neuling
In-Reply-To: <1345620143-17289-1-git-send-email-mikey@neuling.org>

Currently if you are doing a global perf recording with hardware
breakpoints (ie perf record -e mem:0xdeadbeef -a), you can oops with:

  Faulting instruction address: 0xc000000000738890
  cpu 0xc: Vector: 300 (Data Access) at [c0000003f76af8d0]
      pc: c000000000738890: .hw_breakpoint_handler+0xa0/0x1e0
      lr: c000000000738830: .hw_breakpoint_handler+0x40/0x1e0
      sp: c0000003f76afb50
     msr: 8000000000001032
     dar: 6f0
   dsisr: 42000000
    current = 0xc0000003f765ac00
    paca    = 0xc00000000f262a00   softe: 0        irq_happened: 0x01
    pid   = 6810, comm = loop-read
  enter ? for help
  [c0000003f76afbe0] c00000000073cd04 .notifier_call_chain.isra.0+0x84/0xe0
  [c0000003f76afc80] c00000000073cdbc .notify_die+0x3c/0x60
  [c0000003f76afd20] c0000000000139f0 .do_dabr+0x40/0xf0
  [c0000003f76afe30] c000000000005a9c handle_dabr_fault+0x14/0x48
  --- Exception: 300 (Data Access) at 0000000010000480
  SP (ff8679e0) is in userspace

This is because we don't check to see if the break point is associated
with task before we deference the task_struct pointer.  This checks pointer
before dereferencing it.

Signed-off-by: Michael Neuling <mikey@neuling.org>
---
 arch/powerpc/kernel/hw_breakpoint.c |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/powerpc/kernel/hw_breakpoint.c b/arch/powerpc/kernel/hw_breakpoint.c
index f3a82dd..768182c 100644
--- a/arch/powerpc/kernel/hw_breakpoint.c
+++ b/arch/powerpc/kernel/hw_breakpoint.c
@@ -253,7 +253,8 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
 
 	/* Do not emulate user-space instructions, instead single-step them */
 	if (user_mode(regs)) {
-		bp->ctx->task->thread.last_hit_ubp = bp;
+		if (bp->ctx->task)
+			bp->ctx->task->thread.last_hit_ubp = bp;
 		regs->msr |= MSR_SE;
 		goto out;
 	}
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] RAID/DMA/caamxor: support XOR offload by CAAM
From: b29237 @ 2012-08-22  7:05 UTC (permalink / raw)
  To: dan.j.williams, vinod.koul, herbert, r1aaha, linux-crypto,
	linuxppc-dev, linux-kernel
  Cc: Xuelin Shi, naveenburmi

From: Xuelin Shi <b29237@freescale.com>

Add XOR offloading functionality by CAAM and interface with async_tx layer
so that it can be used for RAID parity computation.

Signed-off-by: Naveen Burmi <naveenburmi@freescale.com>
Signed-off-by: Yuan Kang <Yuan.Kang@freescale.com>
Signed-off-by: Xuelin Shi <b29237@freescale.com>
---
 drivers/crypto/caam/Kconfig       |   15 +
 drivers/crypto/caam/Makefile      |    1 +
 drivers/crypto/caam/caamxor.c     |  880 +++++++++++++++++++++++++++++++++++++
 drivers/crypto/caam/desc_constr.h |   53 +++-
 drivers/crypto/caam/intern.h      |    7 +
 drivers/crypto/caam/jr.c          |    8 +-
 6 files changed, 959 insertions(+), 5 deletions(-)
 create mode 100644 drivers/crypto/caam/caamxor.c

diff --git a/drivers/crypto/caam/Kconfig b/drivers/crypto/caam/Kconfig
index 65c7668..643ca0a 100644
--- a/drivers/crypto/caam/Kconfig
+++ b/drivers/crypto/caam/Kconfig
@@ -98,3 +98,18 @@ config CRYPTO_DEV_FSL_CAAM_RNG_API
 
 	  To compile this as a module, choose M here: the module
 	  will be called caamrng.
+
+config CRYPTO_DEV_FSL_CAAM_DMAXOR_API
+	tristate "Freescale CAAM XOR support"
+	depends on CRYPTO_DEV_FSL_CAAM && EXPERIMENTAL
+	default n
+	select DMA_ENGINE
+	select ASYNC_XOR
+	help
+	  Selecting this will offload the xor-parity-calculation for
+	  users of the Asynchronous Transfers/Transforms API (such as
+	  md-raid5 driver) to the SEC4.
+
+
+	  To compile this as a module, choose M here: the module
+	  will be called caamxor.
diff --git a/drivers/crypto/caam/Makefile b/drivers/crypto/caam/Makefile
index b1eb448..457192c 100644
--- a/drivers/crypto/caam/Makefile
+++ b/drivers/crypto/caam/Makefile
@@ -6,5 +6,6 @@ obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM) += caam.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_CRYPTO_API) += caamalg.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_AHASH_API) += caamhash.o
 obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_RNG_API) += caamrng.o
+obj-$(CONFIG_CRYPTO_DEV_FSL_CAAM_DMAXOR_API) += caamxor.o
 
 caam-objs := ctrl.o jr.o error.o key_gen.o
diff --git a/drivers/crypto/caam/caamxor.c b/drivers/crypto/caam/caamxor.c
new file mode 100644
index 0000000..f060cff
--- /dev/null
+++ b/drivers/crypto/caam/caamxor.c
@@ -0,0 +1,880 @@
+/*
+ * caam - Freescale Integrated Security Engine (SEC) device driver
+ * Support for off-loading XOR Parity Calculations to CAAM.
+ *
+ * Copyright 2011 Freescale Semiconductor, Inc
+ *
+ * relationship between job descriptors, shared descriptors and sources:
+ * ------------------------------           -------------------
+ * | ShareDesc                  |<------\   | JobDesc         |
+ * |   Load src pointers to ctx |        \--| ShareDesc ptr   |
+ * | new src jump dst:          |<-----\    | SEQ_OUT_PTR     |
+ * |   Load ith src             |      |    | (output buffer) |
+ * | new src mv dst:            |      |    | (output length) |
+ * |   (ith src commands)       |      |    | SEQ_IN_PTR      |
+ * | load:                      |<---\ |    | (src commands)  |----\
+ * |   Seq load chunk           |    | |    -------------------    |
+ * | return:                    |<---|-|-\                         |
+ * |   XOR quarter chunk        |    | | |                         |
+ * |   Pass complete?           |----^-^---\                       |
+ * |   Half chunk left?         |----^-+ | |                       |
+ * |   Default                  |----^-^-+ |                       |
+ * | store:                     |<---|-|-|-/                       |
+ * |   Seq store chunk          |    | | |    -------------------  |
+ * |   No data left to write?   |X   | | |    | first src ptr   |<-/
+ * |   Put src1 chunk in result |    | | |    | first src len   |
+ * |   Default                  |----^-+ |  /-| shared hdr jump |
+ * | first:                     |<---|-|-|-/  | nop (if needed) |
+ * |   No data left to read?    |----^-^-+    -------------------
+ * |   Seq load chunk           |    | | |    | ith src ptr     |
+ * |   Load src2                |    | | |    | ith src len     |
+ * |   Not first pass?          |----^-^-/    | load src i + 1  |
+ * | first pass:                |    | |      | nop (if needed) |
+ * |   Put src1 chunk in result |    | |      -------------------
+ * |   set output size          |    | |      | last src ptr    |
+ * |   Default                  |----^-/      | last src len    |
+ * | last:                      |<---|--------| shared hdr jump |
+ * |   Update index             |    |        | nop (if needed) |
+ * |   Load src1                |    |        -------------------
+ * |   Default                  |----/
+ * ------------------------------
+ *
+ */
+
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/dmaengine.h>
+
+#include "compat.h"
+#include "regs.h"
+#include "jr.h"
+#include "error.h"
+#include "intern.h"
+#include "desc.h"
+#include "desc_constr.h"
+
+#define MAX_INITIAL_DESCS	64
+#define MAX_XOR_SRCS		8
+
+#define JOB_DESC_BYTES		(4 * CAAM_CMD_SZ + 3 * CAAM_PTR_SZ)
+#define JOB_DESC_LEN		(JOB_DESC_BYTES / CAAM_CMD_SZ)
+#define CMD_DESC_LEN		32
+
+#define LONG_PTR		(CAAM_PTR_SZ > CAAM_CMD_SZ)
+
+#define CTX1_SLOTS		4
+#define SRC_CMD_BYTES		(4 * CAAM_CMD_SZ)
+#define SRC_CMD_LEN		(SRC_CMD_BYTES / CAAM_CMD_SZ)
+#define CHUNK_SIZE		128
+#define CHUNK_SIZE_H		64
+#define CHUNK_SIZE_Q		32
+#define REG_SIZE		8
+
+#define CMD_MOVE_OVERFLOW_LEN	1
+
+#define LABEL_SRC_JMP_BYTES	(5 * CAAM_CMD_SZ)
+#define LABEL_SRC_JMP		(LABEL_SRC_JMP_BYTES / CAAM_CMD_SZ)
+#define LABEL_SRC_MV_BYTES	(CAAM_CMD_SZ + LABEL_SRC_JMP_BYTES)
+#define LABEL_SRC_MV		(LABEL_SRC_MV_BYTES / CAAM_CMD_SZ)
+#define LABEL_FIRST_BYTES	(28 * CAAM_CMD_SZ + LABEL_SRC_MV_BYTES)
+#define LABEL_FIRST		(LABEL_FIRST_BYTES / CAAM_CMD_SZ)
+#define LABEL_LAST_BYTES	(13 * CAAM_CMD_SZ + LABEL_FIRST_BYTES)
+#define LABEL_LAST		(LABEL_LAST_BYTES / CAAM_CMD_SZ)
+#define SH_DESC_BYTES		(5 * CAAM_CMD_SZ + LABEL_LAST_BYTES)
+#define SH_DESC_LEN		(SH_DESC_BYTES / CAAM_CMD_SZ)
+
+#ifdef DEBUG
+/* for print_hex_dumps with line references */
+#define xstr(s) str(s)
+#define str(s) (#s)
+#define debug(format, arg...) printk(format, arg)
+#else
+#define debug(format, arg...)
+#endif
+
+struct caam_xor_sh_desc {
+	u32 desc[SH_DESC_LEN + CMD_MOVE_OVERFLOW_LEN];
+	dma_addr_t sh_desc_phys;
+};
+
+struct caam_dma_async_tx_desc {
+	struct dma_async_tx_descriptor async_tx;
+	struct list_head node;
+	struct caam_dma_jr *dma_jr;
+	u32 job_desc[JOB_DESC_LEN];
+	u32 cmd_desc[CMD_DESC_LEN];
+	dma_addr_t cmd_desc_phys;
+	dma_addr_t dest;
+	dma_addr_t src[MAX_XOR_SRCS];
+	u32 src_cnt;
+	u32 dma_len;
+};
+
+struct caam_dma_desc_pool {
+	int desc_cnt;
+	struct list_head head;
+};
+
+/*
+ * caam_dma_jr - job ring/channel data
+ * @completed_cookie: cookie of latest latest, completed job
+ * @chan: dma channel used by async_tx API
+ * @desc_lock: lock on job descriptor
+ * @submit_q: queue of pending (submitted, but not enqueued) jobs
+ * @done_lock: lock on done_not_acked
+ * @done_not_acked: jobs that have been completed by jr, but maybe not acked
+ * @handle_done: tasklet for cleaning done_not_acked
+ * @caam_hw_jr: jr device data
+ * @pool_lock: lock on soft_desc
+ * @soft_desc: pool of pre-allocated caam_dma_async_tx_desc structures
+ */
+struct caam_dma_jr {
+	dma_cookie_t completed_cookie;
+	struct dma_chan chan;
+	struct device *dev;
+	spinlock_t desc_lock;
+	struct list_head submit_q;
+	spinlock_t done_lock;
+	struct list_head done_not_acked;
+	struct tasklet_struct handle_done;
+	struct caam_drv_private_jr *caam_hw_jr;
+	spinlock_t pool_lock;
+	struct caam_dma_desc_pool *soft_desc;
+};
+
+static inline u32 load_source(u32 ctx, u32 offset, u32 target)
+{
+	return ctx | MOVE_DEST_DESCBUF | SRC_CMD_BYTES |
+	       (target << (2 + MOVE_OFFSET_SHIFT)) |
+	       (offset << MOVE_AUX_SHIFT);
+}
+
+static inline u32 *write_load_source(u32 *desc, u32 ctx, u32 offset, u32 target)
+{
+	return write_move(desc, load_source(ctx, offset, target));
+}
+
+/* generate source commands and job descriptor for each request */
+static void prepare_caam_xor_desc(struct device *dev,
+				  struct caam_dma_async_tx_desc *desc,
+				  dma_addr_t sh_desc_phys,
+				  dma_addr_t dest, dma_addr_t *src,
+				  u32 src_cnt, size_t len)
+{
+	u32 label_src_mv = LABEL_SRC_MV + CMD_MOVE_OVERFLOW_LEN;
+	u32 label_first = LABEL_FIRST + CMD_MOVE_OVERFLOW_LEN;
+	u32 label_last = LABEL_LAST + CMD_MOVE_OVERFLOW_LEN;
+	u32 sh_desc_len = SH_DESC_LEN + CMD_MOVE_OVERFLOW_LEN;
+	int i;
+	u32 *job_descptr = desc->job_desc;
+	u32 *cmd_desc = desc->cmd_desc;
+
+	desc->dest = dest;
+	memcpy(desc->src, src, src_cnt*sizeof(dma_addr_t));
+	desc->src_cnt = src_cnt;
+	desc->dma_len = len;
+
+	/* first source: jump to special commands */
+	cmd_desc = write_ptr(cmd_desc, src[0]);
+	cmd_desc = write_cmd(cmd_desc, len);
+	init_sh_desc(cmd_desc, (label_first & HDR_START_IDX_MASK) <<
+		      HDR_START_IDX_SHIFT);
+	cmd_desc++;
+	if (!LONG_PTR)
+		cmd_desc = write_nop(cmd_desc, 1);
+
+	i = 1;
+	/* sources that load next source from first context */
+	while (i < src_cnt - 1 && i < CTX1_SLOTS - 1) {
+		cmd_desc = write_ptr(cmd_desc, src[i]);
+		cmd_desc = write_cmd(cmd_desc, len);
+		cmd_desc = write_load_source(cmd_desc, MOVE_SRC_CLASS1CTX, i +
+					     1, label_src_mv);
+		if (!LONG_PTR)
+			cmd_desc = write_nop(cmd_desc, 1);
+		i++;
+	}
+	/* sources that load next source from second context */
+	while (i < src_cnt - 1) {
+		cmd_desc = write_ptr(cmd_desc, src[i]);
+		cmd_desc = write_cmd(cmd_desc, len);
+		cmd_desc = write_load_source(cmd_desc, MOVE_SRC_CLASS2CTX, i +
+					     1, label_src_mv);
+		if (!LONG_PTR)
+			cmd_desc = write_nop(cmd_desc, 1);
+		i++;
+	}
+
+	/* last source: jump to special commands */
+	cmd_desc = write_ptr(cmd_desc, src[i]);
+	cmd_desc = write_cmd(cmd_desc, len);
+	init_sh_desc(cmd_desc, (label_last & HDR_START_IDX_MASK) <<
+		      HDR_START_IDX_SHIFT);
+	cmd_desc++;
+	if (!LONG_PTR)
+		cmd_desc = write_nop(cmd_desc, 1);
+
+	desc->cmd_desc_phys = dma_map_single(dev, desc->cmd_desc,
+					     CMD_DESC_LEN * sizeof(u32),
+					     DMA_TO_DEVICE);
+	init_job_desc_shared(job_descptr, sh_desc_phys, sh_desc_len,
+			     HDR_SHARE_WAIT | HDR_REVERSE);
+
+	append_seq_out_ptr(job_descptr, dest, len, 0);
+	append_seq_in_ptr_intlen(job_descptr, desc->cmd_desc_phys,
+					MAX_XOR_SRCS * SRC_CMD_BYTES, 0);
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "job desc @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, job_descptr, CAAM_CMD_SZ *
+		       desc_len(job_descptr), 1);
+	print_hex_dump(KERN_ERR, "srcs @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, src, src_cnt * CAAM_PTR_SZ,
+		       1);
+	print_hex_dump(KERN_ERR, "src cmd@"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, desc->cmd_desc,
+		       SRC_CMD_BYTES * src_cnt, 1);
+#endif
+}
+
+/* generate shared descriptor for each device */
+static void prepare_caam_xor_sh_desc(u32 *descptr, u32 src_cnt)
+{
+	bool overflow;
+	u32 label_src_jmp, label_src_mv;
+	u32 *store_jump_cmd;
+	u32 label_load, label_return, label_store;
+
+	overflow = src_cnt > CTX1_SLOTS;
+	label_src_jmp = LABEL_SRC_JMP + CMD_MOVE_OVERFLOW_LEN;
+	label_src_mv = label_src_jmp + 1;
+	init_sh_desc(descptr, HDR_SHARE_SERIAL);
+	/* Store up to 4 sources in ctx1 */
+	append_cmd(descptr, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+		   LDST_CLASS_1_CCB | (overflow ?
+		   (CTX1_SLOTS * SRC_CMD_BYTES) : (src_cnt * SRC_CMD_BYTES)));
+
+	/* Store any overflow in ctx2 */
+	if (overflow)
+		append_cmd(descptr, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+			   LDST_CLASS_2_CCB | (src_cnt - 4) * 16);
+	else
+		append_cmd(descptr, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
+			   LDST_CLASS_2_CCB | 4 * 16);
+
+	append_cmd(descptr, CMD_LOAD | DISABLE_AUTO_INFO_FIFO);
+
+	/* Load first source */
+	append_move(descptr, load_source(MOVE_SRC_CLASS1CTX, 0, label_src_mv) |
+		    MOVE_WAITCOMP);
+
+	/* Refresh shared descriptor */
+	append_cmd(descptr, CMD_SHARED_DESC_HDR | HDR_SHARE_NEVER | HDR_ONE |
+		   ((label_src_jmp & HDR_START_IDX_MASK) <<
+		    HDR_START_IDX_SHIFT));
+
+	/* Load source and run loaded commands */
+	append_cmd(descptr, CMD_SEQ_IN_PTR | SQIN_EXT);
+	append_len(descptr, SRC_CMD_LEN);
+
+	/* Skip read data */
+	append_seq_fifo_load(descptr, 0, KEY_VLF | FIFOLD_CLASS_SKIP);
+
+	/* Load chunk to ififo */
+	label_load = desc_len(descptr);
+	append_seq_fifo_load(descptr, CHUNK_SIZE, FIFOLD_TYPE_PK |
+			     LDST_CLASS_1_CCB);
+
+	/* Update added number of bytes in ififo */
+	append_math_add_imm_u32(descptr, VARSEQOUTLEN, VARSEQOUTLEN, IMM,
+				CHUNK_SIZE);
+
+	/* Load chunk from ififo to math registers via DECO alignment block*/
+	append_load_imm_u32(descptr, NFIFOENTRY_LC1 | NFIFOENTRY_DTYPE_MSG |
+			    CHUNK_SIZE, LDST_SRCDST_WORD_INFO_FIFO);
+	label_return = desc_len(descptr);
+	append_move(descptr, MOVE_WAITCOMP | MOVE_SRC_INFIFO |
+		    MOVE_DEST_MATH0 | CHUNK_SIZE_Q);
+
+	/* XOR math registers with ofifo */
+	append_math_xor(descptr, REG0, REG0, OUTFIFO, REG_SIZE);
+	append_math_xor(descptr, REG1, REG1, OUTFIFO, REG_SIZE);
+	append_math_xor(descptr, REG2, REG2, OUTFIFO, REG_SIZE);
+	append_math_xor(descptr, REG3, REG3, OUTFIFO, REG_SIZE);
+
+	/* Move result to ofifo */
+	append_move(descptr, MOVE_SRC_MATH0 | MOVE_WAITCOMP |
+		    MOVE_DEST_OUTFIFO | CHUNK_SIZE_Q);
+
+	/* Update reduced number of bytes in ififo */
+	append_math_sub_imm_u32(descptr, VARSEQOUTLEN, VARSEQOUTLEN, IMM,
+				CHUNK_SIZE_Q);
+
+	/* If ififo has no more data, store chunk */
+	store_jump_cmd = append_jump(descptr, JUMP_TEST_ALL |
+				     JUMP_COND_MATH_Z);
+
+	/* If half of chunk left, use next source */
+	append_math_sub_imm_u32(descptr, NONE, VARSEQOUTLEN, IMM,
+				CHUNK_SIZE_H);
+	append_jump_to(descptr, JUMP_TEST_ALL | JUMP_COND_MATH_Z,
+		       label_src_jmp);
+
+	/* Else, keep XORing */
+	append_jump_to(descptr, 0, label_return);
+
+	/* Store */
+	label_store = desc_len(descptr);
+	set_jump_tgt_here(descptr, store_jump_cmd);
+
+	/* Store chunk to seqout */
+	append_seq_fifo_store(descptr, CHUNK_SIZE, FIFOST_TYPE_MESSAGE_DATA);
+
+	/* Halt if no more data */
+	append_math_sub(descptr, NONE, SEQOUTLEN, ONE, CAAM_CMD_SZ);
+	append_jump(descptr, JUMP_TYPE_HALT_USER | JUMP_TEST_ALL |
+			JUMP_COND_MATH_N);
+
+	/* Load first source's next chunk to ofifo */
+	append_move(descptr, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO |
+			MOVE_WAITCOMP | CHUNK_SIZE);
+
+	/* Goto source */
+	append_cmd(descptr, CMD_SHARED_DESC_HDR | HDR_SHARE_NEVER | HDR_ONE |
+		   ((label_src_jmp & HDR_START_IDX_MASK) <<
+		     HDR_START_IDX_SHIFT));
+
+	/* First source, skip read data */
+	append_seq_fifo_load(descptr, 0, KEY_VLF | FIFOLD_CLASS_SKIP);
+
+	/* If no more data to read, go XOR read data */
+	append_math_sub(descptr, NONE, SEQINLEN, ONE, CAAM_CMD_SZ);
+	append_jump_to(descptr, JUMP_TEST_ALL | JUMP_COND_MATH_N,
+		       label_return);
+
+	/* Otherwise, load chunk from first source to DECO alignment block */
+	append_seq_fifo_load(descptr, CHUNK_SIZE, FIFOLD_TYPE_PK |
+			     LDST_CLASS_1_CCB);
+	append_load_imm_u32(descptr, NFIFOENTRY_LC1 | NFIFOENTRY_DTYPE_MSG |
+			    CHUNK_SIZE, LDST_SRCDST_WORD_INFO_FIFO);
+
+	/* Load second source */
+	append_move(descptr, load_source(MOVE_SRC_CLASS1CTX, 1, label_src_mv));
+
+	/* XOR previous pass if this is not first pass */
+	append_math_sub(descptr, NONE, VARSEQINLEN, ONE, CAAM_CMD_SZ);
+	append_jump_to(descptr, JUMP_TEST_INVALL | JUMP_COND_MATH_N,
+		       label_return);
+
+	/* Else, move chunk for DECO alignment block to ofifo */
+	append_move(descptr, MOVE_SRC_INFIFO | MOVE_DEST_OUTFIFO |
+				MOVE_WAITCOMP | CHUNK_SIZE);
+
+	/* and track number of bytes to write*/
+	append_math_add_imm_u32(descptr, SEQOUTLEN, SEQINLEN, IMM, CHUNK_SIZE);
+
+	/* Goto source */
+	append_cmd(descptr, CMD_SHARED_DESC_HDR | HDR_SHARE_NEVER | HDR_ONE |
+		   ((label_src_jmp & HDR_START_IDX_MASK) <<
+		     HDR_START_IDX_SHIFT));
+
+	/* Last source, skip read data */
+	append_seq_fifo_load(descptr, 0, KEY_VLF | FIFOLD_CLASS_SKIP);
+
+	/* Update number of bytes to skip */
+	append_math_add_imm_u32(descptr, VARSEQINLEN, VARSEQINLEN, IMM,
+				CHUNK_SIZE);
+
+	/* Load first source */
+	append_move(descptr, load_source(MOVE_SRC_CLASS1CTX, 0, label_src_mv));
+
+	/* Goto data loading */
+	append_cmd(descptr, CMD_SHARED_DESC_HDR | HDR_SHARE_NEVER | HDR_ONE |
+		   ((label_load & HDR_START_IDX_MASK) << HDR_START_IDX_SHIFT));
+
+#ifdef DEBUG
+	print_hex_dump(KERN_ERR, "shdesc @"xstr(__LINE__)": ",
+		       DUMP_PREFIX_ADDRESS, 16, 4, descptr, CAAM_CMD_SZ *
+		       desc_len(descptr), 1);
+#endif
+}
+
+static enum dma_status caam_jr_tx_status(struct dma_chan *chan,
+					 dma_cookie_t cookie,
+					 struct dma_tx_state *txstate)
+{
+	struct caam_dma_jr *jr = NULL;
+	dma_cookie_t last_used;
+	dma_cookie_t last_complete;
+
+	jr = container_of(chan, struct caam_dma_jr, chan);
+
+	last_used = chan->cookie;
+	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);
+}
+
+static inline void try_clear_desc(struct caam_dma_jr *dma_jr)
+{
+	spin_lock_bh(&dma_jr->done_lock);
+	if (!list_empty(&dma_jr->done_not_acked)) {
+		spin_unlock_bh(&dma_jr->done_lock);
+		tasklet_schedule(&dma_jr->handle_done);
+	} else {
+		spin_unlock_bh(&dma_jr->done_lock);
+	}
+}
+
+/*
+ * tasklet function for checking requests that are completed,
+ * but may not have been acked --delete only if acked
+ */
+static void check_done(unsigned long data)
+{
+	struct caam_dma_jr *dma_jr = (struct caam_dma_jr *) data;
+	struct caam_dma_async_tx_desc *desc, *_desc;
+
+	spin_lock_bh(&dma_jr->done_lock);
+	list_for_each_entry_safe(desc, _desc, &dma_jr->done_not_acked, node) {
+		spin_unlock_bh(&dma_jr->done_lock);
+		if (async_tx_test_ack(&desc->async_tx)) {
+			spin_lock_bh(&dma_jr->done_lock);
+			list_del(&desc->node);
+			spin_unlock_bh(&dma_jr->done_lock);
+			spin_lock_bh(&dma_jr->pool_lock);
+			if (dma_jr->soft_desc->desc_cnt < MAX_INITIAL_DESCS) {
+				INIT_LIST_HEAD(&desc->node);
+				list_add(&desc->node, &dma_jr->soft_desc->head);
+				dma_jr->soft_desc->desc_cnt++;
+				spin_unlock_bh(&dma_jr->pool_lock);
+			} else {
+				spin_unlock_bh(&dma_jr->pool_lock);
+				kfree(desc);
+			}
+		}
+		spin_lock_bh(&dma_jr->done_lock);
+	}
+	spin_unlock_bh(&dma_jr->done_lock);
+}
+
+static void caam_dma_xor_done(struct device *dev, u32 *hwdesc, u32 status,
+			      void *auxarg)
+{
+	struct caam_dma_async_tx_desc *desc;
+	struct caam_dma_jr *dma_jr;
+	dma_async_tx_callback callback;
+	void *callback_param;
+	struct device *jrdev;
+	enum dma_ctrl_flags flags;
+
+	desc = (struct caam_dma_async_tx_desc *)auxarg;
+	dma_jr = desc->dma_jr;
+	jrdev = dma_jr->caam_hw_jr->parentdev;
+	flags = desc->async_tx.flags;
+
+	if (status) {
+		char tmp[256];
+		dev_err(dev, "%s\n", caam_jr_strstatus(tmp, status));
+	}
+
+	dma_run_dependencies(&desc->async_tx);
+
+	spin_lock_bh(&dma_jr->desc_lock);
+	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;
+	}
+	spin_unlock_bh(&dma_jr->desc_lock);
+
+	callback = desc->async_tx.callback;
+	callback_param = desc->async_tx.callback_param;
+
+	dma_unmap_single(jrdev, desc->cmd_desc_phys,
+			CMD_DESC_LEN * sizeof(u32), DMA_TO_DEVICE);
+
+	if (likely(!(flags & DMA_COMPL_SKIP_DEST_UNMAP)))
+		dma_unmap_page(jrdev, desc->dest, desc->dma_len,
+						DMA_BIDIRECTIONAL);
+
+	if (likely(!(flags & DMA_COMPL_SKIP_SRC_UNMAP))) {
+		u32 i;
+		for (i = 0; i < desc->src_cnt; i++) {
+			if (desc->src[i] == desc->dest)
+				continue;
+			dma_unmap_page(jrdev, desc->src[i],
+					desc->dma_len, DMA_TO_DEVICE);
+		}
+	}
+
+	if (async_tx_test_ack(&desc->async_tx)) {
+		spin_lock_bh(&dma_jr->pool_lock);
+		if (dma_jr->soft_desc->desc_cnt < MAX_INITIAL_DESCS) {
+			list_add(&desc->node, &dma_jr->soft_desc->head);
+			dma_jr->soft_desc->desc_cnt++;
+			spin_unlock_bh(&dma_jr->pool_lock);
+		} else {
+			spin_unlock_bh(&dma_jr->pool_lock);
+			kfree(desc);
+		}
+	} else {
+		spin_lock_bh(&dma_jr->done_lock);
+		INIT_LIST_HEAD(&desc->node);
+		list_add_tail(&desc->node, &dma_jr->done_not_acked);
+		spin_unlock_bh(&dma_jr->done_lock);
+	}
+	try_clear_desc(dma_jr);
+
+	if (callback)
+		callback(callback_param);
+}
+
+static void caam_jr_issue_pending(struct dma_chan *chan)
+{
+	struct caam_dma_jr *dma_jr = NULL;
+	struct caam_dma_async_tx_desc *desc, *_desc;
+	struct device *dev;
+
+	dma_jr = container_of(chan, struct caam_dma_jr, chan);
+	dev = dma_jr->dev;
+
+	spin_lock_bh(&dma_jr->desc_lock);
+	list_for_each_entry_safe(desc, _desc, &dma_jr->submit_q, node) {
+		desc->dma_jr = dma_jr;
+		if (caam_jr_enqueue(dev, desc->job_desc,
+				    caam_dma_xor_done, desc) < 0) {
+			spin_unlock_bh(&dma_jr->desc_lock);
+			return;
+		}
+
+		list_del(&desc->node);
+	}
+
+	spin_unlock_bh(&dma_jr->desc_lock);
+}
+
+static dma_cookie_t caam_jr_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct caam_dma_async_tx_desc *desc = NULL;
+	struct caam_dma_jr *jr = NULL;
+	dma_cookie_t cookie;
+
+	desc = container_of(tx, struct caam_dma_async_tx_desc, async_tx);
+	jr = container_of(tx->chan, struct caam_dma_jr, chan);
+
+	spin_lock_bh(&jr->desc_lock);
+
+	cookie = jr->chan.cookie + 1;
+	if (cookie < DMA_MIN_COOKIE)
+		cookie = DMA_MIN_COOKIE;
+
+	desc->async_tx.cookie = cookie;
+	jr->chan.cookie = desc->async_tx.cookie;
+	list_add_tail(&desc->node, &jr->submit_q);
+
+	spin_unlock_bh(&jr->desc_lock);
+
+	return cookie;
+}
+
+static struct dma_async_tx_descriptor *
+caam_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)
+{
+	struct caam_dma_jr *jr = NULL;
+	struct caam_dma_async_tx_desc *desc = NULL;
+	struct caam_drv_private *priv;
+
+	jr = container_of(chan, struct caam_dma_jr, chan);
+
+	if (src_cnt > MAX_XOR_SRCS) {
+		dev_err(jr->dev, "%d srcs exceed max supported %d srcs\n",
+							src_cnt, MAX_XOR_SRCS);
+		return NULL;
+	}
+
+	spin_lock_bh(&jr->pool_lock);
+	if (jr->soft_desc->desc_cnt) {
+		desc = container_of(jr->soft_desc->head.next,
+				    struct caam_dma_async_tx_desc, node);
+		jr->soft_desc->desc_cnt--;
+		list_del(&desc->node);
+	}
+	spin_unlock_bh(&jr->pool_lock);
+
+	if (!desc) {
+		desc = kzalloc(sizeof(struct caam_dma_async_tx_desc),
+			       GFP_KERNEL);
+		if (!desc) {
+			dev_err(jr->dev, "Out of memory for XOR async tx\n");
+			try_clear_desc(jr);
+
+			return ERR_PTR(-ENOMEM);
+		}
+
+		desc->async_tx.tx_submit = caam_jr_tx_submit;
+	}
+
+	dma_async_tx_descriptor_init(&desc->async_tx, &jr->chan);
+
+	priv = dev_get_drvdata(jr->caam_hw_jr->parentdev);
+
+	prepare_caam_xor_desc(jr->caam_hw_jr->parentdev, desc,
+			      priv->xor_sh_desc[0].sh_desc_phys, dest,
+			      src, src_cnt, len);
+
+	desc->async_tx.flags = flags;
+	desc->async_tx.cookie = -EBUSY;
+	return &desc->async_tx;
+}
+
+static void caam_jr_free_chan_resources(struct dma_chan *chan)
+{
+	struct caam_dma_jr *jr = container_of(chan, struct caam_dma_jr, chan);
+	struct caam_dma_async_tx_desc *desc;
+	struct list_head *current_node;
+
+	current_node = jr->soft_desc->head.next;
+	while (jr->soft_desc->desc_cnt > 0) {
+		desc = container_of(current_node, struct caam_dma_async_tx_desc,
+				    node);
+		current_node = current_node->next;
+		list_del(&desc->node);
+		kfree(desc);
+		jr->soft_desc->desc_cnt--;
+	}
+
+	kfree(jr->soft_desc);
+
+	return;
+}
+
+static int caam_jr_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct caam_dma_jr *jr = container_of(chan, struct caam_dma_jr, chan);
+	struct caam_dma_async_tx_desc *desc;
+	unsigned int i;
+
+	jr->soft_desc = kzalloc(sizeof(struct caam_dma_desc_pool), GFP_KERNEL);
+	if (!jr->soft_desc) {
+		pr_err("%s: Failed to allocate resources for DMA channel\n",
+		       __func__);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&jr->soft_desc->head);
+	for (i = 0; i < MAX_INITIAL_DESCS; i++) {
+		desc = kzalloc(sizeof(struct caam_dma_async_tx_desc),
+			       GFP_KERNEL);
+		if (!desc)
+			return -ENOMEM;
+
+		desc->async_tx.tx_submit = caam_jr_tx_submit;
+		jr->soft_desc->desc_cnt++;
+		list_add_tail(&desc->node, &jr->soft_desc->head);
+	}
+
+	return 0;
+}
+
+static int caam_jr_chan_bind(struct device *ctrldev, struct device *dev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	struct caam_drv_private_jr *jrpriv = dev_get_drvdata(dev);
+	struct dma_device *dma_dev = &priv->dma_dev;
+	struct caam_dma_jr *dma_jr;
+
+	dma_jr = kzalloc(sizeof(struct caam_dma_jr), GFP_KERNEL);
+	if (!dma_jr) {
+		dev_err(dev, "Failed to allocate memory for caam job queue\n");
+		return -ENOMEM;
+	}
+
+	dma_jr->chan.device = dma_dev;
+	dma_jr->chan.private = dma_jr;
+
+	INIT_LIST_HEAD(&dma_jr->submit_q);
+	spin_lock_init(&dma_jr->desc_lock);
+	spin_lock_init(&dma_jr->pool_lock);
+	list_add_tail(&dma_jr->chan.device_node, &dma_dev->channels);
+	dma_dev->chancnt++;
+
+	dma_jr->caam_hw_jr = jrpriv;
+	dma_jr->dev = dev;
+	jrpriv->jrdev = dev;
+
+	INIT_LIST_HEAD(&dma_jr->done_not_acked);
+	spin_lock_init(&dma_jr->done_lock);
+	tasklet_init(&dma_jr->handle_done, check_done, (unsigned long) dma_jr);
+
+	return 0;
+}
+
+static inline void caam_jr_chan_unbind(struct device *ctrldev,
+				       struct dma_chan *chan)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	struct dma_device *dma_dev = &priv->dma_dev;
+
+	list_del(&chan->device_node);
+	dma_dev->chancnt--;
+}
+
+static inline void caam_jr_free(struct dma_chan *chan)
+{
+	struct caam_dma_jr *dma_jr = container_of(chan, struct caam_dma_jr,
+						  chan);
+
+	list_del(&chan->device_node);
+	kfree(dma_jr);
+}
+
+static int caam_jr_dma_init(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	struct dma_device *dma_dev = NULL;
+	struct caam_xor_sh_desc *sh_desc;
+	int i;
+
+	priv->xor_sh_desc =
+	    kzalloc(sizeof(struct caam_xor_sh_desc), GFP_KERNEL);
+	if (!priv->xor_sh_desc) {
+		dev_err(ctrldev,
+			"Failed to allocate memory for XOR Shared"
+			"descriptor\n");
+		return -ENOMEM;
+	}
+
+	sh_desc = priv->xor_sh_desc;
+	prepare_caam_xor_sh_desc(sh_desc->desc, MAX_XOR_SRCS);
+	sh_desc->sh_desc_phys = dma_map_single(ctrldev, &sh_desc->desc,
+						SH_DESC_LEN * sizeof(u32),
+						DMA_TO_DEVICE);
+
+	dma_dev = &priv->dma_dev;
+	dma_dev->dev = ctrldev;
+	INIT_LIST_HEAD(&dma_dev->channels);
+
+	dma_dev->max_xor = MAX_XOR_SRCS;
+
+	/*
+	 * xor transaction must be 128 bytes aligned. For unaligned
+	 * transaction, xor-parity calculations will not be off-loaded
+	 * to caam
+	 */
+	dma_dev->xor_align = 8;
+	dma_cap_set(DMA_XOR, dma_dev->cap_mask);
+
+	dma_dev->device_alloc_chan_resources = caam_jr_alloc_chan_resources;
+	dma_dev->device_tx_status = caam_jr_tx_status;
+	dma_dev->device_issue_pending = caam_jr_issue_pending;
+	dma_dev->device_prep_dma_xor = caam_jr_prep_dma_xor;
+	dma_dev->device_free_chan_resources = caam_jr_free_chan_resources;
+
+	for (i = 0; i < priv->total_jobrs; i++)
+		caam_jr_chan_bind(ctrldev, priv->jrdev[i]);
+
+	dma_async_device_register(dma_dev);
+	dev_info(ctrldev, "caam xor support with %d job rings\n",
+		 priv->total_jobrs);
+
+	return 0;
+}
+
+static void caam_jr_dma_exit(struct device *ctrldev)
+{
+	struct caam_drv_private *priv = dev_get_drvdata(ctrldev);
+	struct dma_device *dma_dev = &priv->dma_dev;
+	struct dma_chan *chan, *_chan;
+	struct list_head to_free;
+	int i;
+
+	i = 0;
+	INIT_LIST_HEAD(&to_free);
+	/* before unregistering device, remove channels... */
+	list_for_each_entry_safe(chan, _chan, &dma_dev->channels, device_node) {
+		caam_jr_chan_unbind(ctrldev, chan);
+		list_add_tail(&chan->device_node, &to_free);
+		i++;
+	}
+
+	dma_async_device_unregister(dma_dev);
+
+	/*
+	 * ...but don't delete them until device has been unregistered, so
+	 * that deleted channels will not be used
+	 */
+	list_for_each_entry_safe(chan, _chan, &to_free, device_node) {
+		caam_jr_free(chan);
+	}
+
+	for (i = 0; i < (MAX_XOR_SRCS - 2); i++) {
+		dma_unmap_single(ctrldev, priv->xor_sh_desc[i].sh_desc_phys,
+				 SH_DESC_LEN * sizeof(u32), DMA_TO_DEVICE);
+	}
+
+	kfree(priv->xor_sh_desc);
+	dev_info(ctrldev, "caam xor support disabled\n");
+}
+
+static int __init caam_xor_init(void)
+{
+	struct device_node *dev_node;
+	struct platform_device *pdev;
+	struct device *ctrldev;
+	struct caam_drv_private *priv;
+	int err = 0;
+
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node)
+		return -ENODEV;
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev)
+		return -ENODEV;
+
+	ctrldev = &pdev->dev;
+	priv = dev_get_drvdata(ctrldev);
+	of_node_put(dev_node);
+
+	atomic_set(&priv->tfm_count, -1);
+
+	/* register caam device */
+	err = caam_jr_dma_init(ctrldev);
+	if (err)
+		dev_err(ctrldev, "error in xor initialization: %d\n", err);
+
+	return err;
+}
+
+static void __exit caam_xor_exit(void)
+{
+	struct device_node *dev_node;
+	struct platform_device *pdev;
+	struct device *ctrldev;
+	struct caam_drv_private *priv;
+
+	dev_node = of_find_compatible_node(NULL, NULL, "fsl,sec-v4.0");
+	if (!dev_node)
+		return;
+
+	pdev = of_find_device_by_node(dev_node);
+	if (!pdev)
+		return;
+
+	ctrldev = &pdev->dev;
+	of_node_put(dev_node);
+	priv = dev_get_drvdata(ctrldev);
+
+	caam_jr_dma_exit(ctrldev);
+}
+
+module_init(caam_xor_init);
+module_exit(caam_xor_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("FSL CAAM support for crypto API");
+MODULE_AUTHOR("Freescale Semiconductor - NMG/STC");
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index c85c1f0..d06bf68 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -9,11 +9,13 @@
 #define IMMEDIATE (1 << 23)
 #define CAAM_CMD_SZ sizeof(u32)
 #define CAAM_PTR_SZ sizeof(dma_addr_t)
+#define CAAM_PTR_LEN (CAAM_PTR_SZ / CAAM_CMD_SZ)
 #define CAAM_DESC_BYTES_MAX (CAAM_CMD_SZ * MAX_CAAM_DESCSIZE)
 
 #ifdef DEBUG
-#define PRINT_POS do { printk(KERN_DEBUG "%02d: %s\n", desc_len(desc),\
-			      &__func__[sizeof("append")]); } while (0)
+#define PRINT_POS do { pr_debug("%02d: %s\n", desc_len(desc),\
+				&__func__[sizeof("append")]);\
+		} while (0)
 #else
 #define PRINT_POS
 #endif
@@ -82,6 +84,20 @@ static inline void append_ptr(u32 *desc, dma_addr_t ptr)
 	(*desc) += CAAM_PTR_SZ / CAAM_CMD_SZ;
 }
 
+/* Write command without affecting header, and return pointer to next word */
+static inline u32 *write_ptr(u32 *desc, dma_addr_t ptr)
+{
+	memcpy(desc, &ptr, CAAM_PTR_SZ);
+
+	return desc + CAAM_PTR_LEN;
+}
+
+/* Increase descriptor length */
+static inline void append_len(u32 *desc, unsigned int len)
+{
+	(*desc) += len;
+}
+
 static inline void init_job_desc_shared(u32 *desc, dma_addr_t ptr, int len,
 					u32 options)
 {
@@ -110,6 +126,14 @@ static inline void append_cmd(u32 *desc, u32 command)
 	(*desc)++;
 }
 
+/* Write command without affecting header, and return pointer to next word */
+static inline u32 *write_cmd(u32 *desc, u32 command)
+{
+	*desc = command;
+
+	return desc + 1;
+}
+
 static inline void append_cmd_ptr(u32 *desc, dma_addr_t ptr, int len,
 				  u32 command)
 {
@@ -143,11 +167,28 @@ static inline u32 *append_jump(u32 *desc, u32 options)
 	return cmd;
 }
 
+/* Given destination, as offset from header, append jump */
+static inline void append_jump_to(u32 *desc, u32 options, u32 target)
+{
+	PRINT_POS;
+
+	append_jump(desc, options | ((target - desc_len(desc)) &
+		    JUMP_OFFSET_MASK));
+}
+
 static inline void set_jump_tgt_here(u32 *desc, u32 *jump_cmd)
 {
 	*jump_cmd = *jump_cmd | (desc_len(desc) - (jump_cmd - desc));
 }
 
+/* len words have no commands */
+static inline u32 *write_nop(u32 *desc, int len)
+{
+	*desc = CMD_JUMP | len;
+
+	return desc + len;
+}
+
 #define APPEND_CMD(cmd, op) \
 static inline void append_##cmd(u32 *desc, u32 options) \
 { \
@@ -157,6 +198,14 @@ static inline void append_##cmd(u32 *desc, u32 options) \
 APPEND_CMD(operation, OPERATION)
 APPEND_CMD(move, MOVE)
 
+#define WRITE_CMD(cmd, op) \
+static inline u32 *write_##cmd(u32 *desc, u32 options) \
+{ \
+	PRINT_POS; \
+	return write_cmd(desc, CMD_##op | options); \
+}
+WRITE_CMD(move, MOVE)
+
 #define APPEND_CMD_LEN(cmd, op) \
 static inline void append_##cmd(u32 *desc, unsigned int len, u32 options) \
 { \
diff --git a/drivers/crypto/caam/intern.h b/drivers/crypto/caam/intern.h
index 5cd4c1b..2b41e31 100644
--- a/drivers/crypto/caam/intern.h
+++ b/drivers/crypto/caam/intern.h
@@ -26,6 +26,8 @@
 #define JOBR_INTC_COUNT_THLD 0
 #endif
 
+#define CAAM_NAPI_WEIGHT	63
+
 /*
  * Storage for tracking each in-process entry moving across a ring
  * Each entry on an output ring needs one of these
@@ -58,6 +60,7 @@ struct caam_drv_private_jr {
 	int out_ring_read_index;	/* Output index "tail" */
 	int tail;			/* entinfo (s/w ring) tail index */
 	struct jr_outentry *outring;	/* Base of output ring, DMA-safe */
+	struct device *jrdev;
 };
 
 /*
@@ -91,6 +94,10 @@ struct caam_drv_private {
 	/* list of registered hash algorithms (mk generic context handle?) */
 	struct list_head hash_list;
 
+	/* For DMA-XOR support */
+	struct dma_device dma_dev;
+	struct caam_xor_sh_desc *xor_sh_desc;
+
 	/*
 	 * debugfs entries for developer view into driver/device
 	 * variables at runtime.
diff --git a/drivers/crypto/caam/jr.c b/drivers/crypto/caam/jr.c
index 53c8c51..8dc81cf 100644
--- a/drivers/crypto/caam/jr.c
+++ b/drivers/crypto/caam/jr.c
@@ -80,8 +80,8 @@ static void caam_jr_dequeue(unsigned long devarg)
 		/* we should never fail to find a matching descriptor */
 		BUG_ON(CIRC_CNT(head, tail + i, JOBR_DEPTH) <= 0);
 
-		/* Unmap just-run descriptor so we can post-process */
-		dma_unmap_single(dev, jrp->outring[hw_idx].desc,
+		/* Unmap just-run job descriptor so we can post-process */
+		dma_unmap_single(jrp->jrdev, jrp->outring[hw_idx].desc,
 				 jrp->entinfo[sw_idx].desc_size,
 				 DMA_TO_DEVICE);
 
@@ -230,7 +230,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
 	dma_addr_t desc_dma;
 
 	desc_size = (*desc & HDR_JD_LENGTH_MASK) * sizeof(u32);
-	desc_dma = dma_map_single(dev, desc, desc_size, DMA_TO_DEVICE);
+	desc_dma = dma_map_single(jrp->jrdev, desc, desc_size, DMA_TO_DEVICE);
 	if (dma_mapping_error(dev, desc_dma)) {
 		dev_err(dev, "caam_jr_enqueue(): can't map jobdesc\n");
 		return -EIO;
@@ -466,6 +466,8 @@ int caam_jr_probe(struct platform_device *pdev, struct device_node *np,
 	else
 		dma_set_mask(jrdev, DMA_BIT_MASK(32));
 
+	jrpriv->jrdev = jrdev;
+
 	/* Identify the interrupt */
 	jrpriv->irq = of_irq_to_resource(np, 0, NULL);
 
-- 
1.7.0.4

^ permalink raw reply related

* RE: [PATCH V8] powerpc/fsl-pci: Unify pci/pcie initialization code
From: Jia Hongtao-B38951 @ 2012-08-22  7:41 UTC (permalink / raw)
  To: Wood Scott-B07421, galak@kernel.crashing.org
  Cc: linuxppc-dev@lists.ozlabs.org, Li Yang-R58472, Bradley Hughes
In-Reply-To: <5032B455.3080607@freescale.com>

DQoNCj4gLS0tLS1PcmlnaW5hbCBNZXNzYWdlLS0tLS0NCj4gRnJvbTogV29vZCBTY290dC1CMDc0
MjENCj4gU2VudDogVHVlc2RheSwgQXVndXN0IDIxLCAyMDEyIDY6MDQgQU0NCj4gVG86IEppYSBI
b25ndGFvLUIzODk1MQ0KPiBDYzogbGludXhwcGMtZGV2QGxpc3RzLm96bGFicy5vcmc7IGdhbGFr
QGtlcm5lbC5jcmFzaGluZy5vcmc7IExpIFlhbmctDQo+IFI1ODQ3MjsgQnJhZGxleSBIdWdoZXMN
Cj4gU3ViamVjdDogUmU6IFtQQVRDSCBWOF0gcG93ZXJwYy9mc2wtcGNpOiBVbmlmeSBwY2kvcGNp
ZSBpbml0aWFsaXphdGlvbg0KPiBjb2RlDQo+IA0KPiBPbiAwOC8yMC8yMDEyIDA1OjA2IEFNLCBK
aWEgSG9uZ3RhbyB3cm90ZToNCj4gPiBXZSB1bmlmaWVkIHRoZSBGcmVlc2NhbGUgcGNpL3BjaWUg
aW5pdGlhbGl6YXRpb24gYnkgY2hhbmdpbmcgdGhlDQo+ID4gZnNsX3BjaSB0byBhIHBsYXRmb3Jt
IGRyaXZlci4gSW4gcHJldmlvdXMgUENJIGNvZGUgYXJjaGl0ZWN0dXJlIHRoZQ0KPiA+IGluaXRp
YWxpemF0aW9uIHJvdXRpbmUgaXMgY2FsbGVkIGF0IGJvYXJkX3NldHVwX2FyY2ggc3RhZ2UuIE5v
dyB0aGUNCj4gPiBpbml0aWFsaXphdGlvbiBpcyBkb25lIGluIHByb2JlIGZ1bmN0aW9uIHdoaWNo
IGlzIGFyY2hpdGVjdHVyYWwNCj4gPiBiZXR0ZXIuIEFsc28gSXQncyBjb252ZW5pZW50IGZvciBh
ZGRpbmcgUE0gc3VwcG9ydCBmb3IgUENJIGNvbnRyb2xsZXINCj4gaW4gbGF0ZXIgcGF0Y2guDQo+
ID4NCj4gPiBOb3cgd2UgcmVnaXN0ZXJlZCBwY2kgY29udHJvbGxlcnMgYXMgcGxhdGZvcm0gZGV2
aWNlcy4gU28gd2UgY29tYmluZQ0KPiA+IHR3byBpbml0aWFsaXphdGlvbiBjb2RlIGFzIG9uZSBw
bGF0Zm9ybSBkcml2ZXIuDQo+ID4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBKaWEgSG9uZ3RhbyA8QjM4
OTUxQGZyZWVzY2FsZS5jb20+DQo+ID4gU2lnbmVkLW9mZi1ieTogTGkgWWFuZyA8bGVvbGlAZnJl
ZXNjYWxlLmNvbT4NCj4gPiBTaWduZWQtb2ZmLWJ5OiBDaHVuaGUgTGFuIDxDaHVuaGUuTGFuQGZy
ZWVzY2FsZS5jb20+DQo+ID4gLS0tDQo+ID4gQ2hhbmdlcyBmb3IgVjg6DQo+ID4gKiBVc2UgcHJl
dmlvdXMgcHJpbWFyeSBkZXRlcm1pbmF0aW9uLiBCYXNlZCBvbiB0aGUgcG9pbnQgdGhhdCB0aGVy
ZSBhcmUNCj4gPiAgIGJ1Z3Mgb24gcHJpbWFyeS1sZXNzIHN5c3RlbS4NCj4gPiAqIEFkZCBleGNl
cHRpb25hbCBzdXBwb3J0IG9uIGdlX2ltcDNhIGluIHdoaWNoIHRoZSBwcmltYXJ5IGJ1cyBpcyBu
b3QNCj4gdGhlDQo+ID4gICBmaXJzdCBwY2kgYnVzIGRldGVjdGVkLg0KPiANCj4gVGhlIGV4Y2Vw
dGlvbmFsIHRoaW5nIGFib3V0IGdlX2ltcDNhIGlzIHRoYXQgaXQgaGFzIG5vIGlzYSBub2RlLCBi
dXQNCj4gd2UncmUgbm90IHN1cmUgaWYgaXQgYWN0dWFsbHkgaGFzIGlzYSBvciBub3QuICBXZSBz
aG91bGQgbm90IGJlIHJlbHlpbmcNCj4gb24gcHJvYmUgb3JkZXIgaW4gYW55IGNhc2UuICBEZXZp
Y2UgdHJlZSBub2RlcyBhcmUgbm90IG9yZGVyZWQuDQo+IA0KPiBBbm90aGVyIGludGVyZXN0aW5n
IGNhc2UgaXMgc3R4c3NhODU1NS5kdHMsIHdoaWNoIGhhcyBhbiBpODI1OSBub2RlIGJ1dA0KPiBu
byBJU0Egbm9kZSAoYXJlIHRoZXJlIGFueSBvdGhlciBpbnN0YW5jZXMgb2YgdGhpcz8pLiAgSG93
ZXZlciwgSSBjYW4ndA0KPiB0ZWxsIGlmIHN0eF9ncDMuYyBpcyB0aGUgcGxhdGZvcm0gZmlsZSB0
aGF0IGdvZXMgd2l0aCB0aGlzIGRldmljZSB0cmVlLA0KPiBvciBpZiB0aGUgcGxhdGZvcm0gY29k
ZSBmb3Igc3R4c3NhODU1NSBpcyBvdXQtb2YtdHJlZSAob3Igc29tZSBvdGhlciBmaWxlDQo+IHRo
YXQgSSdtIG5vdCBzZWVpbmcpLg0KPiANCg0KSGkgU2NvdHQgYW5kIEt1bWFyOg0KDQpPYnZpb3Vz
bHkgc3R4X2dwM184NTYwLmR0cyB3aXRob3V0IGlzYSBvciBpODI1OSBub2RlIGdvZXMgd2l0aCB0
aGUgZmlsZQ0Kc3R4X2dwMy5jLiBCdXQgSSdtIG5vdCBzdXJlIHRoZSBib2FyZCBoYXMgSVNBIGJy
aWRnZSBvciBub3QuDQoNCg0KPiA+IC12b2lkIF9fZGV2aW5pdCBmc2xfcGNpX2luaXQodm9pZCkN
Cj4gPiArdm9pZCBmc2xfcGNpX2Fzc2lnbl9wcmltYXJ5KHZvaWQpDQo+ID4gIHsNCj4gPiAtCWlu
dCByZXQ7DQo+ID4gIAlzdHJ1Y3QgZGV2aWNlX25vZGUgKm5vZGU7DQo+ID4gLQlzdHJ1Y3QgcGNp
X2NvbnRyb2xsZXIgKmhvc2U7DQo+ID4gLQlkbWFfYWRkcl90IG1heCA9IDB4ZmZmZmZmZmY7DQo+
ID4NCj4gPiAgCS8qIENhbGxlcnMgY2FuIHNwZWNpZnkgdGhlIHByaW1hcnkgYnVzIHVzaW5nIG90
aGVyIG1lYW5zLiAqLw0KPiA+ICAJaWYgKCFmc2xfcGNpX3ByaW1hcnkpIHsNCj4gDQo+IFNpbmNl
IHRoZSB3aG9sZSBwb2ludCBvZiB0aGlzIGZ1bmN0aW9uIGlzIG5vdyB0byBmaW5kIHRoZSBwcmlt
YXJ5LCBqdXN0DQo+IHJldHVybiBpZiBpdCdzIGFscmVhZHkgc2V0LCBpbnN0ZWFkIG9mIGluZGVu
dGluZyB0aGUgcmVzdCBvZiB0aGUgZnVuY3Rpb24uDQo+IA0KPiA+IEBAIC04NDIsMzggKzgzOSw2
MCBAQCB2b2lkIF9fZGV2aW5pdCBmc2xfcGNpX2luaXQodm9pZCkNCj4gPiAgCQkJbm9kZSA9IGZz
bF9wY2lfcHJpbWFyeTsNCj4gPg0KPiA+ICAJCQlpZiAob2ZfbWF0Y2hfbm9kZShwY2lfaWRzLCBu
b2RlKSkNCj4gPiAtCQkJCWJyZWFrOw0KPiA+ICsJCQkJcmV0dXJuOw0KPiA+ICAJCX0NCj4gPiAt
CX0NCj4gPg0KPiA+IC0Jbm9kZSA9IE5VTEw7DQo+ID4gLQlmb3JfZWFjaF9ub2RlX2J5X3R5cGUo
bm9kZSwgInBjaSIpIHsNCj4gPiAtCQlpZiAob2ZfbWF0Y2hfbm9kZShwY2lfaWRzLCBub2RlKSkg
ew0KPiA+ICsJCW5vZGUgPSBvZl9maW5kX25vZGVfYnlfdHlwZShOVUxMLCAicGNpIik7DQo+ID4g
KwkJaWYgKG9mX21hdGNoX25vZGUocGNpX2lkcywgbm9kZSkpDQo+ID4NCj4gDQo+IFdoYXQgaWYg
dGhlIG5vZGUgcmV0dXJuZWQgZG9lc24ndCBtYXRjaD8gIElmIHlvdSdyZSBjaGVja2luZyBmb3Ig
dGhpcywNCj4gaGFuZGxlIHRoZSBlbHNlLWNhc2UgKGV2ZW4gaWYganVzdCB3aXRoIGFuIGVycm9y
IG1lc3NhZ2UpLg0KPiANCj4gLVNjb3R0DQoNCg==

^ 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