LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [Powerpc/SLQB] Next June 06 : BUG during scsi initialization
From: Nick Piggin @ 2009-06-09 14:19 UTC (permalink / raw)
  To: Sachin Sant; +Cc: Stephen Rothwell, Pekka J Enberg, linux-next, linuxppc-dev
In-Reply-To: <4A2D001E.5060802@in.ibm.com>

On Mon, Jun 08, 2009 at 05:42:14PM +0530, Sachin Sant wrote:
> Pekka J Enberg wrote:
> >Hi Sachin,
> __slab_alloc_page: nid=2, cache_node=c0000000de01ba00, cache_list=c0000000de01ba00
> __slab_alloc_page: nid=2, cache_node=c0000000de01bd00, cache_list=c0000000de01bd00
> __slab_alloc_page: nid=2, cache_node=c0000000de01ba00, cache_lisBUG: spinlock bad magic on CPU#1, modprobe/62
>  lock: c0000000008c4280, .magic: 7dcc61f0, .owner:  || status == __GCONV_INCOMPLETE_INPUT || status == __GCONV_FULL_OUTPUT/724596736, .owner_cpu: 4095
> Call Trace:
> [c0000000c7da36d0] [c0000000000116e0] .show_stack+0x6c/0x16c (unreliable)
> [c0000000c7da3780] [c000000000365bcc] .spin_bug+0xb0/0xd4
> [c0000000c7da3810] [c000000000365e94] ._raw_spin_lock+0x48/0x184
> [c0000000c7da38b0] [c0000000005de4f8] ._spin_lock+0x10/0x24
> [c0000000c7da3920] [c000000000141240] .__slab_alloc_page+0x410/0x4b4
> [c0000000c7da39e0] [c000000000142804] .kmem_cache_alloc+0x13c/0x21c
> [c0000000c7da3aa0] [c0000000001431dc] .kmem_cache_create+0x294/0x2a8
> [c0000000c7da3b90] [d000000000ea1438] .scsi_init_queue+0x38/0x170 [scsi_mod]
> [c0000000c7da3c20] [d000000000ea1334] .init_scsi+0x1c/0xe8 [scsi_mod]
> [c0000000c7da3ca0] [c0000000000092c0] .do_one_initcall+0x80/0x19c
> [c0000000c7da3d90] [c0000000000c09c8] .SyS_init_module+0xe0/0x244
> [c0000000c7da3e30] [c000000000008534] syscall_exit+0x0/0x40

I can't really work it out. It seems to be the kmem_cache_cache which has
a problem, but there have already been lots of caches created and even
this samw cache_node already used right beforehand with no problem.

Unless a CPU or node comes up or something right at this point or the
caller is scheduled onto a different CPU... oopses seem to all
have CPU#1, wheras boot CPU is probably #0 (these CPUs are node 0
and memory is only on node 1 and 2 where there are no CPUs if I read
correctly).

I still can't see the reason for the failure, but can you try this
patch please and show dmesg?

---
 mm/slqb.c |   34 +++++++++++++++++++++++++++++++---
 1 file changed, 31 insertions(+), 3 deletions(-)

Index: linux-2.6/mm/slqb.c
===================================================================
--- linux-2.6.orig/mm/slqb.c
+++ linux-2.6/mm/slqb.c
@@ -963,6 +963,7 @@ static struct slqb_page *allocate_slab(s
 
 	flags |= s->allocflags;
 
+	flags &= ~0x2000;
 	page = (struct slqb_page *)alloc_pages_node(node, flags, s->order);
 	if (!page)
 		return NULL;
@@ -1357,6 +1358,8 @@ static noinline void *__slab_alloc_page(
 	unsigned int colour;
 	void *object;
 
+	if (gfpflags & 0x2000)
+		printk("SLQB: __slab_alloc_page cpu=%d request node=%d\n", smp_processor_id(), node);
 	c = get_cpu_slab(s, smp_processor_id());
 	colour = c->colour_next;
 	c->colour_next += s->colour_off;
@@ -1374,6 +1377,8 @@ static noinline void *__slab_alloc_page(
 	if (unlikely(!page))
 		return page;
 
+	if (gfpflags & 0x2000)
+		printk("SLQB: __slab_alloc_page cpu=%d,nid=%d request node=%d page node=%d\n", smp_processor_id(), numa_node_id(), node, slqb_page_to_nid(page));
 	if (!NUMA_BUILD || likely(slqb_page_to_nid(page) == numa_node_id())) {
 		struct kmem_cache_cpu *c;
 		int cpu = smp_processor_id();
@@ -1382,6 +1387,7 @@ static noinline void *__slab_alloc_page(
 		l = &c->list;
 		page->list = l;
 
+		printk("SLQB: __slab_alloc_page spin_lock(%p)\n", &l->page_lock);
 		spin_lock(&l->page_lock);
 		l->nr_slabs++;
 		l->nr_partial++;
@@ -1398,6 +1404,8 @@ static noinline void *__slab_alloc_page(
 		l = &n->list;
 		page->list = l;
 
+		printk("SLQB: __slab_alloc_page spin_lock(%p)\n", &n->list_lock);
+		printk("SLQB: __slab_alloc_page spin_lock(%p)\n", &l->page_lock);
 		spin_lock(&n->list_lock);
 		spin_lock(&l->page_lock);
 		l->nr_slabs++;
@@ -1411,6 +1419,7 @@ static noinline void *__slab_alloc_page(
 #endif
 	}
 	VM_BUG_ON(!object);
+	printk("SLQB: __slab_alloc_page OK\n");
 	return object;
 }
 
@@ -1440,6 +1449,8 @@ static void *__remote_slab_alloc_node(st
 	struct kmem_cache_list *l;
 	void *object;
 
+	if (gfpflags & 0x2000)
+		printk("SLQB: __remote_slab_alloc_node cpu=%d request node=%d\n", smp_processor_id(), node);
 	n = s->node_slab[node];
 	if (unlikely(!n)) /* node has no memory */
 		return NULL;
@@ -1541,7 +1552,11 @@ static __always_inline void *slab_alloc(
 
 again:
 	local_irq_save(flags);
+	if (gfpflags & 0x2000)
+		printk("SLQB: slab_alloc cpu=%d,nid=%d request node=%d\n", smp_processor_id(), numa_node_id(), node);
 	object = __slab_alloc(s, gfpflags, node);
+	if (gfpflags & 0x2000)
+		printk("SLQB: slab_alloc cpu=%d return=%p\n", smp_processor_id(), object);
 	local_irq_restore(flags);
 
 	if (unlikely(slab_debug(s)) && likely(object)) {
@@ -2869,9 +2884,12 @@ void __init kmem_cache_init(void)
 #endif
 
 #ifdef CONFIG_SMP
+	printk("SLQB: kmem_cache_init possible CPUs: ");
 	for_each_possible_cpu(i) {
 		struct kmem_cache_cpu *c;
 
+		printk("%d ", i);
+
 		c = &per_cpu(kmem_cache_cpus, i);
 		init_kmem_cache_cpu(&kmem_cache_cache, c);
 		kmem_cache_cache.cpu_slab[i] = c;
@@ -2886,14 +2904,18 @@ void __init kmem_cache_init(void)
 		kmem_node_cache.cpu_slab[i] = c;
 #endif
 	}
+	printk("\n");
 #else
 	init_kmem_cache_cpu(&kmem_cache_cache, &kmem_cache_cache.cpu_slab);
 #endif
 
 #ifdef CONFIG_NUMA
-	for_each_node_state(i, N_NORMAL_MEMORY) {
+	printk("SLQB: kmem_cache_init possible nodes: ");
+	for_each_node_state(i, N_POSSIBLE) {
 		struct kmem_cache_node *n;
 
+		printk("%d ", i);
+
 		n = &per_cpu(kmem_cache_nodes, i);
 		init_kmem_cache_node(&kmem_cache_cache, n);
 		kmem_cache_cache.node_slab[i] = n;
@@ -2906,6 +2928,7 @@ void __init kmem_cache_init(void)
 		init_kmem_cache_node(&kmem_node_cache, n);
 		kmem_node_cache.node_slab[i] = n;
 	}
+	printk("\n");
 #endif
 
 	/* Caches that are not of the two-to-the-power-of size */
@@ -3040,12 +3063,17 @@ struct kmem_cache *kmem_cache_create(con
 	if (!kmem_cache_create_ok(name, size, align, flags))
 		goto err;
 
-	s = kmem_cache_alloc(&kmem_cache_cache, GFP_KERNEL);
+	printk("SLQB: kmem_cache_create %s size=%d align=%d flags=%lx\n", name, (int)size, (int)align, flags);
+
+	s = kmem_cache_alloc(&kmem_cache_cache, GFP_KERNEL|0x2000);
 	if (!s)
 		goto err;
 
-	if (kmem_cache_open(s, name, size, align, flags, ctor, 1))
+	printk("SLQB: kmem_cache_create %s kmem_cache allocated\n", name);
+	if (kmem_cache_open(s, name, size, align, flags, ctor, 1)) {
+		printk("SLQB: kmem_cache_create %s kmem_cache opened\n", name);
 		return s;
+	}
 
 	kmem_cache_free(&kmem_cache_cache, s);
 

^ permalink raw reply

* Re: [PATCH v4] zone_reclaim is always 0 by default
From: Mel Gorman @ 2009-06-09 14:38 UTC (permalink / raw)
  To: KOSAKI Motohiro
  Cc: Rik van Riel, Christoph Lameter, linux-mm, Zhang, Yanmin, LKML,
	linuxppc-dev, Robin Holt, linux-ia64, Andrew Morton, Wu Fengguang
In-Reply-To: <20090609211721.DD9A.A69D9226@jp.fujitsu.com>

On Tue, Jun 09, 2009 at 10:48:34PM +0900, KOSAKI Motohiro wrote:
> Hi
> 
> sorry for late responce. my e-mail reading speed is very slow ;-)
> 
> First, Could you please read past thread?
> I think many topic of this mail are already discussed.
> 

I think I caught them all but the horrible fact of the matter is that
whether zone_reclaim_mode should be 1 or 0 on NUMA machines is "it depends".
There are arguements for both and no clear winner.

> 
> > On Thu, Jun 04, 2009 at 07:23:15PM +0900, KOSAKI Motohiro wrote:
> > > 
> > > Current linux policy is, zone_reclaim_mode is enabled by default if the machine
> > > has large remote node distance. it's because we could assume that large distance
> > > mean large server until recently.
> > > 
> > 
> > We don't make assumptions about the server being large, small or otherwise. The
> > affinity tables reporting a distance of 20 or more is saying "remote memory
> > has twice the latency of local memory". This is true irrespective of workload
> > and implies that going off-node has a real penalty regardless of workload.
> 
> No.
> Now, we talk about off-node allocation vs unnecessary file cache dropping.
> IOW, off-node allocation vs disk access.
> 

Even if we used GFP flags to identify the file pages, there is no guarantee
that we are taking the correct action to keep "relevant" pages in memory.

> Then, the worth doesn't only depend on off-node distance, but also depend on
> workload IO tendency and IO speed.
> 
> Fujitsu has 64 core ia64 HPC box, zone-reclaim sometimes made performance
> degression although its box. 
> 

I bet if it was 0, that the off-node accesses would somewtimes make
"performance degression" as well :(

> So, I don't think this problem is small vs large machine issue.
> nor i7 issue.
> high-speed P2P CPU integrated memory controller expose old issue.
> 
> 
> > > In general, workload depended configration shouldn't put into default settings.
> > > 
> > > However, current code is long standing about two year. Highest POWER and IA64 HPC machine
> > > (only) use this setting.
> > > 
> > > Thus, x86 and almost rest architecture change default setting, but Only power and ia64
> > > remain current configuration for backward-compatibility.
> > > 
> > 
> > What about if it's x86-64-based NUMA but it's not i7 based. There, the
> > NUMA distances might really mean something and that zone_reclaim behaviour
> > is desirable.
> 
> hmmm..
> I don't hope ignore AMD, I think it's common characterastic of P2P and
> integrated memory controller machine.
> 
> Also, I don't hope detect CPU family or similar, because we need update
> such code evey when Intel makes new cpu.
> 
> Can we detect P2P interconnect machine? I'm not sure.
> 

I've no idea. It's not just I7 because some of the AMD chips will have
integrated memory controllers as well. We were somewhat depending on the
affinity information providing the necessary information.

> > I think if we're going down the road of setting the default, it shouldn't be
> > per-architecture defaults as such. Other choices for addressing this might be;
> > 
> > 1. Make RECLAIM_DISTANCE a variable on x86. Set it to 20 by default, and 5
> >    (or some other sensible figure) on i7
> > 
> > 2. There should be a per-arch modifier callback for the affinity
> >    distances. If the x86 code detects the CPU is an i7, it can reduce the
> >    reported latencies to be more in line with expected reality.
> > 
> > 3. Do not use zone_reclaim() for file-backed data if more than 20% of memory
> >    overall is free. The difficulty is figuring out if the allocation is for
> >    file pages.
> > 
> > 4. Change zone_reclaim_mode default to mean "do your best to figure it
> >    out". Patch 1 would default large distances to 1 to see what happens.
> >    Then apply a heuristic when in figure-it-out mode and using reclaim_mode == 1
> > 
> > 	If we have locally reclaimed 2% of the nodes memory in file pages
> > 	within the last 5 seconds when >= 20% of total physical memory was
> > 	free, then set the reclaim_mode to 0 on the assumption the node is
> > 	mostly caching pages and shouldn't be reclaimed to avoid excessive IO
> > 
> > Option 1 would appear to be the most straight-forward but option 2
> > should be doable. Option 3 and 4 could turn into a rats nest and I would
> > consider those approaches a bit more drastic.
> 
> hmhm. 
> I think the key-point of option 1 and 2 are proper hardware detecting way.
> 
> option 3 and 4 are more prefere idea to me. I like workload adapted heuristic.
> but you already pointed out its hard, because page-allocator don't know
> allocation purpose ;)
> 

Option 3 may be undoable. Even if the allocations are tagged as "this is
a file-backed allocation", we have no way of detecting how important
that is to the overall workload. Option 4 would be the preference. It's
a heuristic that might let us down, but the administrator can override
it and fix the reclaim_mode in the event we get it wrong.

> 
> > > @@ -10,6 +10,12 @@ struct device_node;
> > >  
> > >  #include <asm/mmzone.h>
> > >  
> > > +/*
> > > + * Distance above which we begin to use zone reclaim
> > > + */
> > > +#define RECLAIM_DISTANCE 20
> > > +
> > > +
> > 
> > Where is the ia-64-specific modifier to RECAIM_DISTANCE?
> 
> 
> arch/ia64/include/asm/topology.h has
> 
> 	/*
> 	 * Distance above which we begin to use zone reclaim
> 	 */
> 	#define RECLAIM_DISTANCE 15
> 
> 
> I don't think distance==15 is machine independent proper definition.
> but there is long lived definition ;)
> 
> 
> 
> 

-- 
Mel Gorman
Part-time Phd Student                          Linux Technology Center
University of Limerick                         IBM Dublin Software Lab

^ permalink raw reply

* Re: SD card over (xilinx_)SPI, timeout error while CID
From: Joachim Foerster @ 2009-06-09 17:26 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: lorenz, dbrownell, john.linn, joachim
In-Reply-To: <1244216069.21470.12.camel@localhost>

Hi,

On Fri, 2009-06-05 at 17:34 +0200, Joachim Foerster wrote:
> we have a very strange problem with SD-card-over-SPI support using
> 2.6.29.4 on our custom PowerPC 405 (Virtex-4 FX FPGA) based board. To
> summarize the problem in one sentence: mmc_spi gets a timeout (error
> -110) after sending MMC command "CMD10" (CID, card identification?).

The problem seems to be these DMA transfers/methods (?), which are used
by mmc_spi, if spi->master->dev.parent->dma_mask is non-NULL in
mmc_spi_probe() .
We detected the problem in form of kind of "data loss/corruption" in
mmc_spi_readbytes() after spi_sync() is called. Data is received
correctly by xilinx_spi (and thus by spi_sync())!

Background: The CMD10 is the first "bigger" ;-) (16 bytes) block
transfer, where mmc_spi waits for the token 0xfe by calling
mmc_spi_skip() in the end and later on receives these 16 bytes. But the
token seems to be "lost/corrupted" and thus a timeout occurs.

For now our dirty workaround is, to remove DMA support by commenting out
the "if (spi->master->dev.parent->dma_mask)" block in mmc_spi_probe().

Note, that in the old 2.6.26+arch/ppc this dma_mask is NULL - so DMA
code is never activated in mmc_spi_probe()!

Conclusion: Either DMA code in mmc_spi has a bug OR dma_*() functions
have a bug OR the device tree setup code should not assign a dma_mask to
xilinx_spi devices?

Any hints? Where do we have to look in case there is something wrong in
device tree setup?

 Joachim

^ permalink raw reply

* "Info threads" hangs in Linux-2.6.29 with KGDBOE
From: srikanth krishnakar @ 2009-06-09 18:08 UTC (permalink / raw)
  To: kgdb-bugreport; +Cc: Jason Wessel

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

Hi All,

*ISSUE *: "*Info threads*" hangs in KGDBOE
Kernel : Linux-2.6.29
Bug found in Architectures: PowerPC (ppc32), x86
-------

While trying to run kernel* Linux-2.6.29* on* PowerPC* Xilinx target
with *KGDBOE
*enabled.  Further issues arise when I run  "*info threads*" after
connecting to the target. following is the error:

(gdb) target remote udp:10.161.2.35:6443

warning: The remote protocol may be unreliable over UDP.

Some events may be lost, rendering further debugging impossible.

Remote debugging using udp:10.161.2.35:6443

kgdb_breakpoint () at kernel/kgdb.c:1803

1803            arch_kgdb_breakpoint();

(gdb) info threads
[New Thread -2]
[New Thread 2]
[New Thread 3]
[New Thread 4]
[New Thread 5]
[New Thread 6]
[New Thread 59]
[New Thread 67]
[New Thread 101]
[New Thread 102]
[New Thread 103]
[New Thread 104]
[New Thread 105]
 14 Thread 105 (nfsiod)  __switch_to (prev=<value optimized out>,
new=0xcf89c100) at arch/powerpc/kernel/process.c:411
 13 Thread 104 (aio/0)  __switch_to (prev=<value optimized out>,
new=0xcf82f4e0) at arch/powerpc/kernel/process.c:411
 12 Thread 103 (kswapd0)  __switch_to (prev=<value optimized out>,
new=0xcf82f4e0) at arch/powerpc/kernel/process.c:411
 11 Thread 102 (pdflush)  __switch_to (prev=<value optimized out>,
new=0xcf82e880) at arch/powerpc/kernel/process.c:411
 10 Thread 101 (pdflush)  Ignoring packet error, continuing...
Ignoring packet error, continuing...
Ignoring packet error, continuing...
Ignoring packet error, continuing...
Ignoring packet error, continuing...

Finally kernel dies, after these error messages. This issue is not found
till Linux-2.6.28.10 kernel version, KGDBOE works fine in x86 & PowerPC. Now
the bug is seen in x86 (32bit) and PowerPC from kernel version Linux-2.6.29

Hope this should not be raw_smp_processor_id issue ! The CPU ID returned in
both arch's is 0.  Which patch in netpoll* or any net device has caused this
issue.

One more thing to notice in x86 or PowerPC the kernel dies exactly after
reply of four threads/packets.


Thanks,
Srikanth Krishnakar

[-- Attachment #2: Type: text/html, Size: 2831 bytes --]

^ permalink raw reply

* Re: [BUILD FAILURE 01/04] Next June 04:PPC64 randconfig [drivers/staging/comedi/drivers.o]
From: Subrata Modak @ 2009-06-09 18:34 UTC (permalink / raw)
  To: Benjamin Herrenschmidt, Greg KH
  Cc: sachinp, fmhess, sfr, linux-kernel, Linuxppc-dev, Ian Abbott,
	linux-next, paulus, Geert.Uytterhoeven, geert, David Miller
In-Reply-To: <1244519418.5235.2.camel@pasglop>

On Tue, 2009-06-09 at 13:50 +1000, Benjamin Herrenschmidt wrote:
> On Sun, 2009-06-07 at 20:06 +0530, Subrata Modak wrote:
> > On Sat, 2009-06-06 at 09:36 -0400, Frank Mori Hess wrote:
> > > On Saturday 06 June 2009, Greg KH wrote:
> > > > Frank and Ian, any thoughts about the vmap call in the
> > > > comedi_buf_alloc() call?  Why is it using PAGE_KERNEL_NOCACHE, and what
> > > > is the prealloc_buf buffer used for?
> > > 
> > > It is a circular buffer used to hold data streaming either to or from a 
> > > board (for example when producing an analog output waveform).  Reads and 
> > > writes to the device files read/write to the circular buffer, plus a few 
> > > drivers do dma directly to/from it.  I personally don't have a problem 
> > > with requiring drivers to have their own dma buffers and making them copy 
> > > data between their private dma buffers and the main circular buffer.  I 
> > > guess the original design wanted to support zero-copy dma.
> > 
> > Great to hear that. How about a patch that solves my build problem on
> > PPC64(the problem seems to be existing for long) ? 
> 
> In any case, doing PAGE_KERNEL_NOCACHE for DMA memory is incorrect on
> many architectures. So at this stage, there's no much option but ifdef I
> suspect for now until this is fixed properly.

Ok. But, i am not sure whether Greg will agree to this. If, Ok, is the
following patch i sent earlier Ok ?

http://lkml.org/lkml/2009/6/5/462,

Regards--
Subrata

> 
> It does make sense to want to have some memory like that shared between
> user space and DMA, though I don't know what the right approach that
> works on all archs is at this stage. Worth asking the Alsa guys, I think
> they have similar issues :-)
> 
> But doing double buffering might do the trick fine for now.
> 
> Cheers,
> Ben.
> 
> 
> 
> 

^ permalink raw reply

* Re: [BUILD FAILURE 02/04] Next June 04:PPC64 randconfig [drivers/usb/host/ohci-hcd.o]
From: Subrata Modak @ 2009-06-09 18:36 UTC (permalink / raw)
  To: linux-usb, David Brownell, Arnd Bergmann
  Cc: Sachin P Sant, Randy Dunlap, David Brownell, Roman Weissgaerber,
	Stephen Rothwell, Linux-Kernel, Linuxppc-dev, Linux-Next, kernel
In-Reply-To: <20090605182651.24094.36577.sendpatchset@elm3a191.beaverton.ibm.com>

On Fri, 2009-06-05 at 13:26 -0500, Subrata Modak wrote:
> >On Thu, 2009-06-04 at 10:07 -0400, Jon Smirl wrote:
> >On Thu, Jun 4, 2009 at 9:31 AM, Subrata Modak
> > <subrata@linux.vnet.ibm.com> wrote:
> > > CC      drivers/usb/host/ohci-hcd.o
> > > In file included from drivers/usb/host/ohci-hcd.c:1060:
> > > drivers/usb/host/ohci-ppc-of.c:242:2: error: #error "No endianess selected for ppc-of-ohci"
> > > make[3]: *** [drivers/usb/host/ohci-hcd.o] Error 1
> > > make[2]: *** [drivers/usb/host] Error 2
> > > make[1]: *** [drivers/usb] Error 2
> > > make: *** [drivers] Error 2
> > >
> > > I reported this earlier, and there were some discussions:
> > > http://groups.google.co.kr/group/linux.kernel/browse_thread/thread/edff9d5572d3d225
> > 
> > Proposed patch by Arnd should fix this. It has not been merged.
> > http://lkml.org/lkml/2009/4/22/49
> 
> Correct, it fixes the issue. However, since few changes might have gone
> to the Kconfig, the patch does not apply cleanly. Below is the patch, just
> a retake of the earlier one, but on the latest code. 
> 
> David,
> 
> Can you please pickup the following patch ?

David,

Is it you who will be merging this patch. Or, do i need to send it to
somebody else ?

Regards--
Subrata

> 
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>,
> Resent-by: Subrata Modak <subrata@linux.vnet.ibm.com>
> ---
> 
> --- linux-2.6.30-rc8/drivers/usb/host/Kconfig.orig	2009-06-05 10:31:30.000000000 -0500
> +++ linux-2.6.30-rc8/drivers/usb/host/Kconfig	2009-06-05 10:37:53.000000000 -0500
> @@ -181,26 +181,26 @@ config USB_OHCI_HCD_PPC_SOC
>  	  Enables support for the USB controller on the MPC52xx or
>  	  STB03xxx processor chip.  If unsure, say Y.
> 
> -config USB_OHCI_HCD_PPC_OF
> -	bool "OHCI support for PPC USB controller on OF platform bus"
> -	depends on USB_OHCI_HCD && PPC_OF
> -	default y
> -	---help---
> -	  Enables support for the USB controller PowerPC present on the
> -	  OpenFirmware platform bus.
> -
>  config USB_OHCI_HCD_PPC_OF_BE
> -	bool "Support big endian HC"
> -	depends on USB_OHCI_HCD_PPC_OF
> -	default y
> +	bool "OHCI support for OF platform bus (big endian)"
> +	depends on USB_OHCI_HCD && PPC_OF
>  	select USB_OHCI_BIG_ENDIAN_DESC
>  	select USB_OHCI_BIG_ENDIAN_MMIO
> +	---help---
> +	Enables support for big-endian USB controllers present on the
> +	OpenFirmware platform bus.
> 
>  config USB_OHCI_HCD_PPC_OF_LE
> -	bool "Support little endian HC"
> -	depends on USB_OHCI_HCD_PPC_OF
> -	default n
> +	bool "OHCI support for OF platform bus (little endian)"
> +	depends on USB_OHCI_HCD && PPC_OF
>  	select USB_OHCI_LITTLE_ENDIAN
> +	---help---
> +	Enables support for little-endian USB controllers present on the
> +	OpenFirmware platform bus.
> +
> +	config USB_OHCI_HCD_PPC_OF
> +	bool
> +	default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
> 
>  config USB_OHCI_HCD_PCI
>  	bool "OHCI support for PCI-bus USB controllers"
> 
> ---
> Regards--
> Subrata
> >

^ permalink raw reply

* Re: [PATCH -next] powerpc/85xx: Add support for X-ES MPC85xx boards
From: Nate Case @ 2009-06-09 18:53 UTC (permalink / raw)
  To: Kumar Gala; +Cc: linuxppc-dev
In-Reply-To: <2AF4BA69-D05A-4D2E-BD32-5E1C93ACF445@kernel.crashing.org>

On Mon, 2009-06-08 at 17:52 -0500, Kumar Gala wrote:
> > +static void xes_mpc85xx_configure_l1(void)
> > +{
[snip]
> 
> I'd prefer we move this into __setup_cpu_e500v1/__setup_cpu_e500v2 so  
> its done for all processors regardless of platform.

How does something like this look?  Let me know and I can test and
submit it separately.

- Nate

diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
index eb4b9ad..546804f 100644
--- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
+++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
@@ -17,6 +17,34 @@
 #include <asm/cputable.h>
 #include <asm/ppc_asm.h>
 
+_GLOBAL(__e500_icache_enable)
+	mfspr	r3, SPRN_L1CSR1
+	oris	r3, r3, L1CSR1_CPE@h
+	ori	r3, r3, (L1CSR1_ICFI | L1CSR1_ICE)
+	mtspr	SPRN_L1CSR1, r3		/* Enable I-Cache */
+	isync
+	blr
+
+_GLOBAL(__e500_dcache_enable)
+	msync
+	isync
+	li	r3, 0
+	mtspr	SPRN_L1CSR0, r3		/* Disable */
+	msync
+	isync
+	li	r3, L1CSR0_DCFI
+	mtspr	SPRN_L1CSR0, r3		/* Invalidate */
+	msync
+	isync
+	mfspr	r3, SPRN_L1CSR0
+	oris	r3, r3, L1CSR0_CPE@h
+	ori	r3, r3, (L1CSR0_DCFI | L1CSR0_DCE)
+	msync
+	isync
+	mtspr	SPRN_L1CSR0, r3		/* Enable */
+	isync
+	blr
+
 _GLOBAL(__setup_cpu_e200)
 	/* enable dedicated debug exception handling resources (Debug APU) */
 	mfspr	r3,SPRN_HID0
@@ -25,7 +53,16 @@ _GLOBAL(__setup_cpu_e200)
 	b	__setup_e200_ivors
 _GLOBAL(__setup_cpu_e500v1)
 _GLOBAL(__setup_cpu_e500v2)
-	b	__setup_e500_ivors
+	mflr	r4
+	bl	__e500_icache_enable
+	bl	__e500_dcache_enable
+	bl	__setup_e500_ivors
+	mtlr	r4
+	blr
 _GLOBAL(__setup_cpu_e500mc)
-	b	__setup_e500mc_ivors
-
+	mflr	r4
+	bl	__e500_icache_enable
+	bl	__e500_dcache_enable
+	bl	__setup_e500mc_ivors
+	mtlr	r4
+	blr

^ permalink raw reply related

* Re: [BUILD FAILURE 01/04] Next June 04:PPC64 randconfig [drivers/staging/comedi/drivers.o]
From: Geert Uytterhoeven @ 2009-06-09 18:54 UTC (permalink / raw)
  To: subrata
  Cc: sachinp, fmhess, sfr, linux-kernel, Linuxppc-dev, Ian Abbott,
	linux-next, paulus, Greg KH, Geert.Uytterhoeven, David Miller
In-Reply-To: <1244572446.5497.32.camel@subratamodak.linux.ibm.com>

On Tue, Jun 9, 2009 at 20:34, Subrata Modak<subrata@linux.vnet.ibm.com> wro=
te:
> On Tue, 2009-06-09 at 13:50 +1000, Benjamin Herrenschmidt wrote:
>> On Sun, 2009-06-07 at 20:06 +0530, Subrata Modak wrote:
>> > On Sat, 2009-06-06 at 09:36 -0400, Frank Mori Hess wrote:
>> > > On Saturday 06 June 2009, Greg KH wrote:
>> > > > Frank and Ian, any thoughts about the vmap call in the
>> > > > comedi_buf_alloc() call? =C2=A0Why is it using PAGE_KERNEL_NOCACHE=
, and what
>> > > > is the prealloc_buf buffer used for?
>> > >
>> > > It is a circular buffer used to hold data streaming either to or fro=
m a
>> > > board (for example when producing an analog output waveform). =C2=A0=
Reads and
>> > > writes to the device files read/write to the circular buffer, plus a=
 few
>> > > drivers do dma directly to/from it. =C2=A0I personally don't have a =
problem
>> > > with requiring drivers to have their own dma buffers and making them=
 copy
>> > > data between their private dma buffers and the main circular buffer.=
 =C2=A0I
>> > > guess the original design wanted to support zero-copy dma.
>> >
>> > Great to hear that. How about a patch that solves my build problem on
>> > PPC64(the problem seems to be existing for long) ?
>>
>> In any case, doing PAGE_KERNEL_NOCACHE for DMA memory is incorrect on
>> many architectures. So at this stage, there's no much option but ifdef I
>> suspect for now until this is fixed properly.
>
> Ok. But, i am not sure whether Greg will agree to this. If, Ok, is the
> following patch i sent earlier Ok ?
>
> http://lkml.org/lkml/2009/6/5/462,

Your patch helps powerpc only. Compilation is still broken on most
other architectures.

>> It does make sense to want to have some memory like that shared between
>> user space and DMA, though I don't know what the right approach that
>> works on all archs is at this stage. Worth asking the Alsa guys, I think
>> they have similar issues :-)
>>
>> But doing double buffering might do the trick fine for now.

Gr{oetje,eeting}s,

						Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k=
.org

In personal conversations with technical people, I call myself a hacker. Bu=
t
when I'm talking to journalists I just say "programmer" or something like t=
hat.
							    -- Linus Torvalds

^ permalink raw reply

* Re: [PATCH -next] powerpc/85xx: Add support for X-ES MPC85xx boards
From: Kumar Gala @ 2009-06-09 19:43 UTC (permalink / raw)
  To: Nate Case; +Cc: linuxppc-dev
In-Reply-To: <1244573639.29684.1536.camel@localhost.localdomain>


On Jun 9, 2009, at 1:53 PM, Nate Case wrote:

> On Mon, 2009-06-08 at 17:52 -0500, Kumar Gala wrote:
>>> +static void xes_mpc85xx_configure_l1(void)
>>> +{
> [snip]
>>
>> I'd prefer we move this into __setup_cpu_e500v1/__setup_cpu_e500v2 so
>> its done for all processors regardless of platform.
>
> How does something like this look?  Let me know and I can test and
> submit it separately.
>
> - Nate
>
> diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/ 
> powerpc/kernel/cpu_setup_fsl_booke.S
> index eb4b9ad..546804f 100644
> --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
> +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
> @@ -17,6 +17,34 @@
> #include <asm/cputable.h>
> #include <asm/ppc_asm.h>
>
> +_GLOBAL(__e500_icache_enable)

I'd prefer we test to see if the cache is enabled and if it is just  
return

> +	mfspr	r3, SPRN_L1CSR1
> +	oris	r3, r3, L1CSR1_CPE@h
> +	ori	r3, r3, (L1CSR1_ICFI | L1CSR1_ICE)
> +	mtspr	SPRN_L1CSR1, r3		/* Enable I-Cache */
> +	isync
> +	blr
> +
> +_GLOBAL(__e500_dcache_enable)

I'd prefer we test to see if the cache is enabled and if it is just  
return
>
> +	msync
> +	isync
> +	li	r3, 0
> +	mtspr	SPRN_L1CSR0, r3		/* Disable */
> +	msync
> +	isync
> +	li	r3, L1CSR0_DCFI

should probably flash reset the locks as well.

>
> +	mtspr	SPRN_L1CSR0, r3		/* Invalidate */
> +	msync
> +	isync
> +	mfspr	r3, SPRN_L1CSR0
> +	oris	r3, r3, L1CSR0_CPE@h
> +	ori	r3, r3, (L1CSR0_DCFI | L1CSR0_DCE)
> +	msync
> +	isync
> +	mtspr	SPRN_L1CSR0, r3		/* Enable */
> +	isync
> +	blr
> +
> _GLOBAL(__setup_cpu_e20

^ permalink raw reply

* [PATCH] powerpc/mpc52xx/mtd: fix mtd-ram access for 16-bit Local Plus Bus
From: Albrecht Dreß @ 2009-06-09 19:46 UTC (permalink / raw)
  To: grant.likely, dwmw2; +Cc: Linux PPC Development

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

Hi all,

this patch adds support for RAM chips connected to the Local Plus Bus  
of a MPC5200B in 16-bit mode.  As no single byte write accesses are  
allowed by the bus in this mode, a byte write has to be split into a  
word read - modify - write sequence (mpc52xx_memcpy2lpb16, as  
fix/extension for memcpy_toio; note that memcpy_fromio *does* work just  
fine).  It has been tested in conjunction with Wolfram Sang's mtd-ram  
[1] and Sascha Hauer's jffs unaligned access [2] patches on 2.6.29.1,  
with a Renesas static RAM connected in 16-bit "Large Flash" mode.

[1]  
<http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-June/072794.html>
[2] <http://article.gmane.org/gmane.linux.drivers.mtd/21521>

Signed-off-by: Albrecht Dreß <albrecht.dress@arcor.de>
Cc: Grant Likely <grant.likely@secretlab.ca>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: linuxppc-dev@ozlabs.org

---

diff -u  
linux-2.6.29.1.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c  
linux-2.6.29.1/arch/powerpc/platforms/52xx/mpc52xx_common.c
--- linux-2.6.29.1.orig/arch/powerpc/platforms/52xx/mpc52xx_common.c     
2009-04-02 22:55:27.000000000 +0200
+++ linux-2.6.29.1/arch/powerpc/platforms/52xx/mpc52xx_common.c  
2009-06-09 21:16:22.000000000 +0200
@@ -225,3 +225,59 @@

         while (1);
  }
+
+/**
+ * mpc52xx_memcpy2lpb16: copy data to the Local Plus Bus in 16-bit  
mode which
+ * doesn't allow byte accesses
+ */
+void
+mpc52xx_memcpy2lpb16(volatile void __iomem *dest, const void *src,
+                    unsigned long n)
+{
+       void *vdest = (void __force *) dest;
+
+       __asm__ __volatile__ ("sync" : : : "memory");
+
+       if (((unsigned long) vdest & 1) != 0) {
+               u8 buf[2];
+
+               *(u16 *)buf = *((volatile u16 *)(vdest - 1));
+               buf[1] = *((u8 *)src);
+               *((volatile u16 *)(vdest - 1)) = *(u16 *)buf;
+               src++;
+               vdest++;
+               n--;
+       }
+
+       /* looks weird, but helps the optimiser... */
+       if (n >= 4) {
+               unsigned long chunks = n >> 2;
+               volatile u32 * _dst = (volatile u32 *)(vdest - 4);
+               volatile u32 * _src = (volatile u32 *)(src - 4);
+
+               vdest += chunks << 2;
+               src += chunks << 2;
+               do {
+                       *++_dst = *++_src;
+               } while (--chunks);
+               n &= 3;
+       }
+
+       if (n >= 2) {
+               *((volatile u16 *)vdest) = *((volatile u16 *)src);
+               src += 2;
+               vdest += 2;
+               n -= 2;
+       }
+
+       if (n > 0) {
+               u8 buf[2];
+
+               *(u16 *)buf = *((volatile u16 *)vdest);
+               buf[0] = *((u8 *)src);
+               *((volatile u16 *)vdest) = *(u16 *)buf;
+       }
+
+       __asm__ __volatile__ ("sync" : : : "memory");
+}
+EXPORT_SYMBOL(mpc52xx_memcpy2lpb16);
diff -u linux-2.6.29.1.orig/arch/powerpc/include/asm/mpc52xx.h  
linux-2.6.29.1/arch/powerpc/include/asm/mpc52xx.h
--- linux-2.6.29.1.orig/arch/powerpc/include/asm/mpc52xx.h       
2009-04-02 22:55:27.000000000 +0200
+++ linux-2.6.29.1/arch/powerpc/include/asm/mpc52xx.h   2009-06-09  
21:14:31.000000000 +0200
@@ -274,6 +274,8 @@
  extern void mpc52xx_map_common_devices(void);
  extern int mpc52xx_set_psc_clkdiv(int psc_id, int clkdiv);
  extern void mpc52xx_restart(char *cmd);
+extern void mpc52xx_memcpy2lpb16(volatile void __iomem *dest, const  
void *src,
+                                unsigned long n);

  /* mpc52xx_pic.c */
  extern void mpc52xx_init_irq(void);
diff -u linux-2.6.29.1.orig/include/linux/mtd/map.h  
linux-2.6.29.1/include/linux/mtd/map.h
--- linux-2.6.29.1.orig/include/linux/mtd/map.h 2009-04-02  
22:55:27.000000000 +0200
+++ linux-2.6.29.1/include/linux/mtd/map.h      2009-06-08  
14:28:05.000000000 +0200
@@ -13,6 +13,9 @@
  #include <asm/unaligned.h>
  #include <asm/system.h>
  #include <asm/io.h>
+#ifdef CONFIG_PPC_MPC52xx
+#include <asm/mpc52xx.h>
+#endif

  #ifdef CONFIG_MTD_MAP_BANK_WIDTH_1
  #define map_bankwidth(map) 1
@@ -417,6 +420,11 @@

  static inline void inline_map_copy_to(struct map_info *map, unsigned  
long to, const void *from, ssize_t len)
  {
+#ifdef CONFIG_PPC_MPC52xx
+       if (map->bankwidth == 2)
+               mpc52xx_memcpy2lpb16(map->virt + to, from, len);
+       else
+#endif
         memcpy_toio(map->virt + to, from, len);
  }


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

^ permalink raw reply

* Re: [PATCH v4] zone_reclaim is always 0 by default
From: Andrew Morton @ 2009-06-09 19:47 UTC (permalink / raw)
  To: Robin Holt
  Cc: riel, cl, linux-mm, mel, yanmin.zhang, linux-kernel, linuxppc-dev,
	holt, kosaki.motohiro, linux-ia64, fengguang.wu
In-Reply-To: <20090609120213.GA18753@attica.americas.sgi.com>

On Tue, 9 Jun 2009 07:02:14 -0500
Robin Holt <holt@sgi.com> wrote:

> On Tue, Jun 09, 2009 at 11:37:55AM +0100, Mel Gorman wrote:
> > On Tue, Jun 09, 2009 at 04:55:07AM -0500, Robin Holt wrote:
> > > On Mon, Jun 08, 2009 at 12:50:48PM +0100, Mel Gorman wrote:
> > > 
> > > Let me start by saying I agree completely with everything you wrote and
> > > still disagree with this patch, but was willing to compromise and work
> > > around this for our upcoming x86_64 machine by putting a "value add"
> > > into our packaging of adding a sysctl that turns reclaim back on.
> > > 
> > 
> > To be honest, I'm more leaning towards a NACK than an ACK on this one. I
> > don't support enough NUMA machines to feel strongly enough about it but
> > unconditionally setting zone_reclaim_mode to 0 on x86-64 just because i7's
> > might be there seems ill-advised to me and will have other consequences for
> > existing more traditional x86-64 NUMA machines.
> 
> I was sort-of planning on coming up with an x86_64 arch specific function
> for setting zone_reclaim_mode, but didn't like the direction things
> were going.
> 
> Something to the effect of...
> --- 20090609.orig/mm/page_alloc.c       2009-06-09 06:51:34.000000000 -0500
> +++ 20090609/mm/page_alloc.c    2009-06-09 06:55:00.160762069 -0500
> @@ -2326,12 +2326,7 @@ static void build_zonelists(pg_data_t *p
>         while ((node = find_next_best_node(local_node, &used_mask)) >= 0) {
>                 int distance = node_distance(local_node, node);
>  
> -               /*
> -                * If another node is sufficiently far away then it is better
> -                * to reclaim pages in a zone before going off node.
> -                */
> -               if (distance > RECLAIM_DISTANCE)
> -                       zone_reclaim_mode = 1;
> +               zone_reclaim_mode = arch_zone_reclaim_mode(distance);
>  
>                 /*
>                  * We don't want to pressure a particular node.
> 
> And then letting each arch define an arch_zone_reclaim_mode().  If other
> values are needed in the determination, we would add parameters to
> reflect this.
> 
> For ia64, add
> 
> static inline ia64_zone_reclaim_mode(int distance)
> {
> 	if (distance > 15)
> 		return 1;
> }
> 
> #define	arch_zone_reclaim_mode(_d)	ia64_zone_reclaim_mode(_d)
> 
> 
> Then, inside x86_64_zone_reclaim_mode(), I could make it something like
> 	if (distance > 40 || is_uv_system())
> 		return 1;
> 
> In the end, I didn't think this fight was worth fighting given how ugly
> this felt.  Upon second thought, I am beginning to think it is not that
> bad, but I also don't think it is that good either.
> 

We've done worse before now...

Is it not possible to work out at runtime whether zone reclaim mode is
beneficial?

Given that zone_reclaim_mode is settable from initscripts, why all the
fuss?

Is anyone testing RECLAIM_WRITE and RECLAIM_SWAP, btw?

The root cause of this problem: having something called "mode".  Any
time we put a "mode" in the kernel, we get in a mess trying to work out
when to set it and to what.

I think I'll drop this patch for now.

^ permalink raw reply

* [PATCH] AMCC Crypto4xx Device Driver v7
From: Shasi Pulijala @ 2009-06-09 21:37 UTC (permalink / raw)
  To: linuxppc-dev


From: Shasi Pulijala <spulijala@amcc.com>

This patch adds further support for AMCC ppc4xx security device driver. =
This is the
second release that adds algorithms like:
 des/3des
 rfc3686(ctr(aes))
 gcm, ccm
 hmac(md5,sha1,..,sha512)
 xcbc(aes), arc4 and kasumi.

Signed-off-by: Shasi Pulijala <spulijala@amcc.com>
Acked-by: Loc Ho <lho@amcc.com>
---
 crypto/md5.c                         |   15 +
 crypto/sha1_generic.c                |   15 +
 crypto/sha256_generic.c              |   15 +
 crypto/sha512_generic.c              |   19 +
 drivers/crypto/amcc/crypto4xx_alg.c  | 1492 =
+++++++++++++++++++++++++++++++++-
 drivers/crypto/amcc/crypto4xx_core.c |  816 ++++++++++++++++++-
 drivers/crypto/amcc/crypto4xx_core.h |   92 +++
 drivers/crypto/amcc/crypto4xx_sa.c   |  114 +++
 drivers/crypto/amcc/crypto4xx_sa.h   |  337 ++++++++-
 include/crypto/sha.h                 |    7 +
 10 files changed, 2870 insertions(+), 52 deletions(-)

diff --git a/crypto/md5.c b/crypto/md5.c
index 83eb529..0c74b84 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -220,6 +220,21 @@ static int md5_final(struct shash_desc *desc, u8 =
*out)
 	return 0;
 }
=20
+void md5_get_immediate_hash(struct crypto_tfm *tfm, u8 *data)
+{
+	struct shash_desc *desc =3D crypto_tfm_ctx(tfm);
+	struct md5_ctx *mctx =3D shash_desc_ctx(desc);
+	int i;
+
+	for (i =3D 0; i < MD5_HASH_WORDS; i++) {
+		*data++ =3D mctx->hash[i] & 0xFF;
+		*data++ =3D (mctx->hash[i] >> 8) & 0xFF;
+		*data++ =3D (mctx->hash[i] >> 16) & 0xFF;
+		*data++ =3D (mctx->hash[i] >> 24) & 0xFF;
+	}
+}
+EXPORT_SYMBOL_GPL(md5_get_immediate_hash);
+
 static struct shash_alg alg =3D {
 	.digestsize	=3D	MD5_DIGEST_SIZE,
 	.init		=3D	md5_init,
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 9efef20..e77b591 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -111,6 +111,21 @@ static int sha1_final(struct shash_desc *desc, u8 =
*out)
 	return 0;
 }
=20
+void sha1_get_immediate_hash(struct crypto_tfm *tfm, u8 *data)
+{
+	struct shash_desc *desc =3D crypto_tfm_ctx(tfm);
+	struct sha1_ctx *sctx =3D shash_desc_ctx(desc);
+	int i;
+
+	for (i =3D 0; i < 5; i++) {
+		*data++ =3D sctx->state[i] & 0xFF;
+		*data++ =3D (sctx->state[i] >> 8) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 16) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 24) & 0xFF;
+	}
+}
+EXPORT_SYMBOL_GPL(sha1_get_immediate_hash);
+
 static struct shash_alg alg =3D {
 	.digestsize	=3D	SHA1_DIGEST_SIZE,
 	.init		=3D	sha1_init,
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index 6349d83..0f5a66b 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -331,6 +331,21 @@ static int sha224_final(struct shash_desc *desc, u8 =
*hash)
 	return 0;
 }
=20
+void sha256_get_immediate_hash(struct crypto_tfm *tfm, u8 *data)
+{
+	struct shash_desc *desc =3D crypto_tfm_ctx(tfm);
+	struct sha256_ctx *sctx =3D shash_desc_ctx(desc);
+	int i;
+
+	for (i =3D 0; i < 8; i++) {
+		*data++ =3D sctx->state[i] & 0xFF;
+		*data++ =3D (sctx->state[i] >> 8) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 16) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 24) & 0xFF;
+	}
+}
+EXPORT_SYMBOL_GPL(sha256_get_immediate_hash);
+
 static struct shash_alg sha256 =3D {
 	.digestsize	=3D	SHA256_DIGEST_SIZE,
 	.init		=3D	sha256_init,
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index 3bea38d..c329903 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -257,6 +257,25 @@ static int sha384_final(struct shash_desc *desc, u8 =
*hash)
 	return 0;
 }
=20
+void sha512_get_immediate_hash(struct crypto_tfm *tfm, u8 *data)
+{
+	struct shash_desc *desc =3D crypto_tfm_ctx(tfm);
+	struct sha512_ctx *sctx =3D shash_desc_ctx(desc);
+	int i;
+
+	for (i =3D 0; i < 8; i++) {
+		*data++ =3D (sctx->state[i] >> 32) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 40) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 48) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 56) & 0xFF;
+		*data++ =3D sctx->state[i] & 0xFF;
+		*data++ =3D (sctx->state[i] >> 8) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 16) & 0xFF;
+		*data++ =3D (sctx->state[i] >> 24) & 0xFF;
+	}
+}
+EXPORT_SYMBOL_GPL(sha512_get_immediate_hash);
+
 static struct shash_alg sha512 =3D {
 	.digestsize	=3D	SHA512_DIGEST_SIZE,
 	.init		=3D	sha512_init,
diff --git a/drivers/crypto/amcc/crypto4xx_alg.c =
b/drivers/crypto/amcc/crypto4xx_alg.c
index 61b6e1b..fac3543 100644
--- a/drivers/crypto/amcc/crypto4xx_alg.c
+++ b/drivers/crypto/amcc/crypto4xx_alg.c
@@ -24,10 +24,13 @@
 #include <linux/crypto.h>
 #include <linux/hash.h>
 #include <crypto/internal/hash.h>
+#include <crypto/aead.h>
 #include <linux/dma-mapping.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/des.h>
 #include <crypto/sha.h>
+#include <crypto/authenc.h>
 #include "crypto4xx_reg_def.h"
 #include "crypto4xx_sa.h"
 #include "crypto4xx_core.h"
@@ -58,9 +61,10 @@ void set_dynamic_sa_command_1(struct dynamic_sa_ctl =
*sa, u32 cm, u32 hmac_mc,
 {
 	sa->sa_command_1.w =3D 0;
 	sa->sa_command_1.bf.crypto_mode31 =3D (cm & 4) >> 2;
-	sa->sa_command_1.bf.crypto_mode9_8 =3D cm & 3;
+	sa->sa_command_1.bf.crypto_mode9_8 =3D (cm & 3);
 	sa->sa_command_1.bf.feedback_mode =3D cfb,
 	sa->sa_command_1.bf.sa_rev =3D 1;
+	sa->sa_command_1.bf.hmac_muting =3D hmac_mc;
 	sa->sa_command_1.bf.extended_seq_num =3D esn;
 	sa->sa_command_1.bf.seq_num_mask =3D sn_mask;
 	sa->sa_command_1.bf.mutable_bit_proc =3D mute;
@@ -69,6 +73,338 @@ void set_dynamic_sa_command_1(struct dynamic_sa_ctl =
*sa, u32 cm, u32 hmac_mc,
 	sa->sa_command_1.bf.copy_hdr =3D cp_hdr;
 }
=20
+/** Table lookup for SA Hash Digest length and
+ *  Hash Contents (based on Hash type)
+ */
+unsigned int crypto4xx_sa_hash_tbl[3][HASH_ALG_MAX_CNT] =3D {
+	/* Hash Contents */
+	{ SA_HASH128_CONTENTS, SA_HASH160_CONTENTS, SA_HASH256_CONTENTS,
+	SA_HASH256_CONTENTS, SA_HASH512_CONTENTS, SA_HASH512_CONTENTS },
+	/* Digest len */
+	{4 * 4, 5 * 4, 7 * 4, 8 * 4, 12 * 4, 16 * 4},
+	/* SA Length */
+	{ SA_HASH128_LEN, SA_HASH160_LEN, SA_HASH256_LEN, SA_HASH256_LEN,
+	SA_HASH512_LEN, SA_HASH512_LEN }
+};
+
+/** Table lookup for Hash Algorithms based on Hash type, used in
+ *  crypto4xx_pre_compute_hmac()
+ */
+char *crypto4xx_hash_alg_map_tbl[HASH_ALG_MAX_CNT] =3D =
CRYPTO4XX_MAC_ALGS;
+
+static void crypto4xx_sg_setbuf(unsigned char *data, size_t bufsize,
+				struct scatterlist *sg, int sg_num)
+{
+	int remainder_of_page;
+	int i =3D 0;
+
+	sg_init_table(sg, sg_num);
+	while (bufsize > 0 && i < sg_num) {
+		sg_set_buf(&sg[i], data, bufsize);
+		remainder_of_page =3D PAGE_SIZE - sg[i].offset;
+		if (bufsize > remainder_of_page) {
+			/* the buffer was split over multiple pages */
+			sg[i].length =3D remainder_of_page;
+			bufsize -=3D remainder_of_page;
+			data +=3D remainder_of_page;
+		} else {
+			bufsize =3D 0;
+		}
+		i++;
+	}
+}
+
+void crypto4xx_compute_immediate_hash(struct crypto_tfm *child_tfm, u8 =
*data,
+				     unsigned char ha)
+{
+	switch (ha) {
+	case SA_HASH_ALG_MD5:
+		md5_get_immediate_hash(child_tfm, data);
+		break;
+	case SA_HASH_ALG_SHA1:
+		sha1_get_immediate_hash(child_tfm, data);
+		break;
+	case SA_HASH_ALG_SHA256:
+	case SA_HASH_ALG_SHA224:
+		sha256_get_immediate_hash(child_tfm, data);
+		break;
+	case SA_HASH_ALG_SHA384:
+	case SA_HASH_ALG_SHA512:
+		sha512_get_immediate_hash(child_tfm, data);
+		break;
+	default:
+		break;
+	}
+}
+
+int crypto4xx_pre_compute_hmac(struct crypto4xx_ctx *ctx,
+			       void *key,
+			       unsigned int keylen,
+			       unsigned int bs,
+			       unsigned char ha,
+			       unsigned char digs)
+{
+	u8 *ipad =3D NULL;
+	u8 *opad;
+	struct crypto_hash *child_hash =3D NULL;
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	struct scatterlist asg[2];
+	struct crypto_tfm *child_tfm;
+	char *child_name =3D NULL;
+	int i, rc =3D 0;
+	int ds;
+
+	BUG_ON(ha >=3D HASH_ALG_MAX_CNT);
+	child_name =3D crypto4xx_hash_alg_map_tbl[ha];
+	child_hash =3D crypto_alloc_hash(child_name, 0, 0);
+	if (IS_ERR(child_hash)) {
+		rc =3D PTR_ERR(child_hash);
+		printk(KERN_ERR "failed to load "
+				"transform for %s error %d\n",
+				child_name, rc);
+		return rc;
+	}
+
+	ipad =3D  kmalloc(bs * 2, GFP_KERNEL);
+	if (ipad =3D=3D NULL) {
+		crypto_free_hash(child_hash);
+		return -ENOMEM;
+	}
+
+	opad =3D ipad + bs;
+	child_tfm =3D crypto_hash_tfm(child_hash);
+	ds =3D crypto_hash_digestsize(child_hash);
+	desc.tfm =3D child_hash;
+	desc.flags =3D 0;
+	if (keylen > bs) {
+		crypto4xx_sg_setbuf(key, keylen, asg, 2);
+		rc =3D crypto_hash_init(&desc);
+		if (rc < 0)
+			goto err_alg_hash_key;
+		rc =3D crypto_hash_update(&desc, asg, keylen);
+		if (rc < 0)
+			goto err_alg_hash_key;
+		rc =3D crypto_hash_final(&desc, ipad);
+		keylen =3D ds;
+	} else {
+		memcpy(ipad, key, keylen);
+	}
+	memset(ipad + keylen, 0, bs-keylen);
+	memcpy(opad, ipad, bs);
+
+	for (i =3D 0; i < bs; i++) {
+		ipad[i] ^=3D 0x36;
+		opad[i] ^=3D 0x5c;
+	}
+
+	sg_init_one(&sg[0], ipad, bs);
+	rc =3D crypto_hash_init(&desc);
+	if (rc < 0)
+		goto err_alg_hash_key;
+	rc =3D crypto_hash_update(&desc, sg, bs);
+	if (rc < 0)
+		goto err_alg_hash_key;
+
+	if (ha =3D=3D SA_HASH_ALG_SHA224)
+		ds =3D SHA256_DIGEST_SIZE;
+	else if (ha =3D=3D SA_HASH_ALG_SHA384)
+		ds =3D SHA512_DIGEST_SIZE;
+
+	crypto4xx_compute_immediate_hash(child_tfm, ipad, ha);
+	crypto4xx_memcpy_le(ctx->sa_in +
+			get_dynamic_sa_offset_inner_digest(ctx), ipad, ds);
+
+	sg_init_one(&sg[0], opad, bs);
+	rc =3D crypto_hash_init(&desc);
+	if (rc < 0)
+		goto err_alg_hash_key;
+
+	rc =3D crypto_hash_update(&desc, sg, bs);
+	if (rc < 0)
+		goto err_alg_hash_key;
+
+	crypto4xx_compute_immediate_hash(child_tfm, opad, ha);
+	crypto4xx_memcpy_le(ctx->sa_in +
+			get_dynamic_sa_offset_outer_digest(ctx), opad, ds);
+
+err_alg_hash_key:
+	kfree(ipad);
+	crypto_free_hash(child_hash);
+	return rc;
+}
+
+int crypto4xx_compute_gcm_hash_key_sw(struct crypto4xx_ctx *ctx,
+				      const u8 *key,
+				      unsigned int keylen)
+{
+	struct crypto_blkcipher *aes_tfm =3D NULL;
+	struct blkcipher_desc 	desc;
+	struct scatterlist sg[1];
+	char src[16];
+	int rc =3D 0;
+
+	aes_tfm =3D crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(aes_tfm)) {
+		printk(KERN_ERR "failed to load transform for %ld\n",
+		       PTR_ERR(aes_tfm));
+		rc =3D PTR_ERR(aes_tfm);
+		return rc;
+	}
+	desc.tfm    =3D aes_tfm;
+	desc.flags  =3D 0;
+
+	memset(src, 0, 16);
+	rc =3D crypto_blkcipher_setkey(aes_tfm, key, keylen);
+	if (rc) {
+		printk(KERN_ERR "setkey() failed flags=3D%x\n",
+		       crypto_blkcipher_get_flags(aes_tfm));
+		goto out;
+	}
+
+	sg_init_one(sg, src, 16);
+	rc =3D crypto_blkcipher_encrypt(&desc, sg, sg, 16);
+	if (rc)
+		goto out;
+	crypto4xx_memcpy_le(ctx->sa_in +
+			get_dynamic_sa_offset_inner_digest(ctx), src, 16);
+
+out:
+	crypto_free_blkcipher(aes_tfm);
+	return rc;
+}
+
+/**
+ * 3DES/DES Functions
+ *
+ */
+static int crypto4xx_setkey_3des(struct crypto_ablkcipher *cipher,
+				 const u8 *key,
+				 unsigned int keylen,
+				 unsigned char cm,
+				 unsigned char fb)
+{
+	struct crypto_tfm    *tfm =3D crypto_ablkcipher_tfm(cipher);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	int rc;
+
+	if (keylen !=3D DES_KEY_SIZE && keylen !=3D DES3_EDE_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher,
+			CRYPTO_TFM_RES_BAD_KEY_LEN);
+
+		return -EINVAL;
+	}
+
+	if (keylen =3D=3D DES_KEY_SIZE) {
+		u32 tmp[32];
+		rc =3D des_ekey(tmp, key);
+		if (unlikely(rc =3D=3D 0) &&
+				  (tfm->crt_flags & CRYPTO_TFM_REQ_WEAK_KEY)) {
+			crypto_ablkcipher_set_flags(cipher,
+				CRYPTO_TFM_RES_WEAK_KEY);
+			return -EINVAL;
+		}
+	}
+
+	/* Create SA */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		crypto4xx_free_sa(ctx);
+
+	rc =3D crypto4xx_alloc_sa(ctx, keylen =3D=3D 8 ? SA_DES_LEN : =
SA_3DES_LEN);
+	if (rc)
+		return rc;
+	/*
+	 *  state record will state in base ctx, so iv and
+	 *  hash result can be reused
+	 *  also don't need to alloc each packet coming
+	 */
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			crypto4xx_free_sa(ctx);
+			return rc;
+		}
+	}
+
+	/* Setup SA */
+	ctx->direction =3D DIR_INBOUND;
+	ctx->hash_final =3D 0;
+
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
+				 SA_CIPHER_ALG_DES,
+				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
+				 SA_OPCODE_DECRYPT, DIR_INBOUND);
+
+	set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH,
+				 fb, SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+
+	if (keylen =3D=3D DES_KEY_SIZE) {
+		crypto4xx_memcpy_le(((struct dynamic_sa_des *) sa)->key,
+				      key, keylen);
+		((struct dynamic_sa_des *)sa)->ctrl.sa_contents =3D
+				SA_DES_CONTENTS;
+		sa->sa_command_0.bf.cipher_alg =3D SA_CIPHER_ALG_DES;
+	} else {
+		crypto4xx_memcpy_le(((struct dynamic_sa_3des *) sa)->key,
+				      key, keylen);
+		((struct dynamic_sa_3des *)sa)->ctrl.sa_contents =3D
+				SA_3DES_CONTENTS;
+		sa->sa_command_0.bf.cipher_alg =3D SA_CIPHER_ALG_3DES;
+	}
+
+	memcpy((void *)(ctx->sa_in +
+			get_dynamic_sa_offset_state_ptr_field(ctx)),
+			(void *)&ctx->state_record_dma_addr, 4);
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+	ctx->is_hash =3D 0;
+	sa->sa_command_0.bf.dir =3D DIR_INBOUND;
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+
+	return 0;
+}
+
+int crypto4xx_setkey_3des_cfb(struct crypto_ablkcipher *cipher,
+			      const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_3des(cipher, key, keylen,
+					CRYPTO_MODE_CFB,
+					CRYPTO_FEEDBACK_MODE_8BIT_CFB);
+}
+
+int crypto4xx_setkey_3des_ofb(struct crypto_ablkcipher *cipher,
+			      const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_3des(cipher, key, keylen,
+				       CRYPTO_MODE_OFB,
+				       CRYPTO_FEEDBACK_MODE_64BIT_OFB);
+}
+
+int crypto4xx_setkey_3des_cbc(struct crypto_ablkcipher *cipher,
+			      const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_3des(cipher, key, keylen,
+				     CRYPTO_MODE_CBC,
+				     CRYPTO_FEEDBACK_MODE_NO_FB);
+}
+
+int crypto4xx_setkey_3des_ecb(struct crypto_ablkcipher *cipher,
+			      const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_3des(cipher, key, keylen,
+				     CRYPTO_MODE_ECB,
+				     CRYPTO_FEEDBACK_MODE_NO_FB);
+}
+
+
 int crypto4xx_encrypt(struct ablkcipher_request *req)
 {
 	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm);
@@ -79,22 +415,54 @@ int crypto4xx_encrypt(struct ablkcipher_request =
*req)
 	ctx->pd_ctl =3D 0x1;
=20
 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
-				  req->nbytes, req->info,
-				  get_dynamic_sa_iv_size(ctx));
+				   req->nbytes, NULL, 0, req->info,
+				   get_dynamic_sa_iv_size(ctx));
 }
=20
 int crypto4xx_decrypt(struct ablkcipher_request *req)
 {
 	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm);
=20
+	ctx->hash_final =3D 0;
+	ctx->is_hash =3D 0;
+	ctx->pd_ctl =3D 0x1;
 	ctx->direction =3D DIR_INBOUND;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				   req->nbytes, NULL, 0, req->info,
+				   get_dynamic_sa_iv_size(ctx));
+}
+
+int crypto4xx_encrypt_ctr(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *ablkcipher =3D =
crypto_ablkcipher_reqtfm(req);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm);
+
 	ctx->hash_final =3D 0;
 	ctx->is_hash =3D 0;
-	ctx->pd_ctl =3D 1;
+	ctx->pd_ctl =3D 0x1;
+	ctx->direction =3D DIR_OUTBOUND;
=20
 	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
-				  req->nbytes, req->info,
-				  get_dynamic_sa_iv_size(ctx));
+				  req->nbytes, NULL, 0,
+				  req->info,
+				  crypto_ablkcipher_ivsize(ablkcipher));
+}
+
+int crypto4xx_decrypt_ctr(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *ablkcipher =3D =
crypto_ablkcipher_reqtfm(req);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm);
+
+	ctx->hash_final =3D 0;
+	ctx->is_hash =3D 0;
+	ctx->pd_ctl =3D 0x1;
+	ctx->direction =3D DIR_INBOUND;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->nbytes, NULL, 0,
+				  req->info,
+				  crypto_ablkcipher_ivsize(ablkcipher));
 }
=20
 /**
@@ -166,6 +534,13 @@ static int crypto4xx_setkey_aes(struct =
crypto_ablkcipher *cipher,
 	return 0;
 }
=20
+int crypto4xx_setkey_aes_ecb(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_ECB,
+				    CRYPTO_FEEDBACK_MODE_NO_FB);
+}
+
 int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
 			     const u8 *key, unsigned int keylen)
 {
@@ -173,8 +548,677 @@ int crypto4xx_setkey_aes_cbc(struct =
crypto_ablkcipher *cipher,
 				    CRYPTO_FEEDBACK_MODE_NO_FB);
 }
=20
+int crypto4xx_setkey_aes_ctr(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen)
+{
+	struct crypto_tfm    *tfm =3D crypto_ablkcipher_tfm(cipher);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	u32 cnt =3D 1;
+	int    rc;
+	u32 cm =3D CRYPTO_MODE_AES_CTR;
+
+	keylen -=3D 4;
+	/* Create SA */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		 crypto4xx_free_sa(ctx);
+
+	if (keylen !=3D AES_KEYSIZE_256 &&
+		   keylen !=3D AES_KEYSIZE_192 && keylen !=3D AES_KEYSIZE_128) {
+		crypto_ablkcipher_set_flags(cipher,
+					    CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	rc =3D crypto4xx_alloc_sa(ctx, SA_AES128_LEN + (keylen-16) / 4);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			crypto4xx_free_sa(ctx);
+			return rc;
+		}
+	}
+
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	ctx->hash_final =3D 0;
+	ctx->ctr_aes =3D 1;
+	/* Setup SA */
+	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
+				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_ENCRYPT,
+				 DIR_INBOUND);
+	set_dynamic_sa_command_1(sa, cm, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB,
+				 SA_EXTENDED_SN_OFF, SA_SEQ_MASK_OFF,
+				 SA_MC_ENABLE, SA_NOT_COPY_PAD,
+				 SA_NOT_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+
+	crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+			    key, keylen);
+	sa->sa_contents =3D SA_AES_CONTENTS | (keylen << 2);
+	sa->sa_command_1.bf.key_len =3D keylen >> 3;
+
+	ctx->direction =3D DIR_INBOUND;
+	memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+	       (void *)&ctx->state_record_dma_addr, 4);
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+
+	crypto4xx_memcpy_le(ctx->state_record, key + keylen, 4);
+	crypto4xx_memcpy_le(ctx->state_record + 12, (void *)&cnt, 4);
+
+	sa->sa_command_0.bf.dir =3D DIR_INBOUND;
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+
+	return 0;
+}
+
+int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
+					  const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_CFB,
+				    CRYPTO_FEEDBACK_MODE_128BIT_CFB);
+}
+
+int crypto4xx_setkey_aes_ofb(struct crypto_ablkcipher *cipher,
+					  const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_OFB,
+				    CRYPTO_FEEDBACK_MODE_64BIT_OFB);
+}
+
+int crypto4xx_setkey_aes_icm(struct crypto_ablkcipher *cipher,
+					  const u8 *key, unsigned int keylen)
+{
+	return crypto4xx_setkey_aes(cipher, key, keylen, CRYPTO_MODE_AES_ICM,
+				    CRYPTO_FEEDBACK_MODE_NO_FB);
+}
+
+/**
+ * AES-GCM Functions
+ */
+static inline int crypto4xx_aes_gcm_validate_keylen(unsigned int =
keylen)
+{
+	switch (keylen) {
+	case 16:
+	case 20:
+	case 24:
+	case 30:
+	case 32:
+	case 36:
+		return 0;
+	default:
+		printk(KERN_ERR "crypto4xx_setkey_aes_gcm: "
+				"ERROR keylen =3D 0x%08x\n", keylen);
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
+
+int crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher,
+				     const u8 *key, unsigned int keylen)
+
+{
+	struct crypto_tfm    *tfm =3D crypto_aead_tfm(cipher);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	int    rc =3D 0;
+
+	u32 cm =3D 4;
+
+	if (crypto4xx_aes_gcm_validate_keylen(keylen) !=3D 0) {
+		printk(KERN_ERR "crypto4xx_setkey_aes_gcm:"
+				"ERROR keylen =3D 0x%08x\n", keylen);
+		crypto_aead_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	    return -EINVAL;
+	}
+
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		 crypto4xx_free_sa(ctx);
+
+	rc =3D crypto4xx_alloc_sa(ctx, SA_AES128_GCM_LEN + (keylen-16) / 4);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc)
+			goto err;
+	}
+
+	sa  =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+
+	sa->sa_contents =3D SA_AES_GCM_CONTENTS | (keylen << 2);
+	sa->sa_command_1.bf.key_len =3D keylen >> 3;
+
+	ctx->direction =3D DIR_INBOUND;
+	crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+			    key, keylen);
+
+	memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+	       (void *)&ctx->state_record_dma_addr, 4);
+
+	rc =3D crypto4xx_compute_gcm_hash_key_sw(ctx, key, keylen);
+	if (rc) {
+		printk(KERN_ERR "GCM hash key setting failed =3D %d\n", rc);
+		goto err;
+	}
+
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+	ctx->is_gcm =3D 1;
+	ctx->hash_final =3D 1;
+	ctx->is_hash =3D 0;
+	ctx->pd_ctl =3D 0x11;
+
+	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_GHASH,
+				 SA_CIPHER_ALG_AES, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_HASH_DECRYPT,
+				 DIR_INBOUND);
+
+	sa->sa_command_1.bf.crypto_mode31 =3D (cm & 4) >> 2;
+	sa->sa_command_1.bf.crypto_mode9_8 =3D (cm & 3);
+	sa->sa_command_1.bf.feedback_mode =3D 0;
+
+	sa->sa_command_1.bf.hash_crypto_offset =3D 0;
+	sa->sa_command_1.bf.sa_rev =3D 1;
+	sa->sa_command_1.bf.copy_payload =3D 1;
+
+	sa->sa_command_1.bf.copy_pad =3D 0;
+	sa->sa_command_1.bf.copy_hdr =3D 0;
+	sa->sa_command_1.bf.mutable_bit_proc =3D 1;
+	sa->sa_command_1.bf.seq_num_mask =3D 1;
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+	sa->sa_command_0.bf.opcode =3D SA_OPCODE_ENCRYPT_HASH;
+
+	return 0;
+err:
+	crypto4xx_free_sa(ctx);
+	return rc;
+}
+
+int crypto4xx_encrypt_aes_gcm(struct aead_request *req)
+{
+	struct crypto_aead *aead =3D crypto_aead_reqtfm(req);
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+
+	ctx->direction =3D DIR_OUTBOUND;
+	ctx->append_icv =3D 1;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->cryptlen, req->assoc, req->assoclen,
+				  req->iv, crypto_aead_ivsize(aead));
+}
+
+int crypto4xx_decrypt_aes_gcm(struct aead_request *req)
+{
+	struct crypto_aead *aead =3D crypto_aead_reqtfm(req);
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+	int len =3D req->cryptlen - crypto_aead_authsize(aead);
+
+	ctx->direction =3D DIR_INBOUND;
+	ctx->append_icv =3D 0;
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  len, req->assoc, req->assoclen,
+				  req->iv, crypto_aead_ivsize(aead));
+}
+
+int crypto4xx_givencrypt_aes_gcm(struct aead_givcrypt_request *req)
+{
+	return -ENOSYS;
+}
+
+int crypto4xx_givdecrypt_aes_gcm(struct aead_givcrypt_request *req)
+{
+	return -ENOSYS;
+}
+
 /**
- * HASH SHA1 Functions
+ * AES-CCM Functions
+ */
+int crypto4xx_setauthsize_aes(struct crypto_aead *ciper,
+			      unsigned int authsize)
+{
+	struct aead_tfm *tfm =3D crypto_aead_crt(ciper);
+
+	switch (authsize) {
+	case 8:
+	case 12:
+	case 16:
+	case 10:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	tfm->authsize =3D authsize;
+	return 0;
+}
+
+int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher, const u8 *key,
+				unsigned int keylen)
+{
+	struct crypto_tfm    *tfm =3D crypto_aead_tfm(cipher);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	int rc =3D 0;
+
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		 crypto4xx_free_sa(ctx);
+
+	rc =3D crypto4xx_alloc_sa(ctx, SA_AES128_CCM_LEN + (keylen-16) / 4);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			crypto4xx_free_sa(ctx);
+			return rc;
+		}
+	}
+
+	/* Setup SA */
+	sa  =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	sa->sa_contents =3D SA_AES_CCM_CONTENTS | (keylen << 2);
+
+	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
+				 SA_CIPHER_ALG_AES,
+				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
+				 SA_OPCODE_HASH_DECRYPT, DIR_INBOUND);
+
+	sa->sa_command_0.bf.digest_len =3D 0;
+	sa->sa_command_1.bf.key_len =3D keylen >> 3;
+	ctx->direction =3D DIR_INBOUND;
+	ctx->append_icv =3D 0;
+	ctx->is_gcm =3D 0;
+	ctx->hash_final =3D 1;
+	ctx->is_hash =3D 0;
+	ctx->pd_ctl =3D 0x11;
+
+	crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+			    key, keylen);
+	memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+	       (void *)&ctx->state_record_dma_addr, 4);
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+
+	set_dynamic_sa_command_1(sa, CRYPTO_MODE_AES_CTR, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_CBC_MAC,
+				 SA_CIPHER_ALG_AES,
+				 SA_PAD_TYPE_ZERO, SA_OP_GROUP_BASIC,
+				 SA_OPCODE_ENCRYPT_HASH, DIR_OUTBOUND);
+	set_dynamic_sa_command_1(sa, CRYPTO_MODE_AES_CTR, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+
+	return 0;
+}
+
+int crypto4xx_encrypt_aes_ccm(struct aead_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+	struct crypto_aead *aead =3D crypto_aead_reqtfm(req);
+	struct dynamic_sa_ctl *sa;
+
+	ctx->direction =3D DIR_OUTBOUND;
+
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	if (req->assoclen)
+		sa->sa_command_1.bf.hash_crypto_offset =3D req->assoclen >> 2;
+
+	sa->sa_command_0.bf.digest_len =3D (crypto_aead_authsize(aead) >> 2);
+	if ((req->iv[0] & 7) =3D=3D 1)
+		sa->sa_command_1.bf.crypto_mode9_8 =3D 1;
+
+	ctx->append_icv =3D 1;
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->cryptlen, req->assoc, req->assoclen,
+				  req->iv, 16);
+}
+
+int crypto4xx_decrypt_aes_ccm(struct aead_request *req)
+{
+	struct crypto4xx_ctx   *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+	struct crypto_aead *aead =3D crypto_aead_reqtfm(req);
+	struct dynamic_sa_ctl *sa;
+
+	/* Support only counter field length of 2 and 4 bytes */
+	if ((req->iv[0] & 0x7) !=3D 1 && (req->iv[0] & 0x7) !=3D 3) {
+		printk(KERN_ERR "algorithm AES-CCM "
+				"unsupported counter length %d\n",
+			req->iv[0] & 0x7);
+		return -EINVAL;
+	}
+
+	ctx->direction =3D DIR_INBOUND;
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+
+	sa->sa_command_0.bf.digest_len =3D (crypto_aead_authsize(aead) >> 2);
+	if ((req->iv[0] & 7) =3D=3D 1)
+		sa->sa_command_1.bf.crypto_mode9_8 =3D 1;
+	else
+		sa->sa_command_1.bf.crypto_mode9_8 =3D 0;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->cryptlen, req->assoc, req->assoclen,
+				  req->iv, 16);
+}
+
+int crypto4xx_givencrypt_aes_ccm(struct aead_givcrypt_request *req)
+{
+	return -ENOSYS;
+}
+
+int crypto4xx_givdecrypt_aes_ccm(struct aead_givcrypt_request *req)
+{
+	return -ENOSYS;
+}
+
+/**
+ * Kasumi Functions
+ *
+ */
+int crypto4xx_setkey_kasumi(struct crypto_ablkcipher *cipher,
+				   const u8 *key,
+				   unsigned int keylen,
+				   unsigned char cm)
+{
+	struct crypto_tfm *tfm =3D crypto_ablkcipher_tfm(cipher);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	u32 sa_len =3D 0;
+	int rc;
+
+	if (keylen !=3D 16) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		printk(KERN_ERR "%s: keylen fail\n", __func__);
+		return -EINVAL;
+	}
+
+	/* Create SA - SA is created here as the alg init function is
+	 * common to many algorithm and it does not have the SA length
+	 * as it is specify to an algorithm. See setkey function has
+	 * to be called for encryption/decryption algorithm once,
+	 * it is okay to do this here.
+	 */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		 crypto4xx_free_sa(ctx);
+
+	if (cm =3D=3D CRYPTO_MODE_KASUMI)
+		 sa_len =3D SA_KASUMI_LEN;
+	else if (cm =3D=3D CRYPTO_MODE_KASUMI_f8)
+		 sa_len =3D SA_KASUMI_F8_LEN;
+
+	rc =3D crypto4xx_alloc_sa(ctx, sa_len);
+	if (rc)
+		return rc;
+
+	if (!ctx->state_record) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			crypto4xx_free_sa(ctx);
+			return rc;
+		}
+	}
+
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	/* Setup SA - SA is a shared resource for request operation. As
+	 * crypto alg and crypto mode can not be change, it should be
+	 * ok to store them there. SA control words are not used by the
+	 * hardware (configured in token instead), we use it to store
+	 * software algorithm and mode selected.
+	 */
+
+	if (cm =3D=3D CRYPTO_MODE_KASUMI) {
+		sa->sa_contents =3D SA_KASUMI_CONTENTS;
+		sa->sa_command_0.bf.cipher_alg =3D SA_CIPHER_ALG_KASUMI;
+		sa->sa_command_0.bf.hash_alg =3D SA_HASH_ALG_NULL;
+		sa->sa_command_0.bf.pad_type =3D 3; /* set to zero padding */
+		sa->sa_command_0.bf.opcode =3D 0;
+		sa->sa_command_1.bf.crypto_mode31 =3D (cm & 4) >> 2;
+		sa->sa_command_1.bf.crypto_mode9_8 =3D (cm & 3);
+		sa->sa_command_1.bf.feedback_mode =3D 0;
+	} else {
+		sa->sa_contents =3D SA_KASUMI_F8_CONTENTS;
+		sa->sa_command_0.bf.cipher_alg =3D SA_CIPHER_ALG_KASUMI;
+		sa->sa_command_0.bf.hash_alg =3D SA_HASH_ALG_NULL;
+		sa->sa_command_0.bf.pad_type =3D 3;
+		sa->sa_command_0.bf.load_iv =3D SA_LOAD_IV_FROM_STATE;
+		sa->sa_command_0.bf.opcode =3D SA_OPCODE_ENCRYPT;
+		sa->sa_command_1.bf.crypto_mode31 =3D (cm & 4) >> 2;;
+		sa->sa_command_1.bf.crypto_mode9_8 =3D (cm & 3);
+		sa->sa_command_1.bf.feedback_mode =3D 0;
+		sa->sa_command_1.bf.mutable_bit_proc =3D 1;
+	}
+
+	ctx->direction =3D DIR_INBOUND;
+	sa->sa_command_1.bf.sa_rev =3D 1;
+	crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+			    key, keylen);
+	ctx->is_hash =3D 0;
+
+	memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+	       (void *)&ctx->state_record_dma_addr, 4);
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+	sa->sa_command_0.bf.dir =3D DIR_INBOUND;
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+
+	return 0;
+}
+
+int crypto4xx_setkey_kasumi_p(struct crypto_ablkcipher *cipher,
+					const u8 *key,
+					unsigned int keylen)
+{
+	return crypto4xx_setkey_kasumi(cipher, key, keylen,
+				       CRYPTO_MODE_KASUMI);
+}
+
+int crypto4xx_setkey_kasumi_f8(struct crypto_ablkcipher *cipher,
+					     const u8 *key,
+					     unsigned int keylen)
+{
+	return crypto4xx_setkey_kasumi(cipher, key, keylen,
+				       CRYPTO_MODE_KASUMI_f8);
+}
+
+/**
+ * Kasumi and Kasumi f8 work with number of bits.
+ * The crypto engine can only take number bytes as source/destination =
length
+ * User should round up bit number to byte number. When receive the =
result
+ * packet and then mask off the extra bits in the last
+ * byte.
+ */
+int crypto4xx_encrypt_kasumi(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+	ctx->direction =3D DIR_OUTBOUND;
+	ctx->pd_ctl =3D 0x1;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->nbytes, NULL, 0, NULL, 0);
+}
+
+/**
+ * Kasumi and Kasumi f8 work with number of bits.
+ * The crypto engine can only take number bytes as source/destination =
length
+ * User should round up bit number to byte number.
+ * When receive the result packet and then mask off the extra bits in =
the last
+ * byte.
+ */
+int crypto4xx_decrypt_kasumi(struct aead_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+
+	ctx->pd_ctl =3D 0x1;
+	ctx->direction =3D DIR_INBOUND;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->cryptlen, NULL, 0, NULL, 0);
+}
+
+/**
+ * Kasumi and Kasumi f8 work with number of bits.
+ * The crypto engine can only take number bytes as source/destination =
length
+ * The user should round up bit number to byte number.
+ * When receive the result packet and then mask
+ * off the extra bits in the last byte.
+ */
+int crypto4xx_encrypt_kasumi_f8(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+
+	ctx->direction =3D DIR_OUTBOUND;
+	ctx->is_hash =3D 0;
+	ctx->pd_ctl =3D 0x1;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->nbytes, NULL, 0, req->info, 8);
+}
+
+/** Note:
+ * Kasumi and Kasumi f8 work with number of bits.
+ * The crypto engine can only take number bytes as source/destination =
length
+ *  User should round up bit number to byte number.
+ * When receive the result packet and then mask off the extra bits in =
the last
+ * byte.
+ */
+int crypto4xx_decrypt_kasumi_f8(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+
+	ctx->direction =3D DIR_INBOUND;
+	ctx->is_hash =3D 0;
+	ctx->pd_ctl =3D 0x1;
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src, req->dst,
+				  req->nbytes, NULL, 0, req->info, 8);
+}
+
+/**
+ * ARC4 Functions
+ *
+ */
+int crypto4xx_setkey_arc4(struct crypto_ablkcipher *cipher,
+				 const u8 *key, unsigned int keylen)
+{
+	struct crypto_tfm *tfm =3D crypto_ablkcipher_tfm(cipher);
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	int rc =3D 0;
+
+	/* Create SA */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		crypto4xx_free_sa(ctx);
+
+	rc =3D crypto4xx_alloc_sa(ctx, SA_ARC4_LEN);
+	if (rc)
+		return rc;
+
+	crypto4xx_alloc_arc4_state_record(ctx);
+	if (ctx->arc4_state_record =3D=3D NULL) {
+		crypto4xx_free_sa(ctx);
+		return -ENOMEM;
+	}
+
+	/* Setup SA */
+	ctx->sa_len =3D SA_ARC4_LEN;
+	ctx->init_arc4 =3D 1;
+	ctx->direction =3D DIR_INBOUND;
+
+	sa =3D ctx->sa_in;
+	memset(((struct dynamic_sa_arc4 *)sa)->key, 0, 16);
+
+	crypto4xx_memcpy_le(((struct dynamic_sa_arc4 *)sa)->key, key, keylen);
+	sa->sa_contents =3D SA_ARC4_CONTENTS;
+
+	set_dynamic_sa_command_0(sa, SA_NOT_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_LOAD_HASH_FROM_SA, SA_LOAD_IV_FROM_STATE,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_NULL,
+				 SA_CIPHER_ALG_ARC4, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_ENCRYPT,
+				 DIR_INBOUND);
+
+	set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB,
+				 SA_EXTENDED_SN_OFF, SA_SEQ_MASK_OFF,
+				 SA_MC_ENABLE, SA_NOT_COPY_PAD,
+				 SA_COPY_PAYLOAD, SA_NOT_COPY_HDR);
+
+	sa->sa_command_1.bf.key_len =3D keylen;
+	memcpy(sa + get_dynamic_sa_offset_arc4_state_ptr(ctx),
+	       (void *)&ctx->arc4_state_record_dma_addr, 4);
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+
+	return 0;
+}
+
+int crypto4xx_arc4_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+
+	if (ctx->init_arc4) {
+		ctx->init_arc4 =3D 0;
+		ctx->pd_ctl =3D 9;
+	} else {
+		ctx->pd_ctl =3D 0x1;
+	}
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src,
+				  req->dst,
+				  req->nbytes, NULL, 0, NULL, 0);
+}
+
+int crypto4xx_arc4_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto4xx_ctx *ctx  =3D crypto_tfm_ctx(req->base.tfm);
+
+	if (ctx->init_arc4) {
+		ctx->init_arc4 =3D 0;
+		ctx->pd_ctl =3D 9;
+	} else {
+		ctx->pd_ctl =3D 0x1;
+	}
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src,
+				  req->dst,
+				  req->nbytes, NULL, 0, NULL, 0);
+}
+
+/**
+ * Support MD5/SHA/HMAC Hashing Algorithms
+ *
  */
 static int crypto4xx_hash_alg_init(struct crypto_tfm *tfm,
 				   unsigned int sa_len,
@@ -185,7 +1229,6 @@ static int crypto4xx_hash_alg_init(struct =
crypto_tfm *tfm,
 	struct crypto4xx_alg *my_alg =3D crypto_alg_to_crypto4xx_alg(alg);
 	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(tfm);
 	struct dynamic_sa_ctl *sa;
-	struct dynamic_sa_hash160 *sa_in;
 	int rc;
=20
 	ctx->dev   =3D my_alg->dev;
@@ -210,6 +1253,9 @@ static int crypto4xx_hash_alg_init(struct =
crypto_tfm *tfm,
=20
 	tfm->crt_ahash.reqsize =3D sizeof(struct crypto4xx_ctx);
 	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	/*
+	 * Setup hash algorithm and hash mode
+	 */
 	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
 				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
 				 SA_NO_HEADER_PROC, ha, SA_CIPHER_ALG_NULL,
@@ -220,13 +1266,12 @@ static int crypto4xx_hash_alg_init(struct =
crypto_tfm *tfm,
 				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
 				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
 				 SA_NOT_COPY_HDR);
+
+	BUG_ON(ha >=3D HASH_ALG_MAX_CNT);
+	sa->sa_contents =3D crypto4xx_sa_hash_tbl[0][ha];
 	ctx->direction =3D DIR_INBOUND;
-	sa->sa_contents =3D SA_HASH160_CONTENTS;
-	sa_in =3D (struct dynamic_sa_hash160 *) ctx->sa_in;
-	/* Need to zero hash digest in SA */
-	memset(sa_in->inner_digest, 0, sizeof(sa_in->inner_digest));
-	memset(sa_in->outer_digest, 0, sizeof(sa_in->outer_digest));
-	sa_in->state_ptr =3D ctx->state_record_dma_addr;
+	memcpy(ctx->sa_in + get_dynamic_sa_offset_state_ptr_field(ctx),
+		(void *)&ctx->state_record_dma_addr, 4);
 	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
=20
 	return 0;
@@ -260,7 +1305,7 @@ int crypto4xx_hash_update(struct ahash_request =
*req)
=20
 	return crypto4xx_build_pd(&req->base, ctx, req->src,
 				  (struct scatterlist *) req->result,
-				  req->nbytes, NULL, 0);
+				  req->nbytes, NULL, 0, NULL, 0);
 }
=20
 int crypto4xx_hash_final(struct ahash_request *req)
@@ -278,16 +1323,431 @@ int crypto4xx_hash_digest(struct ahash_request =
*req)
=20
 	return crypto4xx_build_pd(&req->base, ctx, req->src,
 				  (struct scatterlist *) req->result,
-				  req->nbytes, NULL, 0);
+				  req->nbytes, NULL, 0, NULL, 0);
 }
=20
 /**
  * SHA1 Algorithm
  */
+
+int crypto4xx_md5_alg_init(struct crypto_tfm *tfm)
+{
+	return crypto4xx_hash_alg_init(tfm, SA_HASH128_LEN, SA_HASH_ALG_MD5,
+				       SA_HASH_MODE_HASH);
+}
+
+int crypto4xx_hash_hmac_setkey(struct crypto_ahash *hash,
+				      const u8 *key,
+				      unsigned int keylen,
+				      unsigned int sa_len,
+				      unsigned char ha,
+				      unsigned char hm,
+				      unsigned int max_keylen)
+{
+	struct crypto_tfm	*tfm =3D crypto_ahash_tfm(hash);
+	struct crypto_alg	*alg	 =3D tfm->__crt_alg;
+	struct crypto4xx_alg   *my_alg   =3D crypto_alg_to_crypto4xx_alg(alg);
+	struct crypto4xx_ctx	*ctx =3D crypto_tfm_ctx(tfm);
+	struct dynamic_sa_ctl *sa;
+	int bs 	=3D crypto_tfm_alg_blocksize(tfm);
+	int ds 	=3D crypto_ahash_digestsize(hash);
+	int rc;
+
+	ctx->dev =3D my_alg->dev;
+
+	if (keylen > max_keylen) {
+		crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -1;
+	}
+
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		crypto4xx_free_sa(ctx);
+
+	/* Create SA */
+	rc =3D crypto4xx_alloc_sa(ctx, sa_len);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc)
+			goto err;
+	}
+
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+
+	/*
+	 * Setup hash algorithm and hash mode
+	 */
+	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
+				 SA_NO_HEADER_PROC,
+				 ha, SA_CIPHER_ALG_NULL, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_HASH,
+				 DIR_INBOUND);
+	set_dynamic_sa_command_1(sa, 0, hm,
+				 CRYPTO_FEEDBACK_MODE_NO_FB,
+				 SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+
+	BUG_ON(ha >=3D HASH_ALG_MAX_CNT);
+	sa->sa_contents =3D crypto4xx_sa_hash_tbl[0][ha];
+	ctx->direction =3D DIR_INBOUND;
+	memcpy((ctx->sa_in) + get_dynamic_sa_offset_state_ptr_field(ctx),
+	       (void *)&ctx->state_record_dma_addr, 4);
+
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+	rc =3D crypto4xx_pre_compute_hmac(ctx, (void *)key, keylen, bs, ha, =
ds);
+	if (rc) {
+		printk(KERN_ERR "Hmac Initial Digest Calculation failed\n");
+		goto err;
+	}
+
+	ctx->hash_final =3D 1;
+	ctx->is_hash =3D 1;
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+
+	return 0;
+err:
+	crypto4xx_free_sa(ctx);
+	return rc;
+}
+
+int crypto4xx_md5_hmac_setkey(struct crypto_ahash *hash, const u8 *key,
+			      unsigned int keylen)
+{
+	return crypto4xx_hash_hmac_setkey(hash, key, keylen, SA_HASH128_LEN,
+					  SA_HASH_ALG_MD5, SA_HASH_MODE_HMAC,
+					  256);
+}
+
+/**
+ * SHA1 and SHA2 Algorithm
+ *
+ */
 int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm)
 {
 	return crypto4xx_hash_alg_init(tfm, SA_HASH160_LEN, SA_HASH_ALG_SHA1,
 				       SA_HASH_MODE_HASH);
 }
=20
+int crypto4xx_sha1_hmac_setkey(struct crypto_ahash *hash, const u8 =
*key,
+			       unsigned int keylen)
+{
+	return crypto4xx_hash_hmac_setkey(hash, key, keylen, SA_HASH160_LEN,
+					  SA_HASH_ALG_SHA1, SA_HASH_MODE_HMAC,
+					  256);
+}
+
+int crypto4xx_sha2_alg_init(struct crypto_tfm *tfm)
+{
+	int ds =3D crypto_ahash_digestsize(__crypto_ahash_cast(tfm));
+	u8 ha;
+
+	switch (ds) {
+	default:
+	case 256/8:
+		ha =3D SA_HASH_ALG_SHA256;
+		break;
+	case 224/8:
+		ha =3D SA_HASH_ALG_SHA224;
+		break;
+	case 512/8:
+		ha =3D SA_HASH_ALG_SHA512;
+		break;
+	case 384/8:
+		ha =3D SA_HASH_ALG_SHA384;
+		break;
+	}
+	BUG_ON(ha >=3D HASH_ALG_MAX_CNT);
+
+	return crypto4xx_hash_alg_init(tfm,
+				       crypto4xx_sa_hash_tbl[2][ha], ha, 0);
+}
+
+int crypto4xx_sha2_hmac_setkey(struct crypto_ahash *hash,
+				      const u8 *key,
+				      unsigned int keylen)
+{
+	int ds =3D crypto_ahash_digestsize(hash);
+	unsigned char ha;
+
+	switch (ds) {
+	default:
+	case 256/8:
+		ha =3D SA_HASH_ALG_SHA256;
+		break;
+	case 224/8:
+		ha =3D SA_HASH_ALG_SHA224;
+		break;
+	case 512/8:
+		ha =3D SA_HASH_ALG_SHA512;
+		break;
+	case 384/8:
+		ha =3D SA_HASH_ALG_SHA384;
+		break;
+	}
+	BUG_ON(ha >=3D HASH_ALG_MAX_CNT);
+
+	return crypto4xx_hash_hmac_setkey(hash, key, keylen,
+					  crypto4xx_sa_hash_tbl[2][ha],
+					  ha,
+					  SA_HASH_MODE_HMAC,
+					  512);
+}
+
+/**
+ * AES-XCBC-MAC Algorithm
+ *
+ */
+int crypto4xx_xcbc_digest(const unsigned char *key,
+			  unsigned int keylen,
+			  u8 *sa_hash, int bs)
+{
+	struct scatterlist 	sg[1];
+	struct crypto_blkcipher *aes_tfm =3D NULL;
+	struct blkcipher_desc 	desc;
+	int rc;
+	u8 *digest;
+
+	/* Load pre-computed key value into SA */
+	aes_tfm =3D crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC);
+	if (IS_ERR(aes_tfm)) {
+		rc =3D PTR_ERR(aes_tfm);
+		printk(KERN_ERR "failed to load transform"
+				" for ecb(aes) error %d\n", rc);
+		goto err_alg;
+	}
+	desc.tfm    =3D aes_tfm;
+	desc.flags  =3D 0;
+	rc =3D crypto_blkcipher_setkey(desc.tfm, key, keylen);
+	if (rc) {
+		printk(KERN_ERR  "failed to load key error %d\n", rc);
+		goto err_alg;
+	}
+	digest =3D  kmalloc(16, GFP_KERNEL);
+	if (digest =3D=3D NULL) {
+		rc =3D -ENOMEM;
+		goto err_alg;
+	}
+
+	memset(digest, 0x01, bs);
+	sg_init_one(&sg[0], digest, bs);
+	rc =3D crypto_blkcipher_encrypt(&desc, sg, sg, bs);
+	if (rc < 0) {
+		printk(KERN_ERR "failed to hash key error %d\n", rc);
+		goto err_alg;
+	}
+
+	crypto4xx_memcpy_le((void *) sa_hash, digest, bs);
+
+	memset(digest, 0x02, bs);
+	sg_init_one(&sg[0], digest, bs);
+	rc =3D crypto_blkcipher_encrypt(&desc, sg, sg, bs);
+	if (rc < 0) {
+		printk(KERN_ERR "failed to hash key error %d\n", rc);
+		goto err_alg;
+	}
+
+	sa_hash +=3D 32;
+	crypto4xx_memcpy_le((void *) sa_hash, digest, bs);
+
+	memset(digest, 0x03, bs);
+	sg_init_one(&sg[0], digest, bs);
+	rc =3D crypto_blkcipher_encrypt(&desc, sg, sg, bs);
+	if (rc < 0) {
+		printk(KERN_ERR "failed to hash key error %d\n", rc);
+		goto err_alg;
+	}
+
+	sa_hash +=3D 16;
+	crypto4xx_memcpy_le((void *) sa_hash, digest, bs);
+
+	crypto_free_blkcipher(aes_tfm);
+
+	return 0;
+err_alg:
+	if (aes_tfm)
+		crypto_free_blkcipher(aes_tfm);
+	return rc;
+}
+
+int crypto4xx_xcbc_setkey(struct crypto_ahash *hash,
+				      const u8 *key,
+				      unsigned int keylen)
+{
+	struct crypto_tfm    	*tfm =3D crypto_ahash_tfm(hash);
+	struct crypto4xx_ctx 	*ctx =3D crypto_tfm_ctx(tfm);
+	int bs =3D crypto_tfm_alg_blocksize(tfm);
+	struct dynamic_sa_ctl *sa;
+	u8 *sa_hash;
+	int rc =3D 0;
+
+	if (keylen !=3D 128/8) {
+		crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		 crypto4xx_free_sa(ctx);
+
+	/* Create SA */
+	rc =3D crypto4xx_alloc_sa(ctx, SA_AES128_XCBC_MAC_LEN);
+	if (rc)
+		return rc;
=20
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			rc =3D -ENOMEM;
+			goto err;
+		}
+	}
+
+	ctx->direction =3D DIR_INBOUND;
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	/*
+	 * Setup hash algorithm and hash mode
+	 */
+	sa->sa_contents =3D SA_AES128_XCBC_MAC_CONTENTS;
+	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
+				 SA_NO_HEADER_PROC,
+				 SA_HASH_ALG_AES_XCBC_MAC_128,
+				 SA_CIPHER_ALG_NULL, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_HASH,
+				 DIR_INBOUND);
+	set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB,
+				 SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+	crypto4xx_memcpy_le(ctx->sa_in + get_dynamic_sa_offset_key_field(ctx),
+			    key, keylen);
+
+	memcpy((void *)(ctx->sa_in +
+			get_dynamic_sa_offset_state_ptr_field(ctx)),
+		(void *)&ctx->state_record_dma_addr, 4);
+	ctx->is_hash =3D 1;
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+	sa_hash =3D (u8 *)(&(((struct dynamic_sa_aes128_xcbc_mac *)
+			ctx->sa_in)->inner_digest));
+	rc =3D crypto4xx_xcbc_digest(key, keylen, sa_hash, bs);
+	if (rc) {
+		printk(KERN_ERR "XCBC Digest Calculation Failed %d\n", rc);
+		goto err;
+	}
+
+	ctx->is_hash =3D 1;
+	ctx->hash_final =3D 1;
+	ctx->pd_ctl =3D 0x11;
+
+	ctx->direction =3D DIR_INBOUND;
+
+	memcpy(ctx->sa_out, ctx->sa_in, ctx->sa_len * 4);
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_out;
+	sa->sa_command_0.bf.dir =3D DIR_OUTBOUND;
+
+	return 0;
+err:
+	crypto4xx_free_sa(ctx);
+	return rc;
+}
+
+/**
+ * Kasumi F9 - Hash Algorithms
+ *
+ */
+int crypto4xx_kasumi_f9_setkey(struct crypto_ahash *hash,
+			       const u8 *key, unsigned int keylen)
+{
+	struct crypto_tfm	*tfm =3D crypto_ahash_tfm(hash);
+	struct crypto4xx_ctx	*ctx =3D crypto_tfm_ctx(tfm);
+	int 	rc;
+	struct dynamic_sa_ctl *sa;
+
+	if (keylen !=3D 16) {
+		crypto_ahash_set_flags(hash, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	/* Create SA */
+	if (ctx->sa_in_dma_addr || ctx->sa_out_dma_addr)
+		 crypto4xx_free_sa(ctx);
+
+	rc =3D crypto4xx_alloc_sa(ctx, SA_KASUMI_F9_LEN);
+	if (rc)
+		return rc;
+
+	if (ctx->state_record_dma_addr =3D=3D 0) {
+		rc =3D crypto4xx_alloc_state_record(ctx);
+		if (rc) {
+			crypto4xx_free_sa(ctx);
+			return rc;
+		}
+	}
+
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+	/*
+	 * Setup hash algorithm and hash mode
+	 */
+	set_dynamic_sa_command_0(sa, SA_SAVE_HASH, SA_NOT_SAVE_IV,
+				 SA_NOT_LOAD_HASH, SA_LOAD_IV_FROM_SA,
+				 SA_NO_HEADER_PROC, SA_HASH_ALG_KASUMI_f9,
+				 SA_CIPHER_ALG_NULL, SA_PAD_TYPE_ZERO,
+				 SA_OP_GROUP_BASIC, SA_OPCODE_HASH,
+				 DIR_INBOUND);
+	set_dynamic_sa_command_1(sa, 0, SA_HASH_MODE_HASH,
+				 CRYPTO_FEEDBACK_MODE_NO_FB, SA_EXTENDED_SN_OFF,
+				 SA_SEQ_MASK_OFF, SA_MC_ENABLE,
+				 SA_NOT_COPY_PAD, SA_NOT_COPY_PAYLOAD,
+				 SA_NOT_COPY_HDR);
+	sa->sa_contents =3D SA_KASUMI_F9_CONTENTS;
+
+	ctx->direction =3D DIR_INBOUND;
+	memcpy((void *)(ctx->sa_in +
+			get_dynamic_sa_offset_state_ptr_field(ctx)),
+			(void *)&ctx->state_record_dma_addr, 4);
+
+	crypto4xx_memcpy_le(ctx->sa_in +
+			get_dynamic_sa_offset_inner_digest(ctx), key, keylen);
+	ctx->offset_to_sr_ptr =3D get_dynamic_sa_offset_state_ptr_field(ctx);
+	ctx->is_hash =3D 1;
+	ctx->hash_final =3D 1;
+	ctx->pd_ctl =3D 0x11;
+	ctx->bypass =3D 4;
+
+	return 0;
+}
+
+int crypto4xx_kasumi_f9_digest(struct ahash_request *req)
+{
+	struct crypto4xx_ctx *ctx =3D crypto_tfm_ctx(req->base.tfm);
+	struct scatterlist *src =3D req->src;
+	struct dynamic_sa_ctl *sa;
+	dma_addr_t addr;
+
+	/*
+	 * We have prepended count/fresh/direction/reserv total
+	 * 16byte before the plaintext
+	 * so, need to modify the length.
+	 * We doing so, to make use of tcrypt.c's hash_test.
+	 */
+	sa =3D (struct dynamic_sa_ctl *) ctx->sa_in;
+
+	addr =3D dma_map_page(NULL, sg_page(src), src->offset,
+			    src->length, DMA_TO_DEVICE);
+	crypto4xx_memcpy_le((void *)sa +
+			get_dynamic_sa_offset_outer_digest(ctx),
+			phys_to_virt(addr), 12);
+
+	return crypto4xx_build_pd(&req->base, ctx, req->src,
+				  (struct scatterlist *)req->result,
+				  req->nbytes, NULL, 0, NULL, 0);
+}
diff --git a/drivers/crypto/amcc/crypto4xx_core.c =
b/drivers/crypto/amcc/crypto4xx_core.c
index 4c0dfb2..0fef1f2 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -28,13 +28,18 @@
 #include <linux/platform_device.h>
 #include <linux/init.h>
 #include <linux/of_platform.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/highmem.h>
 #include <asm/dcr.h>
 #include <asm/dcr-regs.h>
 #include <asm/cacheflush.h>
 #include <crypto/internal/hash.h>
 #include <crypto/algapi.h>
 #include <crypto/aes.h>
+#include <crypto/des.h>
 #include <crypto/sha.h>
+#include <crypto/ctr.h>
 #include "crypto4xx_reg_def.h"
 #include "crypto4xx_core.h"
 #include "crypto4xx_sa.h"
@@ -153,6 +158,8 @@ void crypto4xx_free_sa(struct crypto4xx_ctx *ctx)
=20
 	ctx->sa_in_dma_addr =3D 0;
 	ctx->sa_out_dma_addr =3D 0;
+	ctx->sa_in =3D NULL;
+	ctx->sa_out =3D NULL;
 	ctx->sa_len =3D 0;
 }
=20
@@ -178,6 +185,31 @@ void crypto4xx_free_state_record(struct =
crypto4xx_ctx *ctx)
 	ctx->state_record_dma_addr =3D 0;
 }
=20
+u32 crypto4xx_alloc_arc4_state_record(struct crypto4xx_ctx *ctx)
+{
+	ctx->arc4_state_record =3D =
dma_alloc_coherent(ctx->dev->core_dev->device,
+			sizeof(struct arc4_sr),
+			&ctx->arc4_state_record_dma_addr,
+			GFP_ATOMIC);
+	if (!ctx->arc4_state_record_dma_addr)
+		return -ENOMEM;
+
+	memset(ctx->arc4_state_record, 0, sizeof(struct arc4_sr));
+
+	return 0;
+}
+
+void crypto4xx_free_arc4_state_record(struct crypto4xx_ctx *ctx)
+{
+	if (ctx->arc4_state_record !=3D NULL) {
+		dma_free_coherent(ctx->dev->core_dev->device,
+				  sizeof(struct arc4_sr),
+				  ctx->arc4_state_record,
+				  ctx->arc4_state_record_dma_addr);
+	}
+	ctx->arc4_state_record_dma_addr =3D 0;
+}
+
 /**
  * alloc memory for the gather ring
  * no need to alloc buf for the ring
@@ -528,7 +560,7 @@ static u32 crypto4xx_fill_one_page(struct =
crypto4xx_device *dev,
 			(*idx)++;
=20
 		return 0;
-    }
+	}
 }
=20
 static void crypto4xx_copy_pkt_to_dst(struct crypto4xx_device *dev,
@@ -591,9 +623,25 @@ static u32 crypto4xx_copy_digest_to_dst(struct =
pd_uinfo *pd_uinfo,
 	struct sa_state_record *state_record =3D
 				(struct sa_state_record *) pd_uinfo->sr_va;
=20
-	if (sa->sa_command_0.bf.hash_alg =3D=3D SA_HASH_ALG_SHA1) {
-		memcpy((void *) pd_uinfo->dest_va, state_record->save_digest,
-		       SA_HASH_ALG_SHA1_DIGEST_SIZE);
+	switch (sa->sa_command_0.bf.hash_alg) {
+	case SA_HASH_ALG_KASUMI_f9:
+		crypto4xx_memcpy_le((void *)pd_uinfo->dest_va,
+				     (u8 *)state_record->save_digest, 8);
+		break;
+	case SA_HASH_ALG_AES_XCBC_MAC_128:
+		crypto4xx_memcpy_le((void *)pd_uinfo->dest_va,
+				     (u8 *) state_record->save_digest, 16);
+		break;
+	case SA_HASH_ALG_MD5:
+		crypto4xx_memcpy_le((void *)pd_uinfo->dest_va,
+				     (u8 *) state_record->save_digest,
+				     SA_HASH_ALG_MD5_DIGEST_SIZE);
+		break;
+	default:
+		memcpy((void *)pd_uinfo->dest_va,
+			state_record->save_digest,
+			crypto4xx_sa_hash_tbl[1][sa->sa_command_0.bf.hash_alg]);
+		break;
 	}
=20
 	return 0;
@@ -618,6 +666,57 @@ static void crypto4xx_ret_sg_desc(struct =
crypto4xx_device *dev,
 	}
 }
=20
+void crypto4xx_append_icv_to_end(struct crypto4xx_device *dev,
+				 struct scatterlist *dst,
+				 struct sa_state_record *sr,
+				 u32 offset,
+				 u32 len)
+{
+	struct scatterlist *sg;
+	int i =3D 0;
+	u32 cp_len;
+	dma_addr_t addr;
+
+	sg =3D &dst[i];
+	while (len) {
+		while (sg->length < offset) {
+			offset -=3D sg->length;
+			i++;
+			sg =3D &sg[i];
+		}
+		/* at here, icv could be in this sg,
+		* or icv could be in the next sg
+		*/
+		if (sg->length > offset) {
+			/* icv should be in middle of this sg */
+			addr =3D dma_map_page(dev->core_dev->device, sg_page(sg),
+					    sg->offset,
+					    sg->length, DMA_TO_DEVICE);
+			cp_len =3D (sg->length-offset >=3D len) ? len :
+					sg->length-offset;
+			len -=3D cp_len;
+			crypto4xx_memcpy_le((u32 *)(phys_to_virt(addr)
+					+ offset),
+					(u8 *)sr->save_digest, cp_len);
+		} else {
+			/* start from begin of next sg*/
+			i++;
+			sg =3D &sg[i];
+			offset =3D 0;
+			addr =3D dma_map_page(dev->core_dev->device, sg_page(sg),
+					    sg->offset,
+					    sg->length, DMA_FROM_DEVICE);
+			cp_len =3D (sg->length >=3D len) ? len : sg->length;
+			len -=3D cp_len;
+			crypto4xx_memcpy_le((u32 *) (phys_to_virt(addr)
+					+ offset),
+					(u8 *) sr->save_digest, cp_len);
+		}
+		i++;
+		sg =3D &sg[i];
+	}
+}
+
 static u32 crypto4xx_ablkcipher_done(struct crypto4xx_device *dev,
 				     struct pd_uinfo *pd_uinfo,
 				     struct ce_pd *pd)
@@ -664,18 +763,67 @@ static u32 crypto4xx_ahash_done(struct =
crypto4xx_device *dev,
 	return 0;
 }
=20
-static u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx)
+static u32 crypto4xx_aead_done(struct crypto4xx_device *dev,
+			struct pd_uinfo *pd_uinfo,
+			struct ce_pd *pd)
+{
+	struct aead_request *aead_req;
+	struct crypto4xx_ctx *ctx;
+	struct scatterlist *dst;
+	dma_addr_t addr;
+	struct crypto_aead *aead;
+
+	aead_req =3D container_of(pd_uinfo->async_req,
+				struct aead_request, base);
+	aead =3D crypto_aead_reqtfm(aead_req);
+	ctx  =3D crypto_tfm_ctx(aead_req->base.tfm);
+
+	if (pd_uinfo->using_sd) {
+		crypto4xx_copy_pkt_to_dst(dev, pd, pd_uinfo,
+					  pd->pd_ctl_len.bf.pkt_len,
+					  aead_req->dst);
+	} else {
+		dst =3D pd_uinfo->dest_va;
+		addr =3D dma_map_page(dev->core_dev->device, sg_page(dst),
+				    dst->offset,
+				    dst->length, DMA_FROM_DEVICE);
+	}
+
+	if (ctx->append_icv !=3D 0) {
+		dst =3D pd_uinfo->dest_va;
+		crypto4xx_append_icv_to_end(dev, dst,
+					    (struct sa_state_record *)
+					    pd_uinfo->sr_va,
+					    aead_req->cryptlen,
+					    crypto_aead_authsize(aead));
+	}
+	crypto4xx_ret_sg_desc(dev, pd_uinfo);
+	/* call user provided callback function x */
+	if (aead_req->base.complete !=3D NULL)
+		aead_req->base.complete(&aead_req->base, 0);
+
+	return 0;
+}
+
+u32 crypto4xx_pd_done(struct crypto4xx_device *dev, u32 idx)
 {
 	struct ce_pd *pd;
 	struct pd_uinfo *pd_uinfo;
=20
 	pd =3D  dev->pdr + sizeof(struct ce_pd)*idx;
 	pd_uinfo =3D dev->pdr_uinfo + sizeof(struct pd_uinfo)*idx;
+
 	if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) =3D=3D
+			CRYPTO_ALG_TYPE_AEAD)
+		return crypto4xx_aead_done(dev, pd_uinfo, pd);
+	else if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) =3D=3D
 			CRYPTO_ALG_TYPE_ABLKCIPHER)
 		return crypto4xx_ablkcipher_done(dev, pd_uinfo, pd);
-	else
+	else if (crypto_tfm_alg_type(pd_uinfo->async_req->tfm) =3D=3D
+			CRYPTO_ALG_TYPE_AHASH)
 		return crypto4xx_ahash_done(dev, pd_uinfo);
+
+	return 0;
 }
=20
 /**
@@ -777,12 +925,15 @@ u32 crypto4xx_build_pd(struct crypto_async_request =
*req,
 		       struct scatterlist *src,
 		       struct scatterlist *dst,
 		       unsigned int datalen,
+		       struct scatterlist *assoc,
+		       u32 aad_len,
 		       void *iv, u32 iv_len)
 {
 	struct crypto4xx_device *dev =3D ctx->dev;
 	dma_addr_t addr, pd_dma, sd_dma, gd_dma;
 	struct dynamic_sa_ctl *sa;
 	struct scatterlist *sg;
+	struct scatterlist *aad;
 	struct ce_gd *gd;
 	struct ce_pd *pd;
 	u32 num_gd, num_sd;
@@ -792,13 +943,18 @@ u32 crypto4xx_build_pd(struct crypto_async_request =
*req,
 	unsigned long flags;
 	struct pd_uinfo *pd_uinfo =3D NULL;
 	unsigned int nbytes =3D datalen, idx;
-	unsigned int ivlen =3D 0;
 	u32 gd_idx =3D 0;
+	unsigned int aadlen =3D 0;
=20
 	/* figure how many gd is needed */
-	num_gd =3D get_sg_count(src, datalen);
-	if (num_gd =3D=3D 1)
-		num_gd =3D 0;
+	if (aad_len) {
+		num_gd =3D get_sg_count(assoc, aad_len) +
+				get_sg_count(src, datalen);
+	} else {
+		num_gd =3D get_sg_count(src, datalen);
+		if (num_gd =3D=3D 1)
+			num_gd =3D 0;
+	}
=20
 	/* figure how many sd is needed */
 	if (sg_is_last(dst) || ctx->is_hash) {
@@ -855,7 +1011,6 @@ u32 crypto4xx_build_pd(struct crypto_async_request =
*req,
 	pd_uinfo->num_sd =3D num_sd;
=20
 	if (iv_len || ctx->is_hash) {
-		ivlen =3D iv_len;
 		pd->sa =3D pd_uinfo->sa_pa;
 		sa =3D (struct dynamic_sa_ctl *) pd_uinfo->sa_va;
 		if (ctx->direction =3D=3D DIR_INBOUND)
@@ -866,8 +1021,26 @@ u32 crypto4xx_build_pd(struct crypto_async_request =
*req,
 		memcpy((void *) sa + ctx->offset_to_sr_ptr,
 			&pd_uinfo->sr_pa, 4);
=20
-		if (iv_len)
-			crypto4xx_memcpy_le(pd_uinfo->sr_va, iv, iv_len);
+		if (iv_len) {
+			if (ctx->ctr_aes) {
+				/* First the nonce */
+				memcpy(pd_uinfo->sr_va, ctx->state_record,
+				       CTR_RFC3686_NONCE_SIZE);
+				/* Copy the IV that is passed through
+				 * each operation
+				 */
+				crypto4xx_memcpy_le(pd_uinfo->sr_va +
+					CTR_RFC3686_NONCE_SIZE, iv, iv_len);
+			} else
+				crypto4xx_memcpy_le(pd_uinfo->sr_va,
+						iv, iv_len);
+		}
+		if (ctx->is_gcm || ctx->ctr_aes) {
+			u32 seq =3D 1;
+			/*For GCM and CTR(AES) algs adding the counter value*/
+			crypto4xx_memcpy_le(pd_uinfo->sr_va + 12,
+					    (void *)&seq,  4);
+		}
 	} else {
 		if (ctx->direction =3D=3D DIR_INBOUND) {
 			pd->sa =3D ctx->sa_in_dma_addr;
@@ -888,6 +1061,35 @@ u32 crypto4xx_build_pd(struct crypto_async_request =
*req,
 		/* enable gather */
 		sa->sa_command_0.bf.gather =3D 1;
 		idx =3D 0;
+		if (aad_len) {
+			aadlen =3D aad_len;
+			aad =3D assoc;
+			/* walk the sg, and setup gather array for aad*/
+			while (aadlen) {
+				sg =3D &aad[idx];
+				addr =3D dma_map_page(dev->core_dev->device,
+						sg_page(sg), sg->offset,
+						sg->length, DMA_TO_DEVICE);
+
+				gd->ptr =3D addr;
+				gd->ctl_len.len =3D sg->length;
+				gd->ctl_len.done =3D 0;
+				gd->ctl_len.ready =3D 1;
+
+				if (sg->length >=3D aadlen)
+					break;
+
+				aadlen -=3D sg->length;
+
+				gd_idx =3D get_next_gd(gd_idx);
+				gd =3D crypto4xx_get_gdp(dev, &gd_dma, gd_idx);
+				idx++;
+			}
+			/* prepare gd for src */
+			gd_idx =3D get_next_gd(gd_idx);
+			gd =3D crypto4xx_get_gdp(dev, &gd_dma, gd_idx);
+		}
+		idx =3D 0;
 		src =3D &src[0];
 		/* walk the sg, and setup gather array */
 		while (nbytes) {
@@ -972,9 +1174,10 @@ u32 crypto4xx_build_pd(struct crypto_async_request =
*req,
 		}
 	}
=20
-	sa->sa_command_1.bf.hash_crypto_offset =3D 0;
+	sa->sa_command_1.bf.hash_crypto_offset =3D (aad_len >> 2);
 	pd->pd_ctl.w =3D ctx->pd_ctl;
-	pd->pd_ctl_len.w =3D 0x00400000 | (ctx->bypass << 24) | datalen;
+	pd->pd_ctl_len.w =3D 0x00400000 | (ctx->bypass << 24) |
+			(datalen + aad_len);
 	pd_uinfo->state =3D PD_ENTRY_INUSE;
 	wmb();
 	/* write any value to push engine to read a pd */
@@ -997,11 +1200,15 @@ static int crypto4xx_alg_init(struct crypto_tfm =
*tfm)
 	ctx->sa_in_dma_addr =3D 0;
 	ctx->sa_out_dma_addr =3D 0;
 	ctx->sa_len =3D 0;
+	ctx->is_gcm =3D 0;
+	ctx->append_icv =3D 0;
=20
 	if (alg->cra_type =3D=3D &crypto_ablkcipher_type)
 		tfm->crt_ablkcipher.reqsize =3D sizeof(struct crypto4xx_ctx);
 	else if (alg->cra_type =3D=3D &crypto_ahash_type)
 		tfm->crt_ahash.reqsize =3D sizeof(struct crypto4xx_ctx);
+	else if (alg->cra_type =3D=3D &crypto_aead_type)
+		tfm->crt_aead.reqsize =3D sizeof(struct crypto4xx_ctx);
=20
 	return 0;
 }
@@ -1105,6 +1312,88 @@ static irqreturn_t =
crypto4xx_ce_interrupt_handler(int irq, void *data)
  * Supported Crypto Algorithms
  */
 struct crypto_alg crypto4xx_alg[] =3D {
+		/* Crypto DES ECB, CBC,  modes */
+
+	{.cra_name 		=3D "cbc(des)",
+	 .cra_driver_name 	=3D "ppc4xx-cbc-des",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D DES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+		.ablkcipher =3D {
+				.min_keysize 	=3D DES_KEY_SIZE,
+				.max_keysize 	=3D DES_KEY_SIZE,
+				.ivsize 	=3D DES_BLOCK_SIZE,
+				.setkey 	=3D crypto4xx_setkey_3des_cbc,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+	{.cra_name 		=3D "ecb(des)",
+	 .cra_driver_name 	=3D "ppc4xx-ecb-des",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D DES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D DES_KEY_SIZE,
+				.max_keysize 	=3D DES_KEY_SIZE,
+				.setkey 	=3D crypto4xx_setkey_3des_ecb,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+
+	/* Crypto 3DES ECB, CBC, CFB, and OFB modes */
+	{.cra_name 		=3D "cbc(des3_ede)",
+	 .cra_driver_name 	=3D "ppc4xx-cbc-3des",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D DES3_EDE_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D DES3_EDE_KEY_SIZE,
+				.max_keysize 	=3D DES3_EDE_KEY_SIZE,
+				.ivsize 	=3D DES3_EDE_BLOCK_SIZE,
+				.setkey 	=3D crypto4xx_setkey_3des_cbc,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+	{.cra_name 		=3D "ecb(des3_ede)",
+	 .cra_driver_name 	=3D "ppc4xx-ecb-3des",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D DES3_EDE_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D DES3_EDE_KEY_SIZE,
+				.max_keysize 	=3D DES3_EDE_KEY_SIZE,
+				.setkey 	=3D crypto4xx_setkey_3des_ecb,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
 	/* Crypto AES modes */
 	{
 		.cra_name 	=3D "cbc(aes)",
@@ -1127,25 +1416,495 @@ struct crypto_alg crypto4xx_alg[] =3D {
 			}
 		}
 	},
-	/* Hash SHA1 */
-	{
-		.cra_name	=3D "sha1",
-		.cra_driver_name =3D "sha1-ppc4xx",
-		.cra_priority	=3D CRYPTO4XX_CRYPTO_PRIORITY,
-		.cra_flags	=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
-		.cra_blocksize	=3D SHA1_BLOCK_SIZE,
-		.cra_ctxsize	=3D sizeof(struct crypto4xx_ctx),
-		.cra_alignmask	=3D 0,
-		.cra_type	=3D &crypto_ahash_type,
-		.cra_init	=3D crypto4xx_sha1_alg_init,
-		.cra_module	=3D THIS_MODULE,
-		.cra_u		=3D {
+	{.cra_name 		=3D "ofb(aes)",
+	 .cra_driver_name 	=3D "ppc4xx-ofb-aes",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize		=3D AES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D AES_MIN_KEY_SIZE,
+				.max_keysize 	=3D AES_MAX_KEY_SIZE,
+				.ivsize 	=3D AES_BLOCK_SIZE,
+				.setkey 	=3D crypto4xx_setkey_aes_ofb,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+	{.cra_name 		=3D "cfb(aes)",
+	 .cra_driver_name 	=3D "ppc4xx-cfb-aes",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize		=3D AES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D AES_MIN_KEY_SIZE,
+				.max_keysize 	=3D AES_MAX_KEY_SIZE,
+				.ivsize 	=3D AES_BLOCK_SIZE,
+				.setkey 	=3D crypto4xx_setkey_aes_cfb,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+	/* Crypto AES ECB, CBC, CTR, GCM, CCM, and GMAC modes */
+	{.cra_name 		=3D "ecb(aes)",
+	 .cra_driver_name 	=3D "ppc4xx-ecb-aes",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D AES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D AES_MIN_KEY_SIZE,
+				.max_keysize 	=3D AES_MAX_KEY_SIZE,
+				.setkey 	=3D crypto4xx_setkey_aes_ecb,
+				.encrypt 	=3D crypto4xx_encrypt,
+				.decrypt 	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+	{.cra_name 		=3D "rfc3686(ctr(aes))",
+	 .cra_driver_name 	=3D "ppc4xx-ctr-aes",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D CTR_RFC3686_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type		=3D &crypto_ablkcipher_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D AES_MIN_KEY_SIZE,
+				.max_keysize 	=3D AES_MAX_KEY_SIZE,
+				.ivsize 	=3D CTR_RFC3686_BLOCK_SIZE,
+				.setkey 	=3D crypto4xx_setkey_aes_ctr,
+				.encrypt 	=3D crypto4xx_encrypt_ctr,
+				.decrypt 	=3D crypto4xx_decrypt_ctr,
+			}
+		}
+	},
+	/* AEAD Algorithms */
+	{.cra_name 		=3D "gcm(aes)",
+	 .cra_driver_name 	=3D "ppc4xx-gcm-aes",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D AES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_aead_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.aead =3D {
+				.maxauthsize	=3D 16,
+				.ivsize 	=3D 12,
+				.setkey 	=3D crypto4xx_setkey_aes_gcm,
+				.setauthsize	=3D crypto4xx_setauthsize_aes,
+				.encrypt 	=3D crypto4xx_encrypt_aes_gcm,
+				.decrypt 	=3D crypto4xx_decrypt_aes_gcm,
+				.givencrypt	=3D crypto4xx_givencrypt_aes_gcm,
+				.givdecrypt	=3D crypto4xx_givdecrypt_aes_gcm,
+			}
+		}
+	},
+	{.cra_name 		=3D "ccm(aes)",
+	 .cra_driver_name 	=3D "ppc4xx-ccm-aes",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D AES_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_aead_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.aead =3D {
+				.ivsize 	=3D AES_BLOCK_SIZE,
+				.maxauthsize	=3D 16,
+				.setkey		=3D crypto4xx_setkey_aes_ccm,
+				.setauthsize	=3D crypto4xx_setauthsize_aes,
+				.encrypt	=3D crypto4xx_encrypt_aes_ccm,
+				.decrypt	=3D crypto4xx_decrypt_aes_ccm,
+				.givencrypt	=3D crypto4xx_givencrypt_aes_ccm,
+				.givdecrypt	=3D crypto4xx_givdecrypt_aes_ccm,
+			}
+		}
+	},
+	/* Hash MD5 */
+	{.cra_name 		=3D "md5",
+	 .cra_driver_name 	=3D "ppc4xx-md5",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D 64,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_init 		=3D crypto4xx_md5_alg_init,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize 	=3D SA_HASH_ALG_MD5_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+			}
+		}
+	},
+	/* Hash MD5-HMAC */
+	{.cra_name 		=3D "hmac(md5)",
+	 .cra_driver_name 	=3D "ppc4xx-hmac-md5",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D 64,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize	=3D SA_HASH_ALG_MD5_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+				.setkey		=3D crypto4xx_md5_hmac_setkey,
+			}
+		}
+	},
+	/* Hash SHA1, SHA2 and HMAC */
+	{.cra_name 		=3D "sha1",
+	 .cra_driver_name 	=3D "ppc4xx-sha1",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA1_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type   		=3D &crypto_ahash_type,
+	 .cra_init 		=3D crypto4xx_sha1_alg_init,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u  		=3D {
+			.ahash =3D {
+				.digestsize	=3D SHA1_DIGEST_SIZE,
+				.init   	=3D crypto4xx_hash_init,
+				.update 	=3D crypto4xx_hash_update,
+				.final  	=3D crypto4xx_hash_final,
+				.digest 	=3D crypto4xx_hash_digest,
+				}
+		}
+	},
+	{.cra_name 		=3D "hmac(sha1)",
+	 .cra_driver_name 	=3D "ppc4xx-hmac-sha1",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA1_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type   		=3D &crypto_ahash_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u  		=3D {
 			.ahash =3D {
 				.digestsize 	=3D SHA1_DIGEST_SIZE,
+				.init   	=3D crypto4xx_hash_init,
+				.update 	=3D crypto4xx_hash_update,
+				.final  	=3D crypto4xx_hash_final,
+				.digest 	=3D crypto4xx_hash_digest,
+				.setkey 	=3D crypto4xx_sha1_hmac_setkey,
+			}
+		}
+	},
+
+	{.cra_name 		=3D "sha224",
+	 .cra_driver_name 	=3D "ppc4xx-sha224",
+	 .cra_priority		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA224_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_init 		=3D crypto4xx_sha2_alg_init,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize	=3D SHA224_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+			}
+		}
+	},
+	{.cra_name 		=3D "hmac(sha224)",
+	 .cra_driver_name 	=3D "ppc4xx-hmac-sha224",
+	 .cra_priority		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA224_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize 	=3D SHA224_DIGEST_SIZE,
+				.init   	=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+				.setkey		=3D crypto4xx_sha2_hmac_setkey,
+			}
+		}
+	},
+	{.cra_name 		=3D "sha256",
+	 .cra_driver_name 	=3D "ppc4xx-sha256",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA256_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_init 		=3D crypto4xx_sha2_alg_init,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize	=3D SHA256_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+			}
+		}
+	},
+	{.cra_name 		=3D "hmac(sha256)",
+	 .cra_driver_name 	=3D "ppc4xx-hmac-sha256",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA256_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize	=3D SHA256_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+				.setkey		=3D crypto4xx_sha2_hmac_setkey,
+			}
+		}
+	},
+	{.cra_name 		=3D "sha384",
+	 .cra_driver_name 	=3D "ppc4xx-sha384",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA384_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_init 		=3D crypto4xx_sha2_alg_init,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize	=3D SHA384_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+			}
+		}
+	},
+	{.cra_name 		=3D "hmac(sha384)",
+	 .cra_driver_name 	=3D "ppc4xx-hmac-sha384",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA384_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize	=3D SHA384_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update 	=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+				.setkey		=3D crypto4xx_sha2_hmac_setkey,
+			}
+		}
+	},
+	{.cra_name 		=3D "sha512",
+	 .cra_driver_name 	=3D "ppc4xx-sha512",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA512_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_init 		=3D crypto4xx_sha2_alg_init,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize 	=3D SHA512_DIGEST_SIZE,
+				.init		=3D crypto4xx_hash_init,
+				.update		=3D crypto4xx_hash_update,
+				.final 		=3D crypto4xx_hash_final,
+				.digest		=3D crypto4xx_hash_digest,
+			}
+		}
+	},
+	{.cra_name 		=3D "hmac(sha512)",
+	 .cra_driver_name 	=3D "ppc4xx-hmac-sha512",
+	 .cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	 .cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	 .cra_blocksize 	=3D SHA512_BLOCK_SIZE,
+	 .cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	 .cra_alignmask 	=3D 0,
+	 .cra_type 		=3D &crypto_ahash_type,
+	 .cra_module 		=3D THIS_MODULE,
+	 .cra_u 		=3D {
+			.ahash =3D {
+				.digestsize 	=3D SHA512_DIGEST_SIZE,
 				.init		=3D crypto4xx_hash_init,
 				.update		=3D crypto4xx_hash_update,
+				.final		=3D crypto4xx_hash_final,
+				.digest 	=3D crypto4xx_hash_digest,
+				.setkey 	=3D crypto4xx_sha2_hmac_setkey,
+			}
+		}
+	},
+	/* Hash XCBC, GHASH, and Kasumi F9 */
+	{.cra_name 		=3D "xcbc(aes)",
+	.cra_driver_name	=3D "ppc4xx-xcbc-aes",
+	.cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	.cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	.cra_blocksize 	=3D AES_BLOCK_SIZE,
+	.cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	.cra_alignmask 	=3D 0,
+	.cra_type 		=3D &crypto_ahash_type,
+	.cra_module 		=3D THIS_MODULE,
+	.cra_u 			=3D {
+			.ahash =3D {
+				.digestsize 	=3D 16,
+				.init   	=3D crypto4xx_hash_init,
+				.update 	=3D crypto4xx_hash_update,
 				.final  	=3D crypto4xx_hash_final,
 				.digest 	=3D crypto4xx_hash_digest,
+				.setkey 	=3D crypto4xx_xcbc_setkey,
+			}
+		}
+	},
+	/* Crypto Kasumi and Kasumi F8 */
+	{.cra_name 		=3D "kasumi",
+	.cra_driver_name 	=3D "ppc4xx-kasumi",
+	.cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	.cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		=3D KASUMI_BLOCK_SIZE,
+	.cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	.cra_alignmask 	=3D 0,
+	.cra_type 		=3D &crypto_ablkcipher_type,
+	.cra_module 		=3D THIS_MODULE,
+	.cra_u 			=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D KASUMI_KEY_SIZE,
+				.max_keysize 	=3D KASUMI_KEY_SIZE,
+				.ivsize 	=3D KASUMI_BLOCK_SIZE,
+				.setkey 	=3D crypto4xx_setkey_kasumi_p,
+				.encrypt	=3D crypto4xx_encrypt,
+				.decrypt	=3D crypto4xx_decrypt,
+			}
+		}
+	},
+	{
+	.cra_name 		=3D "f8(kasumi)",
+	.cra_driver_name 	=3D "ppc4xx-f8-kasumi",
+	.cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	.cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		=3D KASUMI_BLOCK_SIZE,
+	.cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	.cra_alignmask 	=3D 0,
+	.cra_type 		=3D &crypto_ablkcipher_type,
+	.cra_module 		=3D THIS_MODULE,
+	.cra_u 			=3D {
+			.ablkcipher =3D {
+				.min_keysize	=3D KASUMI_KEY_SIZE,
+				.max_keysize	=3D KASUMI_KEY_SIZE,
+				.ivsize		=3D KASUMI_BLOCK_SIZE,
+				.setkey		=3D crypto4xx_setkey_kasumi_f8,
+				.encrypt	=3D crypto4xx_encrypt_kasumi_f8,
+				.decrypt	=3D crypto4xx_decrypt_kasumi_f8,
+			}
+		}
+	},
+	{.cra_name 		=3D "f9(kasumi)",
+	.cra_driver_name 	=3D "ppc4xx-f9-kasumi",
+	.cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	.cra_flags 		=3D CRYPTO_ALG_TYPE_AHASH | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		=3D KASUMI_BLOCK_SIZE,
+	.cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	.cra_alignmask		=3D 0,
+	.cra_type 		=3D &crypto_ahash_type,
+	.cra_module 		=3D THIS_MODULE,
+	.cra_u			=3D {
+			.ahash =3D {
+			.digestsize 	=3D 8,
+			.init   	=3D crypto4xx_hash_init,
+			.update 	=3D crypto4xx_hash_update,
+			.final  	=3D crypto4xx_hash_final,
+			.digest 	=3D crypto4xx_kasumi_f9_digest,
+			.setkey 	=3D crypto4xx_kasumi_f9_setkey,
+			}
+		}
+	},
+	/* Crypto ARC4 - stateless */
+	{.cra_name 		=3D "ecb(arc4)",
+	.cra_driver_name 	=3D "ppc4xx-arc4",
+	.cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	.cra_flags 		=3D CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize 		=3D 1,
+	.cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	.cra_alignmask 		=3D 0,
+	.cra_type 		=3D &crypto_ablkcipher_type,
+	.cra_module 		=3D THIS_MODULE,
+	.cra_u 			=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D 1,
+				.max_keysize 	=3D 16,
+				.setkey 	=3D crypto4xx_setkey_arc4,
+				.encrypt	=3D crypto4xx_arc4_encrypt,
+				.decrypt	=3D crypto4xx_arc4_decrypt,
+			}
+		}
+	},
+	/* Crypto ARC4 - statefull */
+	{.cra_name 		=3D "cbc(arc4)",
+	.cra_driver_name 	=3D "ppc4xx-arc4",
+	.cra_priority 		=3D CRYPTO4XX_CRYPTO_PRIORITY,
+	.cra_flags 		=3D CRYPTO_ALG_TYPE_BLKCIPHER | CRYPTO_ALG_ASYNC,
+	.cra_blocksize		=3D 1,
+	.cra_ctxsize 		=3D sizeof(struct crypto4xx_ctx),
+	.cra_alignmask 		=3D 0,
+	.cra_type		=3D &crypto_ablkcipher_type,
+	.cra_module 		=3D THIS_MODULE,
+	.cra_u 			=3D {
+			.ablkcipher =3D {
+				.min_keysize 	=3D 1,
+				.max_keysize	=3D 16,
+				.setkey		=3D crypto4xx_setkey_arc4,
+				.encrypt 	=3D crypto4xx_arc4_encrypt,
+				.decrypt	=3D crypto4xx_arc4_decrypt,
 			}
 		}
 	},
@@ -1275,7 +2034,6 @@ static int __exit crypto4xx_remove(struct =
of_device *ofdev)
 	crypto4xx_unregister_alg(core_dev->dev);
 	/* Free all allocated memory */
 	crypto4xx_stop_all(core_dev);
-
 	return 0;
 }
=20
diff --git a/drivers/crypto/amcc/crypto4xx_core.h =
b/drivers/crypto/amcc/crypto4xx_core.h
index 1ef1034..f3d04b6 100644
--- a/drivers/crypto/amcc/crypto4xx_core.h
+++ b/drivers/crypto/amcc/crypto4xx_core.h
@@ -116,6 +116,8 @@ struct crypto4xx_ctx {
 	dma_addr_t sa_in_dma_addr;
 	void *sa_out;
 	dma_addr_t sa_out_dma_addr;
+	void *arc4_state_record;
+	dma_addr_t arc4_state_record_dma_addr;
 	void *state_record;
 	dma_addr_t state_record_dma_addr;
 	u32 sa_len;
@@ -125,7 +127,11 @@ struct crypto4xx_ctx {
 	u32 save_iv;
 	u32 pd_ctl_len;
 	u32 pd_ctl;
+	u32 append_icv;
+	u32 is_gcm;
+	u32 ctr_aes;
 	u32 bypass;
+	u32 init_arc4;
 	u32 is_hash;
 	u32 hash_final;
 };
@@ -154,9 +160,12 @@ extern u32 crypto4xx_alloc_sa_rctx(struct =
crypto4xx_ctx *ctx,
 extern void crypto4xx_free_sa_rctx(struct crypto4xx_ctx *rctx);
 extern void crypto4xx_free_ctx(struct crypto4xx_ctx *ctx);
 extern u32 crypto4xx_alloc_state_record(struct crypto4xx_ctx *ctx);
+extern u32 crypto4xx_alloc_arc4_state_record(struct crypto4xx_ctx =
*ctx);
+extern void crypto4xx_free_arc4_state_record(struct crypto4xx_ctx =
*ctx);
 extern u32 get_dynamic_sa_offset_state_ptr_field(struct crypto4xx_ctx =
*ctx);
 extern u32 get_dynamic_sa_offset_key_field(struct crypto4xx_ctx *ctx);
 extern u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx);
+u32 get_dynamic_sa_offset_arc4_state_ptr(struct crypto4xx_ctx *ctx);
 extern void crypto4xx_memcpy_le(unsigned int *dst,
 				const unsigned char *buf, int len);
 extern u32 crypto4xx_build_pd(struct crypto_async_request *req,
@@ -164,9 +173,15 @@ extern u32 crypto4xx_build_pd(struct =
crypto_async_request *req,
 			      struct scatterlist *src,
 			      struct scatterlist *dst,
 			      unsigned int datalen,
+			      struct scatterlist *assoc,
+			      u32 aad_len,
 			      void *iv, u32 iv_len);
 extern int crypto4xx_setkey_aes_cbc(struct crypto_ablkcipher *cipher,
 				    const u8 *key, unsigned int keylen);
+extern int crypto4xx_setkey_3des_cbc(struct crypto_ablkcipher *cipher,
+				     const u8 *key, unsigned int keylen);
+extern int crypto4xx_setkey_3des_ecb(struct crypto_ablkcipher *cipher,
+				     const u8 *key, unsigned int keylen);
 extern int crypto4xx_encrypt(struct ablkcipher_request *req);
 extern int crypto4xx_decrypt(struct ablkcipher_request *req);
 extern int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
@@ -174,4 +189,81 @@ extern int crypto4xx_hash_digest(struct =
ahash_request *req);
 extern int crypto4xx_hash_final(struct ahash_request *req);
 extern int crypto4xx_hash_update(struct ahash_request *req);
 extern int crypto4xx_hash_init(struct ahash_request *req);
+extern int crypto4xx_md5_alg_init(struct crypto_tfm *tfm);
+extern int crypto4xx_hash_hmac_setkey(struct crypto_ahash *hash,
+			       const u8 *key,
+			       unsigned int keylen,
+			       unsigned int sa_len,
+			       unsigned char ha,
+			       unsigned char hm,
+			       unsigned int max_keylen);
+extern int crypto4xx_md5_hmac_setkey(struct crypto_ahash *hash, const =
u8 *key,
+			      unsigned int keylen);
+extern int crypto4xx_sha1_alg_init(struct crypto_tfm *tfm);
+extern int crypto4xx_sha2_alg_init(struct crypto_tfm *tfm);
+extern int crypto4xx_sha2_hmac_setkey(struct crypto_ahash *hash,
+			       const u8 *key,
+			       unsigned int keylen);
+extern int crypto4xx_sha1_hmac_setkey(struct crypto_ahash *hash, const =
u8 *key,
+			       unsigned int keylen);
+extern u32 get_dynamic_sa_offset_inner_digest(struct crypto4xx_ctx =
*ctx);
+extern u32 get_dynamic_sa_offset_outer_digest(struct crypto4xx_ctx =
*ctx);
+extern int crypto4xx_pre_compute_hmac(struct crypto4xx_ctx *ctx,
+			       void *key,
+			       unsigned int keylen,
+			       unsigned int bs,
+			       unsigned char ha,
+			       unsigned char digs);
+int crypto4xx_setkey_aes_ecb(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen);
+int crypto4xx_setkey_aes_ofb(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen);
+int crypto4xx_setkey_aes_cfb(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen);
+int crypto4xx_setkey_aes_ctr(struct crypto_ablkcipher *cipher,
+			     const u8 *key, unsigned int keylen);
+int crypto4xx_setkey_aes_gcm(struct crypto_aead *cipher,
+			     const u8 *key, unsigned int keylen);
+int crypto4xx_setkey_aes_ccm(struct crypto_aead *cipher,
+			     const u8 *key, unsigned int keylen);
+
+int crypto4xx_encrypt_aes_gcm(struct aead_request *req);
+int crypto4xx_decrypt_aes_gcm(struct aead_request *req);
+int crypto4xx_encrypt_aes_ccm(struct aead_request *req);
+int crypto4xx_decrypt_aes_ccm(struct aead_request *req);
+int crypto4xx_encrypt_ctr(struct ablkcipher_request *req);
+int crypto4xx_decrypt_ctr(struct ablkcipher_request *req);
+int crypto4xx_setauthsize_aes(struct crypto_aead *ciper,
+			      unsigned int authsize);
+int crypto4xx_givencrypt_aes_ccm(struct aead_givcrypt_request *req);
+int crypto4xx_givencrypt_aes_gcm(struct aead_givcrypt_request *req);
+int crypto4xx_givdecrypt_aes_ccm(struct aead_givcrypt_request *req);
+int crypto4xx_givdecrypt_aes_gcm(struct aead_givcrypt_request *req);
+int crypto4xx_setkey_kasumi_f8(struct crypto_ablkcipher *cipher,
+			       const u8 *key,
+			       unsigned int keylen);
+
+int crypto4xx_encrypt_kasumi_f8(struct ablkcipher_request *req);
+int crypto4xx_decrypt_kasumi_f8(struct ablkcipher_request *req);
+int crypto4xx_setkey_kasumi_p(struct crypto_ablkcipher *cipher,
+			      const u8 *key,
+			      unsigned int keylen);
+int crypto4xx_kasumi_f9_digest(struct ahash_request *req);
+int crypto4xx_kasumi_f9_setkey(struct crypto_ahash *hash,
+			       const u8 *key, unsigned int keylen);
+int crypto4xx_xcbc_setkey(struct crypto_ahash *hash,
+			  const u8 *key,
+			  unsigned int keylen);
+int crypto4xx_setkey_arc4(struct crypto_ablkcipher *cipher,
+			  const u8 *key, unsigned int keylen);
+int crypto4xx_arc4_decrypt(struct ablkcipher_request *req);
+int crypto4xx_arc4_encrypt(struct ablkcipher_request *req);
+u32 crypto4xx_alloc_arc4_state_record(struct crypto4xx_ctx *ctx);
+int crypto4xx_setauthsize_aes_ccm(struct crypto_aead *ciper,
+				  unsigned int authsize);
+
+/* From crypto/md5.c */
+extern void md5_get_immediate_hash(struct crypto_tfm *tfm, u8 *data);
+extern unsigned int crypto4xx_sa_hash_tbl[3][6];
+
 #endif
diff --git a/drivers/crypto/amcc/crypto4xx_sa.c =
b/drivers/crypto/amcc/crypto4xx_sa.c
index 466fd94..fa4ff7a 100644
--- a/drivers/crypto/amcc/crypto4xx_sa.c
+++ b/drivers/crypto/amcc/crypto4xx_sa.c
@@ -84,6 +84,119 @@ u32 get_dynamic_sa_offset_state_ptr_field(struct =
crypto4xx_ctx *ctx)
 	return sizeof(struct dynamic_sa_ctl) + offset * 4;
 }
=20
+u32 get_dynamic_sa_offset_arc4_state_ptr(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction =3D=3D DIR_INBOUND)
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+	offset =3D cts.bf.key_size
+		+ cts.bf.inner_size
+		+ cts.bf.outer_size
+		+ cts.bf.spi
+		+ cts.bf.seq_num0
+		+ cts.bf.seq_num1
+		+ cts.bf.seq_num_mask0
+		+ cts.bf.seq_num_mask1
+		+ cts.bf.seq_num_mask2
+		+ cts.bf.seq_num_mask3
+		+ cts.bf.iv0
+		+ cts.bf.iv1
+		+ cts.bf.iv2
+		+ cts.bf.iv3
+		+ cts.bf.state_ptr
+		+ cts.bf.arc4_ij_ptr;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_offset_inner_digest(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction =3D=3D DIR_INBOUND)
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+	offset =3D cts.bf.key_size;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_offset_outer_digest(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction =3D=3D DIR_INBOUND)
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+
+	offset =3D cts.bf.key_size
+		+ cts.bf.inner_size;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_offset_spi(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction =3D=3D DIR_INBOUND)
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+
+	offset =3D cts.bf.key_size
+		+ cts.bf.inner_size
+		+ cts.bf.outer_size;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_offset_seq_num(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction =3D=3D DIR_INBOUND)
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+
+	offset =3D cts.bf.key_size
+		+ cts.bf.inner_size
+		+ cts.bf.outer_size
+		+ cts.bf.spi;
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
+u32 get_dynamic_sa_offset_seq_num_mask(struct crypto4xx_ctx *ctx)
+{
+	u32 offset;
+	union dynamic_sa_contents cts;
+
+	if (ctx->direction =3D=3D DIR_INBOUND)
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_in))->sa_contents;
+	else
+		cts.w =3D ((struct dynamic_sa_ctl *)(ctx->sa_out))->sa_contents;
+
+	offset =3D cts.bf.key_size
+		+ cts.bf.inner_size
+		+ cts.bf.outer_size
+		+ cts.bf.spi
+		+ cts.bf.seq_num0
+		+ cts.bf.seq_num1;
+
+	return sizeof(struct dynamic_sa_ctl) + offset * 4;
+}
+
 u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx)
 {
 	union dynamic_sa_contents cts;
@@ -92,6 +205,7 @@ u32 get_dynamic_sa_iv_size(struct crypto4xx_ctx *ctx)
 		cts.w =3D ((struct dynamic_sa_ctl *) ctx->sa_in)->sa_contents;
 	else
 		cts.w =3D ((struct dynamic_sa_ctl *) ctx->sa_out)->sa_contents;
+
 	return (cts.bf.iv0 + cts.bf.iv1 + cts.bf.iv2 + cts.bf.iv3) * 4;
 }
=20
diff --git a/drivers/crypto/amcc/crypto4xx_sa.h =
b/drivers/crypto/amcc/crypto4xx_sa.h
index 4b83ed7..5a1e308 100644
--- a/drivers/crypto/amcc/crypto4xx_sa.h
+++ b/drivers/crypto/amcc/crypto4xx_sa.h
@@ -50,12 +50,42 @@ union dynamic_sa_contents {
 	u32 w;
 } __attribute__((packed));
=20
+#define SA_OPCODE_ESP                   	0
+#define SA_OPCODE_AH                    	1
+#define SA_OPCODE_SSL                   	4
+#define SA_OPCODE_TLS                   	5
+#define SA_OPCODE_SRTP                  	7
+#define SA_OPCODE_DTLS                  	1
+#define SA_OPCODE_TLS1_1                	6
+
+#define SA_OP_GROUP_BASIC               	0
+#define SA_OP_GROUP_PROTOCOL            	1
+#define SA_OP_GROUP_EXTEND_PROTOCOL     	3
+
+#define SA_OPCODE_EXT_PROT_DTLS         	1
+#define SA_OPCODE_EXT_PROT_MACSEC       	2
+#define SA_OPCODE_EXT_PROT_SSL          	4
+#define SA_OPCODE_EXT_PROT_TLS10        	5
+#define SA_OPCODE_EXT_PROT_TLS11        	6
+
 #define DIR_OUTBOUND				0
 #define DIR_INBOUND				1
-#define SA_OP_GROUP_BASIC			0
 #define SA_OPCODE_ENCRYPT			0
 #define SA_OPCODE_DECRYPT			0
+#define SA_OPCODE_ENCRYPT_HASH          	1
+#define SA_OPCODE_HASH_DECRYPT			1
 #define SA_OPCODE_HASH				3
+#define SA_OPCODE_HASH_ENCRYPT          	4
+#define SA_OPCODE_DECRYPT_HASH			4
+
+#define SA_OPCODE_ESP                   	0
+#define SA_OPCODE_AH                    	1
+#define SA_OPCODE_SSL                   	4
+#define SA_OPCODE_TLS                   	5
+#define SA_OPCODE_SRTP                  	7
+#define SA_OPCODE_DTLS                  	1
+#define SA_OPCODE_TLS1_1                	6
+
 #define SA_CIPHER_ALG_DES			0
 #define SA_CIPHER_ALG_3DES			1
 #define SA_CIPHER_ALG_ARC4			2
@@ -65,8 +95,17 @@ union dynamic_sa_contents {
=20
 #define SA_HASH_ALG_MD5				0
 #define SA_HASH_ALG_SHA1			1
+#define SA_HASH_ALG_SHA224              	2
+#define SA_HASH_ALG_SHA256              	3
+#define SA_HASH_ALG_SHA384              	4
+#define SA_HASH_ALG_SHA512              	5
+#define HASH_ALG_MAX_CNT			6
+#define SA_HASH_ALG_AES_XCBC_MAC_128    	8
+#define SA_HASH_ALG_KASUMI_f9           	9
+#define SA_HASH_ALG_GHASH			12
+#define SA_HASH_ALG_GMAC        		13
+#define SA_HASH_ALG_CBC_MAC			14
 #define SA_HASH_ALG_NULL			15
-#define SA_HASH_ALG_SHA1_DIGEST_SIZE		20
=20
 #define SA_LOAD_HASH_FROM_SA			0
 #define SA_LOAD_HASH_FROM_STATE			2
@@ -87,6 +126,16 @@ union dynamic_sa_contents {
 #define SA_HEADER_PROC				1
 #define SA_NO_HEADER_PROC			0
=20
+#define SA_HASH_ALG_MD5_DIGEST_SIZE		16
+#define SA_HASH_ALG_SHA1_DIGEST_SIZE		20
+#define SA_HASH_ALG_SHA224_DIGEST_SIZE		28
+#define SA_HASH_ALG_SHA256_DIGEST_SIZE		32
+#define SA_HASH_ALG_SHA384_DIGEST_SIZE		48
+#define SA_HASH_ALG_SHA512_DIGEST_SIZE		64
+
+
+#define CRYPTO4XX_MAC_ALGS	{ "md5", "sha1", \
+				"sha224", "sha256", "sha384", "sha512" }
 union sa_command_0 {
 	struct {
 		u32 scatter:1;
@@ -111,7 +160,13 @@ union sa_command_0 {
 } __attribute__((packed));
=20
 #define CRYPTO_MODE_ECB				0
+#define CRYPTO_MODE_KASUMI			0
 #define CRYPTO_MODE_CBC				1
+#define CRYPTO_MODE_OFB                  	2
+#define CRYPTO_MODE_CFB                  	3
+#define CRYPTO_MODE_AES_CTR              	4
+#define CRYPTO_MODE_KASUMI_f8            	4
+#define CRYPTO_MODE_AES_ICM              	5
=20
 #define CRYPTO_FEEDBACK_MODE_NO_FB		0
 #define CRYPTO_FEEDBACK_MODE_64BIT_OFB		0
@@ -124,7 +179,7 @@ union sa_command_0 {
 #define SA_AES_KEY_LEN_256			4
=20
 #define SA_REV2					1
-/**
+/*
  * The follow defines bits sa_command_1
  * In Basic hash mode  this bit define simple hash or hmac.
  * In IPsec mode, this bit define muting control.
@@ -177,13 +232,46 @@ struct dynamic_sa_ctl {
 /**
  * State Record for Security Association (SA)
  */
-struct  sa_state_record {
+struct sa_state_record {
 	u32 save_iv[4];
 	u32 save_hash_byte_cnt[2];
 	u32 save_digest[16];
 } __attribute__((packed));
=20
 /**
+ * Arc4 State Record for Security Association (SA)
+ */
+struct arc4_sr {
+	u32 arc4_state[64];
+} __attribute__((packed));
+
+/**
+ * Security Association (SA) for DES
+ */
+struct dynamic_sa_des {
+	struct dynamic_sa_ctl  ctrl;
+	u32 key[2];
+	u32 iv[2];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_DES_LEN		(sizeof(struct dynamic_sa_des)/4)
+#define SA_DES_CONTENTS         0x26000022
+
+/**
+ * Security Association (SA) for 3DES
+ */
+struct dynamic_sa_3des {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[6];
+	u32 iv[2]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_3DES_LEN		(sizeof(struct dynamic_sa_3des)/4)
+#define SA_3DES_CONTENTS        0x26000062
+
+/**
  * Security Association (SA) for AES128
  *
  */
@@ -194,11 +282,10 @@ struct dynamic_sa_aes128 {
 	u32 state_ptr;
 	u32 reserved;
 } __attribute__((packed));
-
 #define SA_AES128_LEN		(sizeof(struct dynamic_sa_aes128)/4)
 #define SA_AES128_CONTENTS	0x3e000042
=20
-/*
+/**
  * Security Association (SA) for AES192
  */
 struct dynamic_sa_aes192 {
@@ -208,7 +295,6 @@ struct dynamic_sa_aes192 {
 	u32 state_ptr;
 	u32 reserved;
 } __attribute__((packed));
-
 #define SA_AES192_LEN		(sizeof(struct dynamic_sa_aes192)/4)
 #define SA_AES192_CONTENTS	0x3e000062
=20
@@ -228,6 +314,19 @@ struct dynamic_sa_aes256 {
 #define SA_AES_CONTENTS		0x3e000002
=20
 /**
+ * Security Association (SA) for HASH128: HMAC-MD5
+ */
+struct dynamic_sa_hash128 {
+	struct dynamic_sa_ctl ctrl;
+	u32 inner_digest[4];
+	u32 outer_digest[4];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_HASH128_LEN		(sizeof(struct dynamic_sa_hash128)/4)
+#define SA_HASH128_CONTENTS     0x20008402
+
+/**
  * Security Association (SA) for HASH160: HMAC-SHA1
  */
 struct dynamic_sa_hash160 {
@@ -240,4 +339,228 @@ struct dynamic_sa_hash160 {
 #define SA_HASH160_LEN		(sizeof(struct dynamic_sa_hash160)/4)
 #define SA_HASH160_CONTENTS     0x2000a502
=20
+/**
+ * Security Association (SA) for HASH256: HMAC-SHA224, HMAC-SHA256
+ */
+struct dynamic_sa_hash256 {
+	struct dynamic_sa_ctl ctrl;
+	u32 inner_digest[8];
+	u32 outer_digest[8];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_HASH256_LEN		(sizeof(struct dynamic_sa_hash256)/4)
+#define SA_HASH256_CONTENTS     0x20010802
+
+/*
+ * Security Association (SA) for HASH512: HMAC-SHA512
+ */
+struct dynamic_sa_hash512 {
+	struct dynamic_sa_ctl ctrl;
+	u32 inner_digest[16];
+	u32 outer_digest[16];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_HASH512_LEN		(sizeof(struct dynamic_sa_hash512)/4)
+#define SA_HASH512_CONTENTS     0x20021002
+
+/**
+ * Security Association (SA) for AES128_XCBC_MAC
+ */
+struct dynamic_sa_aes128_xcbc_mac {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[4];
+	u32 inner_digest[8];
+	u32 outer_digest[8];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES128_XCBC_MAC_LEN	(sizeof(struct =
dynamic_sa_aes128_xcbc_mac)/4)
+#define SA_AES128_XCBC_MAC_CONTENTS     0x3e010842
+
+/**
+ * Security Association (SA) for AES128_GCM
+ */
+struct dynamic_sa_aes128_gcm {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[4];
+	u32 inner_digest[4];
+	u32 outer_digest[4];
+	u32 spi;
+	u32 seq;
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES128_GCM_LEN	(sizeof(struct dynamic_sa_aes128_gcm)/4)
+#define SA_AES128_GCM_CONTENTS          0x3e0c8442
+
+/**
+ * Security Association (SA) for AES192_XCBC_MAC
+ */
+struct dynamic_sa_aes192_xcbc_mac {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[6];
+	u32 inner_digest[8];
+	u32 outer_digest[8];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES192_XCBC_MAC_LEN	(sizeof(struct =
dynamic_sa_aes192_xcbc_mac)/4)
+#define SA_AES192_XCBC_MAC_CONTENTS     0x3e010862
+
+/**
+ * Security Association (SA) for AES192_GCM
+ */
+struct dynamic_sa_aes192_gcm {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[6];
+	u32 inner_digest[4];
+	u32 outer_digest[4];
+	u32 spi;
+	u32 seq;
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES192_GCM_LEN	(sizeof(struct dynamic_sa_aes192_gcm)/4)
+#define SA_AES192_GCM_CONTENTS          0x3e0c8462
+
+
+/**
+ * Security Association (SA) for AES256_XCBC_MAC
+ */
+struct dynamic_sa_aes256_xcbc_mac {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[8];
+	u32 inner_digest[8];
+	u32 outer_digest[8];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES256_XCBC_MAC_LEN	(sizeof(struct =
dynamic_sa_aes256_xcbc_mac)/4)
+#define SA_AES256_XCBC_MAC_CONTENTS     0x3e010882
+
+/**
+ * Security Association (SA) for AES256_GCM
+ */
+struct dynamic_sa_aes256_gcm {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[8];
+	u32 inner_digest[4];
+	u32 outer_digest[4];
+	u32 spi;
+	u32 seq;
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES256_GCM_LEN	(sizeof(struct dynamic_sa_aes256_gcm)/4)
+#define SA_AES256_GCM_CONTENTS          0x3e0c8482
+#define SA_AES_GCM_CONTENTS          0x3e0c8402
+
+/**
+ * Security Association (SA) for Kasumi
+ */
+struct dynamic_sa_kasumi {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[4];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_KASUMI_LEN		(sizeof(struct dynamic_sa_kasumi)/4)
+#define SA_KASUMI_CONTENTS              0x20000042
+
+/**
+ * Security Association (SA) for Kasumi f8
+ */
+struct dynamic_sa_kasumi_f8 {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[4];
+	u32 iv[2];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_KASUMI_F8_LEN	(sizeof(struct dynamic_sa_kasumi_f8)/4)
+#define SA_KASUMI_F8_CONTENTS           0x26000042
+
+#define KASUMI_BLOCK_SIZE 8
+#define KASUMI_KEY_SIZE   16
+
+/**
+ * Security Association (SA) for Kasumi f8
+ */
+struct dynamic_sa_kasumi_f9 {
+	struct dynamic_sa_ctl ctrl;
+	u32 inner_digest[4];
+	u32 outter_digest[3];
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_KASUMI_F9_LEN	(sizeof(struct dynamic_sa_kasumi_f9)/4)
+#define SA_KASUMI_F9_CONTENTS           0x20006402
+
+/**
+ * Security Association (SA) for AES256 CCM
+ */
+struct dynamic_sa_aes256_ccm {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[8];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES256_CCM_LEN	(sizeof(struct dynamic_sa_aes256_ccm)/4)
+#define SA_AES256_CCM_CONTENTS      0x3e000082
+#define SA_AES_CCM_CONTENTS      0x3e000002
+
+/**
+ * Security Association (SA) for AES192 CCM
+ */
+struct dynamic_sa_aes192_ccm {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[6];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES192_CCM_LEN           (sizeof(struct =
dynamic_sa_aes192_ccm)/4)
+#define SA_AES192_CCM_CONTENTS      0x3e000062
+
+/**
+ * Security Association (SA) for AES128 CCM
+ */
+struct dynamic_sa_aes128_ccm {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[4];
+	u32 iv[4]; /* for CBC, OFC, and CFB mode */
+	u32 state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_AES128_CCM_LEN	(sizeof(struct dynamic_sa_aes128_ccm)/4)
+#define SA_AES128_CCM_CONTENTS      0x3e000042
+
+/**
+ * Security Association (SA) for ARC4
+ */
+struct arc4_ij_ptr {
+	u32 rsv:16;
+	u32 j:8;
+	u32 i:8;
+} __attribute__((packed));
+
+struct dynamic_sa_arc4 {
+	struct dynamic_sa_ctl ctrl;
+	u32 key[4];
+	struct arc4_ij_ptr ij;
+	u32 arc4_state_ptr;
+	u32 reserved;
+} __attribute__((packed));
+#define SA_ARC4_LEN		(sizeof(struct dynamic_sa_arc4)/4)
+#define SA_ARC4_CONTENTS        0xc0000042
+
 #endif
diff --git a/include/crypto/sha.h b/include/crypto/sha.h
index c0ccc2b..8894c2f 100644
--- a/include/crypto/sha.h
+++ b/include/crypto/sha.h
@@ -62,4 +62,11 @@
 #define SHA512_H6	0x1f83d9abfb41bd6bULL
 #define SHA512_H7	0x5be0cd19137e2179ULL
=20
+/* From crypto/sha1_generic.c */
+void sha1_get_immediate_hash(struct crypto_tfm *tfm, u8 *data);
+/* From crypto/sha256_generic.c */
+void sha256_get_immediate_hash(struct crypto_tfm *tfm, u8 *data);
+/* From crypto/sha512_generic.c */
+void sha512_get_immediate_hash(struct crypto_tfm *tfm, u8 *data);
+
 #endif
--=20
1.5.5

^ permalink raw reply related

* Re: [BUILD FAILURE 01/04] Next June 04:PPC64 randconfig [drivers/staging/comedi/drivers.o]
From: Benjamin Herrenschmidt @ 2009-06-09 22:34 UTC (permalink / raw)
  To: subrata
  Cc: sachinp, sfr, fmhess, Greg KH, linux-kernel, Linuxppc-dev,
	Ian Abbott, linux-next, paulus, Geert.Uytterhoeven, geert,
	David Miller
In-Reply-To: <1244572446.5497.32.camel@subratamodak.linux.ibm.com>


> > In any case, doing PAGE_KERNEL_NOCACHE for DMA memory is incorrect on
> > many architectures. So at this stage, there's no much option but ifdef I
> > suspect for now until this is fixed properly.
> 
> Ok. But, i am not sure whether Greg will agree to this. If, Ok, is the
> following patch i sent earlier Ok ?
> 
> http://lkml.org/lkml/2009/6/5/462,

Not really.

You probably want to use a constant (call it MY_DMA_MAP_PGPROT), and
in a header, you have a bunch of ifdef's that set it to PAGE_KERNEL,
PAGE_KERNEL_NOCACHE or PAGE_KERNEL_NC depending on what's needed.

Today, you can pretty much assume that

 - x86*, sparc*, ia64*, alpha, ... needs PAGE_KERNEL
 - powerpc needs PAGE_KERNEL if !CONFIG_NOT_COHERENT_CACHE
 - powerpc needs PAGE_KERNEL_NC if CONFIG_NOT_COHERENT_CACHE
 - ARM and MIPS, I think, needs PAGE_KERNEL_NOCACHE
 - ... others I don't know.

Cheers,
Ben.

> Regards--
> Subrata
> 
> > 
> > It does make sense to want to have some memory like that shared between
> > user space and DMA, though I don't know what the right approach that
> > works on all archs is at this stage. Worth asking the Alsa guys, I think
> > they have similar issues :-)
> > 
> > But doing double buffering might do the trick fine for now.
> > 
> > Cheers,
> > Ben.
> > 
> > 
> > 
> > 

^ permalink raw reply

* [PATCH] of_serial: Add UPF_FIXED_TYPE flag
From: Dave Mitchell @ 2009-06-09 23:39 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: arnd

This patch adds the UPF_FIXED_TYPE flag which will bypass the
8250's autoconfig probe for uart type. The uart type identified
by the of_serial's parse of the flat device tree will be utilized
as defined.

Signed-off-by: Dave Mitchell <dmitchell@amcc.com>
---
 drivers/serial/of_serial.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/serial/of_serial.c b/drivers/serial/of_serial.c
index 14f8fa9..3f2027c 100644
--- a/drivers/serial/of_serial.c
+++ b/drivers/serial/of_serial.c
@@ -67,7 +67,7 @@ static int __devinit of_platform_serial_setup(struct of_device *ofdev,
 	port->type = type;
 	port->uartclk = *clk;
 	port->flags = UPF_SHARE_IRQ | UPF_BOOT_AUTOCONF | UPF_IOREMAP
-		| UPF_FIXED_PORT;
+		| UPF_FIXED_PORT | UPF_FIXED_TYPE;
 	port->dev = &ofdev->dev;
 	/* If current-speed was set, then try not to change it. */
 	if (spd)
-- 
1.6.3.2

^ permalink raw reply related

* Re: [PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages
From: Michael Ellerman @ 2009-06-10  0:02 UTC (permalink / raw)
  To: Hannes Hering
  Cc: rdreier, alexs, linux-kernel, ewg, linuxppc-dev, raisch, ossrosch
In-Reply-To: <200906091559.24661.hannes.hering@linux.vnet.ibm.com>

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

On Tue, 2009-06-09 at 15:59 +0200, Hannes Hering wrote:
> This patch implements toleration of dynamic memory operations and 16 GB
> gigantic pages. On module load the driver walks through available system
> memory, checks for available memory ranges and then registers the kernel
> internal memory region accordingly. The translation of address ranges is
> implemented via a 3-level busmap.

Hi Hannes,

For those of us who haven't read the HEA spec lately, can you give us
some more detail on that? :)

How does it interact with kexec/kdump?

> +static int ehca_update_busmap(unsigned long pfn, unsigned long nr_pages)
> +{
> +	unsigned long i, start_section, end_section;
> +	int top, dir, idx;
> +
> +	if (!nr_pages)
> +		return 0;
> +
> +	if (!ehca_bmap) {
> +		ehca_bmap = kmalloc(sizeof(struct ehca_bmap), GFP_KERNEL);
> +		if (!ehca_bmap)
> +			return -ENOMEM;
> +		/* Set map block to 0xFF according to EHCA_INVAL_ADDR */
> +		memset(ehca_bmap, 0xFF, EHCA_TOP_MAP_SIZE);
> +	}
> +
> +	start_section = phys_to_abs(pfn * PAGE_SIZE) / EHCA_SECTSIZE;
> +	end_section = phys_to_abs((pfn + nr_pages) * PAGE_SIZE) / EHCA_SECTSIZE;


phys_to_abs() ? As below, or does it come from somewhere else?

 arch/powerpc/include/asm/abs_addr.h:
 47 static inline unsigned long phys_to_abs(unsigned long pa)                   
 48 {
 49         unsigned long chunk;
 50 
 51         /* This is a no-op on non-iSeries */
 52         if (!firmware_has_feature(FW_FEATURE_ISERIES))
 53                 return pa;
 54 
 55         chunk = addr_to_chunk(pa);
 56 
 57         if (chunk < mschunks_map.num_chunks)
 58                 chunk = mschunks_map.mapping[chunk];
 59 
 60         return chunk_to_addr(chunk) + (pa & MSCHUNKS_OFFSET_MASK);
 61 }


cheers

[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 197 bytes --]

^ permalink raw reply

* Re: [BUILD FAILURE 02/04] Next June 04:PPC64 randconfig [drivers/usb/host/ohci-hcd.o]
From: David Brownell @ 2009-06-10  0:38 UTC (permalink / raw)
  To: Subrata Modak, Arnd Bergmann
  Cc: Sachin P Sant, Randy Dunlap, Stephen Rothwell, linux-usb,
	Linux-Kernel, Linuxppc-dev, Linux-Next, kernel
In-Reply-To: <20090605182651.24094.36577.sendpatchset@elm3a191.beaverton.ibm.com>

On Friday 05 June 2009, Subrata Modak wrote:
> Correct, it fixes the issue. However, since few changes might have gone
> to the Kconfig, the patch does not apply cleanly. Below is the patch, just
> a retake of the earlier one, but on the latest code. 

And it got mangled a bit along the way.  Plus, the original one
goofed up Kconfig dependency displays ... both issues fixed in
this version, against current mainline GIT.

If someone can verify all four PPC/OF/OHCI configs build on
on PPC64, I'm OK with it.

- Dave


========== CUT HERE
From: Arnd Bergmann <arnd@arndb.de>
Subject: fix build failure for PPC64 randconfig [usb/ohci]

We could just make the USB_OHCI_HCD_PPC_OF option implicit
and selected only if at least one of USB_OHCI_HCD_PPC_OF_BE
and USB_OHCI_HCD_PPC_OF_LE are set.

[ dbrownell@users.sourceforge.net: fix patch manglation and dependencies ]

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Resent-by: Subrata Modak <subrata@linux.vnet.ibm.com>
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
---
 drivers/usb/host/Kconfig |   29 +++++++++++++++--------------
 1 file changed, 15 insertions(+), 14 deletions(-)

--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -180,26 +180,27 @@ config USB_OHCI_HCD_PPC_SOC
 	  Enables support for the USB controller on the MPC52xx or
 	  STB03xxx processor chip.  If unsure, say Y.
 
-config USB_OHCI_HCD_PPC_OF
-	bool "OHCI support for PPC USB controller on OF platform bus"
-	depends on USB_OHCI_HCD && PPC_OF
-	default y
-	---help---
-	  Enables support for the USB controller PowerPC present on the
-	  OpenFirmware platform bus.
-
 config USB_OHCI_HCD_PPC_OF_BE
-	bool "Support big endian HC"
-	depends on USB_OHCI_HCD_PPC_OF
-	default y
+	bool "OHCI support for OF platform bus (big endian)"
+	depends on USB_OHCI_HCD && PPC_OF
 	select USB_OHCI_BIG_ENDIAN_DESC
 	select USB_OHCI_BIG_ENDIAN_MMIO
+	---help---
+	  Enables support for big-endian USB controllers present on the
+	  OpenFirmware platform bus.
 
 config USB_OHCI_HCD_PPC_OF_LE
-	bool "Support little endian HC"
-	depends on USB_OHCI_HCD_PPC_OF
-	default n
+	bool "OHCI support for OF platform bus (little endian)"
+	depends on USB_OHCI_HCD && PPC_OF
 	select USB_OHCI_LITTLE_ENDIAN
+	---help---
+	  Enables support for little-endian USB controllers present on the
+	  OpenFirmware platform bus.
+
+config USB_OHCI_HCD_PPC_OF
+	bool
+	depends on USB_OHCI_HCD && PPC_OF
+	default USB_OHCI_HCD_PPC_OF_BE || USB_OHCI_HCD_PPC_OF_LE
 
 config USB_OHCI_HCD_PCI
 	bool "OHCI support for PCI-bus USB controllers"

^ permalink raw reply

* "next" branch update
From: Benjamin Herrenschmidt @ 2009-06-10  3:14 UTC (permalink / raw)
  To: linuxppc-dev list

Hi !

I've updated my "next" branch with the following patches. We're getting
real close to the merge window now, so if something is missing, please
holler ASAP.

Cheers,
Ben.

Becky Bruce (1):
      powerpc: Add support for swiotlb on 32-bit

Benjamin Herrenschmidt (8):
      powerpc/mm: Fix some SMP issues with MMU context handling
      powerpc/mm: Fix a AB->BA deadlock scenario with nohash MMU context lock
      powerpc: Set init_bootmem_done on NUMA platforms as well
      powerpc: Move VMX and VSX asm code to vector.S
      powerpc: Introduce CONFIG_PPC_BOOK3S
      powerpc: Split exception handling out of head_64.S
      powerpc: Separate PACA fields for server CPUs
      powerpc: Shield code specific to 64-bit server processors

Grant Likely (1):
      powerpc/virtex: refactor intc driver and add support for i8259 cascading

John Linn (1):
      fbdev: Add PLB support and cleanup DCR in xilinxfb driver.

Roderick Colenbrander (3):
      powerpc/virtex: Add support for Xilinx PCI host bridge
      powerpc/virtex: Add Xilinx ML510 reference design support
      powerpc/virtex: Add ml510 reference design device tree

Roland McGrath (1):
      powerpc: Add PTRACE_SINGLEBLOCK support

Stephen Rothwell (4):
      powerpc/pseries: Fix warnings when printing resource_size_t
      powerpc/xmon: Remove unused variable in xmon.c
      powerpc: Fix warning when printing a resource_size_t
      powerpc/spufs: Remove unused error path

^ permalink raw reply

* Re: "next" branch update
From: Grant Likely @ 2009-06-10  4:13 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1244603678.2431.18.camel@pasglop>

On Tue, Jun 9, 2009 at 9:14 PM, Benjamin Herrenschmidt
<benh@kernel.crashing.org> wrote:
>
> Hi !
>
> I've updated my "next" branch with the following patches. We're getting
> real close to the merge window now, so if something is missing, please
> holler ASAP.

Just these two; but I see you've got them marked "under review":

http://patchwork.ozlabs.org/patch/28191/
http://patchwork.ozlabs.org/patch/27752/

g.

--
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.

^ permalink raw reply

* Re: "next" branch update
From: Timur Tabi @ 2009-06-10  6:07 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev list
In-Reply-To: <1244603678.2431.18.camel@pasglop>

On Tue, Jun 9, 2009 at 10:14 PM, Benjamin
Herrenschmidt<benh@kernel.crashing.org> wrote:
> Hi !
>
> I've updated my "next" branch with the following patches. We're getting
> real close to the merge window now, so if something is missing, please
> holler ASAP.

[PATCH 1/2 v9] powerpc: introduce macro spin_event_timeout()

-- 
Timur Tabi
Linux kernel developer at Freescale

^ permalink raw reply

* Re: [Patch 2/6] Introduce PPC64 specific Hardware Breakpoint interfaces
From: K.Prasad @ 2009-06-10  6:43 UTC (permalink / raw)
  To: David Gibson
  Cc: Michael Neuling, Benjamin Herrenschmidt, linuxppc-dev, paulus,
	Alan Stern, Roland McGrath
In-Reply-To: <20090605051158.GJ2054@yookeroo.seuss>

On Fri, Jun 05, 2009 at 03:11:58PM +1000, David Gibson wrote:
> On Wed, Jun 03, 2009 at 10:05:11PM +0530, K.Prasad wrote:

Hi David,
	Sorry for the delay in response below. In the meanwhile, I
discovered an issue in detecting stray exceptions that affected
user-space handling of breakpoints. I've made some changes to correct
that behaviour which will be included in version VI of the patchset.

> > Introduce PPC64 implementation for the generic hardware breakpoint interfaces
> > defined in kernel/hw_breakpoint.c. Enable the HAVE_HW_BREAKPOINT flag and the
> > Makefile.
> 
> 
> [snip]
> > +/*
> > + * Install the debug register values for just the kernel, no thread.
> 
> This comment does seem to quite match the function below.
> 

Thanks for pointing out. Will change it to read thus:
/*
 * Clear the DABR which contains the thread-specific breakpoint address
 */

> > + */
> > +void arch_uninstall_thread_hw_breakpoint()
> > +{
> > +	set_dabr(0);
> > +}
> > +
> > +/*
> > + * Store a breakpoint's encoded address, length, and type.
> > + */
> > +int arch_store_info(struct hw_breakpoint *bp, struct task_struct *tsk)
> > +{
> > +	/*
> > +	 * User-space requests will always have the address field populated
> > +	* Symbol names from user-space are rejected
> > +	*/
> > +	if (tsk && bp->info.name)
> > +		return -EINVAL;
> > +	/*
> > +	 * User-space requests will always have the address field populated
> > +	 * For kernel-addresses, either the address or symbol name can be
> > +	 * specified.
> > +	 */
> > +	if (bp->info.name)
> > +		bp->info.address = (unsigned long)
> > +					kallsyms_lookup_name(bp->info.name);
> 
> Archs don't have to implement this name lookup stuff, but it looks
> like most of them would - so it looks like there ought to be a helper
> function in generic code that will do the check / name lookup stuff.
> 
>

It doesn't turn out to be very generic. The IO breakpoints in x86, the
address-range (only) breakpoints in S390 and perhaps 4xx powerpc
processors were what made me think that this should remain in
arch-specific code. In these cases, we might have to deal only with
breakpoint addresses and not names.

> > +	if (bp->info.address)
> > +		return 0;
> 
> Hrm.. you realise there's no theoretical reason a userspace program
> couldn't put a breakpoint at address 0...?
> 

I agree. I think there must be parts of code that works based on this
assumption. Will check and remove them.

> > +	return -EINVAL;
> > +}
> > +
> > +/*
> > + * Validate the arch-specific HW Breakpoint register settings
> > + */
> > +int arch_validate_hwbkpt_settings(struct hw_breakpoint *bp,
> > +						struct task_struct *tsk)
> > +{
> > +	int is_kernel, ret = -EINVAL;
> > +
> > +	if (!bp)
> > +		return ret;
> > +
> > +	switch (bp->info.type) {
> > +	case HW_BREAKPOINT_READ:
> > +	case HW_BREAKPOINT_WRITE:
> > +	case HW_BREAKPOINT_RW:
> > +		break;
> > +	default:
> > +		return ret;
> > +	}
> > +
> > +	if (bp->triggered)
> > +		ret = arch_store_info(bp, tsk);
> > +
> > +	is_kernel = is_kernel_addr(bp->info.address);
> > +	if ((tsk && is_kernel) || (!tsk && !is_kernel))
> > +		return -EINVAL;
> > +
> > +	return ret;
> > +}
> > +
> > +void arch_update_user_hw_breakpoint(int pos, struct task_struct *tsk)
> > +{
> > +	struct thread_struct *thread = &(tsk->thread);
> > +	struct hw_breakpoint *bp = thread->hbp[0];
> > +
> > +	if (bp)
> > +		thread->dabr = (bp->info.address & ~HW_BREAKPOINT_ALIGN) |
> > +				bp->info.type | DABR_TRANSLATION;
> > +	else
> > +		thread->dabr = 0;
> > +}
> > +
> > +void arch_flush_thread_hw_breakpoint(struct task_struct *tsk)
> > +{
> > +	struct thread_struct *thread = &(tsk->thread);
> > +
> > +	thread->dabr = 0;
> > +}
> > +
> > +/*
> > + * Handle debug exception notifications.
> > + */
> > +int __kprobes hw_breakpoint_handler(struct die_args *args)
> > +{
> > +	int rc = NOTIFY_STOP;
> > +	struct hw_breakpoint *bp;
> > +	struct pt_regs *regs = args->regs;
> > +	unsigned long dar = regs->dar;
> > +	int cpu, is_one_shot, stepped = 1;
> > +
> > +	/* Disable breakpoints during exception handling */
> > +	set_dabr(0);
> > +
> > +	cpu = get_cpu();
> > +	/* Determine whether kernel- or user-space address is the trigger */
> > +	bp = (hbp_kernel_pos == HBP_NUM) ? current->thread.hbp[0] :
> > +					per_cpu(this_hbp_kernel[0], cpu);
> > +	/*
> > +	 * bp can be NULL due to lazy debug register switching
> > +	 * or due to the delay between updates of hbp_kernel_pos
> > +	 * and this_hbp_kernel.
> > +	 */
> > +	if (!bp)
> > +		goto out;
> > +
> > +	if (dar == bp->info.address)
> > +		per_cpu(dabr_data, cpu) = (hbp_kernel_pos == HBP_NUM) ?
> > +						current->thread.dabr : kdabr;
> > +	else {
> > +		/*
> > +		 * This exception is triggered not because of a memory access on
> > +		 * the monitored variable but in the double-word address range
> > +		 * in which it is contained. We will consume this exception,
> > +		 * considering it as 'noise'.
> > +		 */
> > +		rc = NOTIFY_STOP;
> > +		goto out;
> > +	}
> > +	is_one_shot = (bp->triggered == ptrace_triggered) ? 1 : 0;
> 
> Ouch, explicitly special-casing ptrace_triggered is pretty nasty.
> Since the bp_info is already arch specific, maybe it should include a
> flag to indicate whether the breakpoint is one-shot or not.
> 

The reason to check for ptrace_triggered is to contain the one-shot
behaviour only to ptrace (thus retaining the semantics) and not to extend
them to all user-space requests through register_user_hw_breakpoint().

A one-shot behaviour for all user-space requests would create more work
for the user-space programs (such as re-registration) and will leave open
a small window of opportunity for debug register grabbing by kernel-space
requests.

So, in effect a request through register_user_hw_breakpoint() interface
will behave as under:
- Single-step over the causative instruction that triggered the
  breakpoint exception handler.
- Deliver the SIGTRAP signal to user-space after executing the causative
  instruction.

This behaviour is in consonance with that of kernel-space requests and
those on x86 processors, and helps define a consistent behaviour across
architectures for user-space.

Let me know what you think on the same.

> > +	(bp->triggered)(bp, regs);
> > +	/*
> > +	 * Ptrace expects the HW Breakpoints to be one-shot. We will return
> > +	 * NOTIFY_DONE without restoring DABR with the breakpoint address. The
> > +	 * downstream code will generate SIGTRAP to the process
> > +	 */
> > +	if (is_one_shot) {
> > +		rc = NOTIFY_DONE;
> > +		goto out;
> 
> Don't you need to clear dabr_data?  Otherwise if we enter single step
> for some other reason (e.g. gdb turns it on), won't we incorrectly hit
> the code-path to step over a dabr breakpoint?
> 

Yes, I missed it.

> > +	}
> > +
> > +	stepped = emulate_step(regs, regs->nip);
> > +	/*
> > +	 * Single-step the causative instruction manually if
> > +	 * emulate_step() could not execute it
> > +	 */
> > +	if (stepped == 0) {
> > +		regs->msr |= MSR_SE;
> > +		goto out;
> > +	}
> > +	set_dabr(per_cpu(dabr_data, cpu));
> > +	per_cpu(dabr_data, cpu) = 0;
> > +
> > +out:
> > +	/* Enable pre-emption only if single-stepping is finished */
> > +	if (stepped)
> > +		put_cpu_no_resched();
> > +	return rc;
> > +}
> > +
> > +/*
> > + * Handle single-step exceptions following a DABR hit.
> > + */
> > +int __kprobes single_step_dabr_instruction(struct die_args *args)
> > +{
> > +	struct pt_regs *regs = args->regs;
> > +	int cpu = get_cpu();
> > +	int ret = NOTIFY_DONE;
> > +	siginfo_t info;
> > +	unsigned long this_dabr_data = per_cpu(dabr_data, cpu);
> > +
> > +	/*
> > +	 * Check if we are single-stepping as a result of a
> > +	 * previous HW Breakpoint exception
> > +	 */
> > +	if (this_dabr_data == 0)
> > +		goto out;
> > +
> > +	regs->msr &= ~MSR_SE;
> > +	/* Deliver signal to user-space */
> > +	if (this_dabr_data < TASK_SIZE) {
> > +		info.si_signo = SIGTRAP;
> > +		info.si_errno = 0;
> > +		info.si_code = TRAP_HWBKPT;
> > +		info.si_addr = (void __user *)(per_cpu(dabr_data, cpu));
> > +		force_sig_info(SIGTRAP, &info, current);
> 
> Uh.. I recall mentioning in my previous review that in order to match
> previous behaviour we need to deliver the userspace signal *before*
> stepping over the breakpointed instruction, rather than after (which
> I guess is why breakpoints are one-shot in the old scheme).
> 

This code would implement the behaviour as stated in the comment for
user-space requests above.

> > _______________________________________________
> > Linuxppc-dev mailing list
> > Linuxppc-dev@ozlabs.org
> > https://ozlabs.org/mailman/listinfo/linuxppc-dev
> > 
> 
> -- 
> David Gibson			| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson

Thanks,
K.Prasad

^ permalink raw reply

* [PATCH] powerpc: Add configurable -Werror for arch/powerpc
From: Michael Ellerman @ 2009-06-10  6:48 UTC (permalink / raw)
  To: linuxppc-dev

Add the option to build the code under arch/powerpc with -Werror.

The intention is to make it harder for people to inadvertantly introduce
warnings in the arch/powerpc code. It needs to be configurable so that
if a warning is introduced, people can easily work around it while it's
being fixed.

The option is a negative, ie. don't enable -Werror, so that it will be
turned on for allyes and allmodconfig builds.

The default is n, in the hope that developers will build with -Werror,
that will probably lead to some build breaks, I am prepared to be flamed.

It's not enabled for math-emu, which is a steaming pile of warnings.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/Kconfig.debug      |   17 +++++++++++++++++
 arch/powerpc/kernel/Makefile    |    2 ++
 arch/powerpc/kvm/Makefile       |    2 ++
 arch/powerpc/lib/Makefile       |    2 ++
 arch/powerpc/mm/Makefile        |    2 ++
 arch/powerpc/oprofile/Makefile  |    2 ++
 arch/powerpc/platforms/Makefile |    2 ++
 arch/powerpc/sysdev/Makefile    |    2 ++
 arch/powerpc/xmon/Makefile      |    2 ++
 9 files changed, 33 insertions(+), 0 deletions(-)

diff --git a/arch/powerpc/Kconfig.debug b/arch/powerpc/Kconfig.debug
index d79a902..3b10051 100644
--- a/arch/powerpc/Kconfig.debug
+++ b/arch/powerpc/Kconfig.debug
@@ -2,6 +2,23 @@ menu "Kernel hacking"
 
 source "lib/Kconfig.debug"
 
+config PPC_DISABLE_WERROR
+	bool "Don't build arch/powerpc code with -Werror"
+	default n
+	help
+	  This option tells the compiler NOT to build the code under
+	  arch/powerpc with the -Werror flag (which means warnings
+	  are treated as errors).
+
+	  Only enable this if you are hitting a build failure in the
+	  arch/powerpc code caused by a warning, and you don't feel
+	  inclined to fix it.
+
+config PPC_WERROR
+	bool
+	depends on !PPC_DISABLE_WERROR
+	default y
+
 config PRINT_STACK_DEPTH
 	int "Stack depth to print" if DEBUG_KERNEL
 	default 64
diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile
index 65cf365..110ec6d 100644
--- a/arch/powerpc/kernel/Makefile
+++ b/arch/powerpc/kernel/Makefile
@@ -4,6 +4,8 @@
 
 CFLAGS_ptrace.o		+= -DUTS_MACHINE='"$(UTS_MACHINE)"'
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 CFLAGS_prom_init.o	+= -mno-minimal-toc
 endif
diff --git a/arch/powerpc/kvm/Makefile b/arch/powerpc/kvm/Makefile
index 4b2df66..459c7ee 100644
--- a/arch/powerpc/kvm/Makefile
+++ b/arch/powerpc/kvm/Makefile
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module
 #
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 EXTRA_CFLAGS += -Ivirt/kvm -Iarch/powerpc/kvm
 
 common-objs-y = $(addprefix ../../../virt/kvm/, kvm_main.o coalesced_mmio.o)
diff --git a/arch/powerpc/lib/Makefile b/arch/powerpc/lib/Makefile
index 29b742b..3040dac 100644
--- a/arch/powerpc/lib/Makefile
+++ b/arch/powerpc/lib/Makefile
@@ -2,6 +2,8 @@
 # Makefile for ppc-specific library files..
 #
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS		+= -mno-minimal-toc
 endif
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile
index c4bcf07..2d2192e 100644
--- a/arch/powerpc/mm/Makefile
+++ b/arch/powerpc/mm/Makefile
@@ -2,6 +2,8 @@
 # Makefile for the linux ppc-specific parts of the memory manager.
 #
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS	+= -mno-minimal-toc
 endif
diff --git a/arch/powerpc/oprofile/Makefile b/arch/powerpc/oprofile/Makefile
index 2ef6b0d..73e1c2c 100644
--- a/arch/powerpc/oprofile/Makefile
+++ b/arch/powerpc/oprofile/Makefile
@@ -1,3 +1,5 @@
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS	+= -mno-minimal-toc
 endif
diff --git a/arch/powerpc/platforms/Makefile b/arch/powerpc/platforms/Makefile
index f741919..a6812ee 100644
--- a/arch/powerpc/platforms/Makefile
+++ b/arch/powerpc/platforms/Makefile
@@ -1,4 +1,6 @@
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 obj-$(CONFIG_FSL_ULI1575)	+= fsl_uli1575.o
 
 obj-$(CONFIG_PPC_PMAC)		+= powermac/
diff --git a/arch/powerpc/sysdev/Makefile b/arch/powerpc/sysdev/Makefile
index 2d1c87d..d073bfd 100644
--- a/arch/powerpc/sysdev/Makefile
+++ b/arch/powerpc/sysdev/Makefile
@@ -1,3 +1,5 @@
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifeq ($(CONFIG_PPC64),y)
 EXTRA_CFLAGS			+= -mno-minimal-toc
 endif
diff --git a/arch/powerpc/xmon/Makefile b/arch/powerpc/xmon/Makefile
index 9cb03b7..85ab97a 100644
--- a/arch/powerpc/xmon/Makefile
+++ b/arch/powerpc/xmon/Makefile
@@ -1,5 +1,7 @@
 # Makefile for xmon
 
+subdir-ccflags-$(CONFIG_PPC_WERROR) := -Werror
+
 ifdef CONFIG_PPC64
 EXTRA_CFLAGS += -mno-minimal-toc
 endif
-- 
1.6.2.1

^ permalink raw reply related

* Re: [Patch 3/6] Modify ptrace code to use Hardware Breakpoint interfaces
From: K.Prasad @ 2009-06-10  6:50 UTC (permalink / raw)
  To: David Gibson
  Cc: Michael Neuling, Benjamin Herrenschmidt, linuxppc-dev, paulus,
	Alan Stern, Roland McGrath
In-Reply-To: <20090605051345.GK2054@yookeroo.seuss>

On Fri, Jun 05, 2009 at 03:13:45PM +1000, David Gibson wrote:
> On Wed, Jun 03, 2009 at 10:05:24PM +0530, K.Prasad wrote:
> > Modify the ptrace code to use the hardware breakpoint interfaces for user-space.
> > 
> > Signed-off-by: K.Prasad <prasad@linux.vnet.ibm.com>
> > ---
> >  arch/powerpc/kernel/ptrace.c |   47 +++++++++++++++++++++++++++++++++++++++++++
> >  1 file changed, 47 insertions(+)
> > 
> > Index: linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
> > ===================================================================
> > --- linux-2.6-tip.hbkpt.orig/arch/powerpc/kernel/ptrace.c
> > +++ linux-2.6-tip.hbkpt/arch/powerpc/kernel/ptrace.c
> > @@ -37,6 +37,7 @@
> >  #include <asm/page.h>
> >  #include <asm/pgtable.h>
> >  #include <asm/system.h>
> > +#include <asm/hw_breakpoint.h>
> >  
> >  /*
> >   * does not yet catch signals sent when the child dies.
> > @@ -735,9 +736,26 @@ void user_disable_single_step(struct tas
> >  	clear_tsk_thread_flag(task, TIF_SINGLESTEP);
> >  }
> >  
> > +void ptrace_triggered(struct hw_breakpoint *bp, struct pt_regs *regs)
> > +{
> > +	/*
> > +	 * Unregister the breakpoint request here since ptrace has defined a
> > +	 * one-shot behaviour for breakpoint exceptions in PPC64.
> > +	 * The SIGTRAP signal is generated automatically for us in do_dabr().
> > +	 * We don't have to do anything here
> > +	 */
> > +	unregister_user_hw_breakpoint(current, bp);
> > +	kfree(bp);
> 
> Couldn't you also clear the saved dabr info here, to avoid having to
> special case this in the actual breakpoint handler.
> 

The saved dabr_data is created as a static variable and I didn't want to
modify its value across files.

> Also, I think you should be delivering the signal here - for gdb
> compatibility I think we'll need to match the old behaviour which has
> the TRAP delivered before executing the breakpointed instruction.
> 

We could do it either way. Return a NOTIFY_DONE from
hw_breakpoint_handler() and allow the do_dabr()
code to deliver the signal, or deliver a signal here and return a
NOTIFY_STOP in the exception handler. I chose the former as it doesn't
duplicate the code.

> -- 
> David Gibson			| I'll have my music baroque, and my code
> david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
> 				| _way_ _around_!
> http://www.ozlabs.org/~dgibson

Thanks,
K.Prasad

^ permalink raw reply

* [PATCH] powerpc: Don't do generic calibrate_delay()
From: Benjamin Herrenschmidt @ 2009-06-10  7:12 UTC (permalink / raw)
  To: linuxppc-dev

Currently we are wasting time calling the generic calibrate_delay()
function. We don't need it since our implementation of __delay() is
based on the CPU timebase. So instead, we use our own small
implementation that initializes loops_per_jiffy to something sensible
to make the few users like spinlock debug be happy

Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---

 arch/powerpc/Kconfig       |    4 ----
 arch/powerpc/kernel/time.c |   10 ++++++++++
 2 files changed, 10 insertions(+), 4 deletions(-)

--- linux-work.orig/arch/powerpc/Kconfig	2009-06-10 16:09:35.000000000 +1000
+++ linux-work/arch/powerpc/Kconfig	2009-06-10 16:13:00.000000000 +1000
@@ -93,10 +93,6 @@ config GENERIC_HWEIGHT
 	bool
 	default y
 
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
 config GENERIC_FIND_NEXT_BIT
 	bool
 	default y
Index: linux-work/arch/powerpc/kernel/time.c
===================================================================
--- linux-work.orig/arch/powerpc/kernel/time.c	2009-06-10 16:09:35.000000000 +1000
+++ linux-work/arch/powerpc/kernel/time.c	2009-06-10 16:13:00.000000000 +1000
@@ -52,6 +52,7 @@
 #include <linux/jiffies.h>
 #include <linux/posix-timers.h>
 #include <linux/irq.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/processor.h>
@@ -1143,6 +1144,15 @@ void div128_by_32(u64 dividend_high, u64
 
 }
 
+/* We don't need to calibrate delay, we use the CPU timebase for that */
+void calibrate_delay(void)
+{
+	/* Some generic code (such as spinlock debug) use loops_per_jiffy
+	 * as the number of __delay(1) in a jiffy, so make it so
+	 */
+	loops_per_jiffy = tb_ticks_per_jiffy;
+}
+
 static int __init rtc_init(void)
 {
 	struct platform_device *pdev;

^ permalink raw reply

* Re: [PATCH 2.6.31] ehca: Tolerate dynamic memory operations and huge pages
From: Hannes Hering @ 2009-06-10  8:54 UTC (permalink / raw)
  To: michael; +Cc: rdreier, alexs, linux-kernel, ewg, linuxppc-dev, raisch, ossrosch
In-Reply-To: <1244592156.4680.5.camel@concordia>

Hi Michael,

On Wednesday 10 June 2009 02:02:36 Michael Ellerman wrote:
> For those of us who haven't read the HEA spec lately, can you give us
> some more detail on that? :)
first of all, please note that this patch is actually for the ehca infiniband
driver. The ehca driver uses an internal memory region, which is supposed to
contain all physical memory. A memory region maps a virtually contiguous
adapter address space to the physical or better absolute address space. The
limitation is that the memory region cannot map non-contiguous virtual adapter
address space. However, on ppc64 machines there is a feature to dynamically add
or remove memory to logical partitions during runtime. These operations scatter
the absolute memory so that the kernel memory has a non-contiguous layout. This
layout cannot be represented in a memory region. The purpose of this code is to
detect the memory layout so that the memory region can be made up of the
existing memory chunks. It also translates the kernel addresses to the memory
region address, which is needed for interaction with the HCA.
> How does it interact with kexec/kdump?
We never tested the ehca driver with kexec/kdump. This patch also doesn't
improve anything in this context.

> phys_to_abs() ? As below, or does it come from somewhere else?
You're right, actually that isn't needed on System p. On the other hand I
needed to choose an address type, which is the base of all mapping. The
"busmap" holds all addresses as absolute addresses. The absolute addresses can
then be converted in any other type (virt, phys). 

Regards

Hannes

^ permalink raw reply

* [Patch 0/6] PPC64-HWBKPT: Hardware Breakpoint interfaces - ver VI
From: K.Prasad @ 2009-06-10  9:07 UTC (permalink / raw)
  To: David Gibson, linuxppc-dev
  Cc: paulus, Michael Neuling, Benjamin Herrenschmidt, Alan Stern,
	Roland McGrath

Hi David,
	Please find a new set of patches that implement the changes described below.

Changelog - ver VI
-------------------
(Ver I: http://ozlabs.org/pipermail/linuxppc-dev/2009-May/071942.html) 
(Ver II: http://ozlabs.org/pipermail/linuxppc-dev/2009-May/072106.html)
(Ver III: http://ozlabs.org/pipermail/linuxppc-dev/2009-May/072387.html
(Ver IV: http://ozlabs.org/pipermail/linuxppc-dev/2009-May/072518.html
(Ver V: http://lists.ozlabs.org/pipermail/linuxppc-dev/2009-June/072749.html)
9th June June 2009
-------------------

Changelog - ver VI
------------------
The task of identifying 'genuine' breakpoint exceptions from those caused by
'out-of-range' accesses turned out to be more tricky than originally thought.
Some changes to this effect were made in version IV of this patchset, but they
were not sufficient for user-space. Basically the breakpoint address received
through ptrace is always aligned to 8-bytes since ptrace receives an encoded
'data' (consisting of address | translation_enable | bkpt_type), and the size of
the symbol is not known. However for kernel-space addresses, the symbol-size can
be determined using kallsyms_lookup_size_offset() and this is used to check if
DAR (in the exception context) is
'bkpt_address <= DAR <= (bkpt_address + symbol_size)', failing which we conclude
it as a stray exception.

The following changes are made to enable check:
- Addition of a symbolsize field in 'struct arch_hw_breakpoint' field.
- Store the size of the 'watched' kernel symbol into 'symbolsize' field in
  arch_store_info(0 routine.
- Verify if the above described condition is true when is_one_shot is FALSE in
  hw_breakpoint_handler().

Kindly let me know your comments on the same.

Thanks,
K.Prasad

^ 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